TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
44 / 44
100.0%
Branches:
43 / 45
95.6%
Functions:
7 / 7
100.0%

distribution/spliced.cpp
Line Branch Exec Source
1 #include "terraingen/distribution/spliced.h"
2
3 #include "terraingen/distribution/combined.h"
4
5 #include <cmath>
6 #include <stdexcept>
7 #include <utility>
8
9 namespace terraingen {
10
11 namespace {
12
13 /// The kind of `pieces`, after checking there is one and that they share it.
14 764 SfdKind CheckedKind(const std::vector<SfdPiece>& pieces) {
15 764 std::vector<const SizeFrequencyDistribution*> distributions;
16
2/2
✓ Branch 4 taken 1523 times.
✓ Branch 5 taken 764 times.
2287 for (const SfdPiece& piece : pieces) {
17
1/1
✓ Branch 2 taken 1523 times.
1523 distributions.push_back(piece.distribution.get());
18 }
19
2/2
✓ Branch 1 taken 764 times.
✓ Branch 5 taken 760 times.
1528 return detail::CommonKind(distributions, "A spliced distribution");
20 764 }
21
22 /// Whether `distribution` may be evaluated from `low` to `high` metres.
23 1515 bool Covers(const SizeFrequencyDistribution& distribution, double low, double high) {
24
1/1
✓ Branch 1 taken 1515 times.
1515 const DiameterRange usable = detail::UsableRange(distribution);
25
3/4
✓ Branch 0 taken 1515 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1514 times.
✓ Branch 3 taken 1 time.
3030 return usable.min <= low && usable.max >= high;
26 }
27
28 } // namespace
29
30 764 SplicedSfd::SplicedSfd(std::vector<SfdPiece> pieces, DiameterRange range, double tolerance)
31 764 : SizeFrequencyDistribution(CheckedKind(pieces), range), pieces_(std::move(pieces)) {
32
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 759 times.
760 if (pieces_.front().start != range.min) {
33
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("The first piece must start at the range minimum");
34 }
35
2/2
✓ Branch 1 taken 1517 times.
✓ Branch 2 taken 754 times.
2271 for (std::size_t i = 0; i < pieces_.size(); ++i) {
36 1517 const SfdPiece& piece = pieces_[i];
37
2/2
✓ Branch 1 taken 758 times.
✓ Branch 2 taken 759 times.
1517 const double end = i + 1 < pieces_.size() ? pieces_[i + 1].start : range.max;
38
7/8
✓ Branch 0 taken 758 times.
✓ Branch 1 taken 759 times.
✓ Branch 3 taken 758 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 757 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1515 times.
2274 if (i > 0 && !(std::isfinite(piece.start) && piece.start > pieces_[i - 1].start &&
39
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 756 times.
757 piece.start < range.max)) {
40
1/1
✓ Branch 2 taken 2 times.
2 throw std::invalid_argument("Piece starts must increase within the range");
41 }
42
3/3
✓ Branch 2 taken 1515 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1514 times.
1515 if (!Covers(*piece.distribution, piece.start, end)) {
43
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("Each piece must be valid over its diameter interval");
44 }
45
2/2
✓ Branch 0 taken 755 times.
✓ Branch 1 taken 759 times.
1514 if (i > 0) {
46
3/3
✓ Branch 1 taken 755 times.
✓ Branch 6 taken 755 times.
✓ Branch 9 taken 753 times.
755 detail::CheckJoin(CumulativeOf(*pieces_[i - 1].distribution, piece.start),
47 755 CumulativeOf(*piece.distribution, piece.start), piece.start,
48 tolerance, false);
49 }
50 }
51 766 }
52
53 7863851 std::size_t SplicedSfd::PieceAt(double diameter) const {
54 7863851 return detail::IndexOfStart(pieces_, diameter);
55 }
56
57 6786539 double SplicedSfd::CumulativeAt(double diameter) const {
58 6786539 return CumulativeOf(*pieces_[PieceAt(diameter)].distribution, diameter);
59 }
60
61 1017112 double SplicedSfd::IncrementalAt(double diameter) const {
62 1017112 return IncrementalOf(*pieces_[PieceAt(diameter)].distribution, diameter);
63 }
64
65 60200 double SplicedSfd::InvertCumulative(double target, double dMin, double dMax) const {
66 60200 std::size_t index = PieceAt(dMin);
67
2/2
✓ Branch 1 taken 60150 times.
✓ Branch 2 taken 5871 times.
66021 while (index + 1 < pieces_.size()) {
68 60150 const double high = std::fmin(dMax, pieces_[index + 1].start);
69
2/2
✓ Branch 3 taken 54329 times.
✓ Branch 4 taken 5821 times.
60150 if (target >= CumulativeOf(*pieces_[index].distribution, high)) {
70 54329 break;
71 }
72 5821 ++index;
73 }
74 60200 const SizeFrequencyDistribution& piece = *pieces_[index].distribution;
75 60200 const double low = std::fmax(dMin, pieces_[index].start);
76 const double high =
77
2/2
✓ Branch 1 taken 54329 times.
✓ Branch 2 taken 5871 times.
60200 index + 1 < pieces_.size() ? std::fmin(dMax, pieces_[index + 1].start) : dMax;
78
2/2
✓ Branch 1 taken 522 times.
✓ Branch 2 taken 59678 times.
60200 if (target >= CumulativeOf(piece, low)) {
79 522 return low;
80 }
81 59678 return InvertCumulativeOf(piece, target, low, high);
82 }
83
84 } // namespace terraingen
85