distribution/summed.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "terraingen/distribution/summed.h" | ||
| 2 | |||
| 3 | #include "terraingen/distribution/combined.h" | ||
| 4 | #include "terraingen/util/checks.h" | ||
| 5 | |||
| 6 | #include <cmath> | ||
| 7 | #include <stdexcept> | ||
| 8 | #include <utility> | ||
| 9 | |||
| 10 | namespace terraingen { | ||
| 11 | |||
| 12 | namespace { | ||
| 13 | |||
| 14 | /// The kind of `terms`, after checking them. | ||
| 15 | 605 | SfdKind CheckedKind(const std::vector<WeightedSfd>& terms) { | |
| 16 | 605 | std::vector<const SizeFrequencyDistribution*> distributions; | |
| 17 | 1347 | for (const WeightedSfd& term : terms) { | |
| 18 | 742 | distributions.push_back(term.distribution.get()); | |
| 19 | } | ||
| 20 | 608 | const SfdKind kind = detail::CommonKind(distributions, "A summed distribution"); | |
| 21 | 1340 | for (const WeightedSfd& term : terms) { | |
| 22 | 739 | RequirePositive(term.weight, "Summed distribution weights"); | |
| 23 | } | ||
| 24 | 601 | return kind; | |
| 25 | 605 | } | |
| 26 | |||
| 27 | /// Where every term may be evaluated, after checking the terms. | ||
| 28 | 305 | DiameterRange Overlap(const std::vector<WeightedSfd>& terms) { | |
| 29 | 305 | CheckedKind(terms); | |
| 30 | 301 | DiameterRange range; | |
| 31 | 671 | for (const WeightedSfd& term : terms) { | |
| 32 | 370 | const DiameterRange usable = detail::UsableRange(*term.distribution); | |
| 33 | 370 | range.min = std::fmax(range.min, usable.min); | |
| 34 | 370 | range.max = std::fmin(range.max, usable.max); | |
| 35 | } | ||
| 36 | 301 | if (!(range.min < range.max)) { | |
| 37 | 1 | throw std::invalid_argument("Summed terms must have overlapping valid ranges"); | |
| 38 | } | ||
| 39 | 300 | return range; | |
| 40 | } | ||
| 41 | |||
| 42 | } // namespace | ||
| 43 | |||
| 44 | 305 | SummedSfd::SummedSfd(std::vector<WeightedSfd> terms) | |
| 45 | 305 | : SizeFrequencyDistribution(CheckedKind(terms), Overlap(terms)), terms_(std::move(terms)) {} | |
| 46 | |||
| 47 | 10712641 | double SummedSfd::CumulativeAt(double diameter) const { | |
| 48 | 10712641 | double sum = 0.0; | |
| 49 | 27361593 | for (const WeightedSfd& term : terms_) { | |
| 50 | 16648952 | sum += term.weight * CumulativeOf(*term.distribution, diameter); | |
| 51 | } | ||
| 52 | 10712641 | return sum; | |
| 53 | } | ||
| 54 | |||
| 55 | 807123 | double SummedSfd::IncrementalAt(double diameter) const { | |
| 56 | 807123 | double sum = 0.0; | |
| 57 | 2218660 | for (const WeightedSfd& term : terms_) { | |
| 58 | 1411537 | sum += term.weight * IncrementalOf(*term.distribution, diameter); | |
| 59 | } | ||
| 60 | 807123 | return sum; | |
| 61 | } | ||
| 62 | |||
| 63 | } // namespace terraingen | ||
| 64 |