TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
32 / 32
100.0%
Branches:
31 / 31
100.0%
Functions:
6 / 6
100.0%

distribution/log_polynomial.cpp
Line Branch Exec Source
1 #include "terraingen/distribution/log_polynomial.h"
2
3 #include "terraingen/util/checks.h"
4
5 #include <algorithm>
6 #include <cmath>
7 #include <stdexcept>
8 #include <utility>
9
10 namespace terraingen {
11
12 810 LogPolynomialSfd::LogPolynomialSfd(std::vector<double> coefficients, DiameterRange range,
13 810 SfdKind kind, double diameterUnit, double areaUnit)
14 810 : SizeFrequencyDistribution(kind, range), coefficients_(std::move(coefficients)),
15 810 diameterUnit_(diameterUnit), areaUnit_(areaUnit) {
16
7/7
✓ Branch 1 taken 809 times.
✓ Branch 2 taken 1 time.
✓ Branch 6 taken 809 times.
✓ Branch 8 taken 1 time.
✓ Branch 9 taken 808 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 808 times.
810 if (coefficients_.empty() || !std::all_of(coefficients_.begin(), coefficients_.end(),
17 9589 [](double value) { return std::isfinite(value); })) {
18
1/1
✓ Branch 2 taken 2 times.
2 throw std::invalid_argument("A log polynomial needs finite coefficients");
19 }
20
6/6
✓ Branch 1 taken 807 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 806 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 806 times.
808 if (!IsPositive(diameterUnit_) || !IsPositive(areaUnit_)) {
21
1/1
✓ Branch 2 taken 2 times.
2 throw std::invalid_argument("Diameter and area units must be positive and finite");
22 }
23
6/6
✓ Branch 0 taken 805 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 804 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 804 times.
806 if (!(range.min > 0.0 && std::isfinite(range.max))) {
24 throw std::invalid_argument(
25
1/1
✓ Branch 2 taken 2 times.
2 "A log polynomial needs a finite range with a positive minimum");
26 }
27 804 constexpr int kSamples = 4096;
28 804 const double low = std::log10(range.min / diameterUnit_);
29 804 const double high = std::log10(range.max / diameterUnit_);
30
2/2
✓ Branch 0 taken 3285796 times.
✓ Branch 1 taken 802 times.
3286598 for (int i = 0; i <= kSamples; ++i) {
31
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3285794 times.
3285796 if (Derivative(low + (high - low) * i / kSamples) > 0.0) {
32
1/1
✓ Branch 2 taken 2 times.
2 throw std::invalid_argument("A cumulative distribution cannot increase with diameter");
33 }
34 }
35 818 }
36
37 6774404 double LogPolynomialSfd::Polynomial(double x) const {
38 6774404 double sum = 0.0;
39
2/2
✓ Branch 3 taken 81288887 times.
✓ Branch 4 taken 6774404 times.
88063291 for (auto it = coefficients_.rbegin(); it != coefficients_.rend(); ++it) {
40 81288887 sum = sum * x + *it;
41 }
42 6774404 return sum;
43 }
44
45 4019357 double LogPolynomialSfd::Derivative(double x) const {
46 4019357 double sum = 0.0;
47
2/2
✓ Branch 1 taken 44008018 times.
✓ Branch 2 taken 4019357 times.
48027375 for (std::size_t i = coefficients_.size() - 1; i > 0; --i) {
48 44008018 sum = sum * x + static_cast<double>(i) * coefficients_[i];
49 }
50 4019357 return sum;
51 }
52
53 6774404 double LogPolynomialSfd::CumulativeAt(double diameter) const {
54 6774404 return std::pow(10.0, Polynomial(std::log10(diameter / diameterUnit_))) / areaUnit_;
55 }
56
57 733561 double LogPolynomialSfd::IncrementalAt(double diameter) const {
58 733561 return -CumulativeAt(diameter) * Derivative(std::log10(diameter / diameterUnit_)) / diameter;
59 }
60
61 } // namespace terraingen
62