| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | // | ||
| 4 | /// @file Stats.h | ||
| 5 | /// | ||
| 6 | /// @author Ken Museth | ||
| 7 | /// | ||
| 8 | /// @brief Classes to compute statistics and histograms | ||
| 9 | |||
| 10 | #ifndef OPENVDB_MATH_STATS_HAS_BEEN_INCLUDED | ||
| 11 | #define OPENVDB_MATH_STATS_HAS_BEEN_INCLUDED | ||
| 12 | |||
| 13 | #include <iosfwd> // for ostringstream | ||
| 14 | #include <openvdb/version.h> | ||
| 15 | #include <openvdb/Exceptions.h> | ||
| 16 | #include <iostream> | ||
| 17 | #include <iomanip> | ||
| 18 | #include <sstream> | ||
| 19 | #include <vector> | ||
| 20 | #include <functional>// for std::less | ||
| 21 | #include "Math.h" | ||
| 22 | |||
| 23 | namespace openvdb { | ||
| 24 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 25 | namespace OPENVDB_VERSION_NAME { | ||
| 26 | namespace math { | ||
| 27 | |||
| 28 | /// @brief Templated class to compute the minimum and maximum values. | ||
| 29 | template <typename ValueType, typename Less = std::less<ValueType> > | ||
| 30 | class MinMax | ||
| 31 | { | ||
| 32 | using Limits = std::numeric_limits<ValueType>; | ||
| 33 | public: | ||
| 34 | |||
| 35 | /// @brief Empty constructor | ||
| 36 | /// | ||
| 37 | /// @warning Only use this constructor with POD types | ||
| 38 | 4 | MinMax() : mMin(Limits::max()), mMax(Limits::lowest()) | |
| 39 | { | ||
| 40 | static_assert(std::numeric_limits<ValueType>::is_specialized, | ||
| 41 | "openvdb::math::MinMax default constructor requires a std::numeric_limits specialization"); | ||
| 42 | } | ||
| 43 | |||
| 44 | /// @brief Constructor | ||
| 45 |
0/7✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
55 | MinMax(const ValueType &min, const ValueType &max) : mMin(min), mMax(max) |
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | /// @brief Default copy constructor | ||
| 50 | MinMax(const MinMax &other) = default; | ||
| 51 | |||
| 52 | /// Add a single sample. | ||
| 53 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | inline void add(const ValueType &val, const Less &less = Less()) |
| 54 | { | ||
| 55 |
9/18✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
|
11 | if (less(val, mMin)) mMin = val; |
| 56 |
8/16✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
10 | if (less(mMax, val)) mMax = val; |
| 57 | 3 | } | |
| 58 | |||
| 59 | /// Return the minimum value. | ||
| 60 | inline const ValueType& min() const { return mMin; } | ||
| 61 | |||
| 62 | /// Return the maximum value. | ||
| 63 | inline const ValueType& max() const { return mMax; } | ||
| 64 | |||
| 65 | /// Add the samples from the other Stats instance. | ||
| 66 | inline void add(const MinMax& other, const Less &less = Less()) | ||
| 67 | { | ||
| 68 | if (less(other.mMin, mMin)) mMin = other.mMin; | ||
| 69 | if (less(mMax, other.mMax)) mMax = other.mMax; | ||
| 70 | } | ||
| 71 | |||
| 72 | /// @brief Print MinMax to the specified output stream. | ||
| 73 | void print(const std::string &name= "", std::ostream &strm=std::cout, int precision=3) const | ||
| 74 | { | ||
| 75 | // Write to a temporary string stream so as not to affect the state | ||
| 76 | // (precision, field width, etc.) of the output stream. | ||
| 77 | std::ostringstream os; | ||
| 78 | os << std::setprecision(precision) << std::setiosflags(std::ios::fixed); | ||
| 79 | os << "MinMax "; | ||
| 80 | if (!name.empty()) os << "for \"" << name << "\" "; | ||
| 81 | os << " Min=" << mMin << ", Max=" << mMax << std::endl; | ||
| 82 | strm << os.str(); | ||
| 83 | } | ||
| 84 | |||
| 85 | protected: | ||
| 86 | |||
| 87 | ValueType mMin, mMax; | ||
| 88 | };//end MinMax | ||
| 89 | |||
| 90 | /// @brief This class computes the minimum and maximum values of a population | ||
| 91 | /// of floating-point values. | ||
| 92 | class Extrema | ||
| 93 | { | ||
| 94 | public: | ||
| 95 | |||
| 96 | /// @brief Constructor | ||
| 97 | /// @warning The min/max values are initiated to extreme values | ||
| 98 | Extrema() | ||
| 99 | 9 | : mSize(0) | |
| 100 | , mMin(std::numeric_limits<double>::max()) | ||
| 101 |
7/12✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
|
20 | , mMax(-mMin) |
| 102 | { | ||
| 103 | } | ||
| 104 | |||
| 105 | /// Add a single sample. | ||
| 106 | void add(double val) | ||
| 107 | { | ||
| 108 |
9/16✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
|
1127223 | ++mSize; |
| 109 |
22/32✓ Branch 0 taken 411618 times.
✓ Branch 1 taken 608498 times.
✓ Branch 2 taken 262771 times.
✓ Branch 3 taken 511453 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 138629 times.
✓ Branch 7 taken 542031 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 4499456 times.
✓ Branch 10 taken 138629 times.
✓ Branch 11 taken 542031 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4499456 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 340330 times.
✓ Branch 16 taken 4 times.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 1 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 6 times.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 13 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
|
12494935 | mMin = std::min<double>(val, mMin); |
| 110 |
15/18✓ Branch 0 taken 190429 times.
✓ Branch 1 taken 829687 times.
✓ Branch 2 taken 106690 times.
✓ Branch 3 taken 681551 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 642680 times.
✓ Branch 7 taken 37980 times.
✓ Branch 8 taken 4422656 times.
✓ Branch 9 taken 76800 times.
✓ Branch 10 taken 642680 times.
✓ Branch 11 taken 37980 times.
✓ Branch 12 taken 4422656 times.
✓ Branch 13 taken 76800 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 340330 times.
✓ Branch 18 taken 35089528 times.
✓ Branch 19 taken 8553628 times.
|
66565901 | mMax = std::max<double>(val, mMax); |
| 111 | } | ||
| 112 | |||
| 113 | /// Add @a n samples with constant value @a val. | ||
| 114 | void add(double val, uint64_t n) | ||
| 115 | { | ||
| 116 | 174350 | mSize += n; | |
| 117 |
5/8✓ Branch 0 taken 22610 times.
✓ Branch 1 taken 42853 times.
✓ Branch 2 taken 2197 times.
✓ Branch 3 taken 43453 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4394 times.
|
115507 | mMin = std::min<double>(val, mMin); |
| 118 |
6/10✓ Branch 0 taken 373 times.
✓ Branch 1 taken 65090 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 45650 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4394 times.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 58837 times.
|
174724 | mMax = std::max<double>(val, mMax); |
| 119 | } | ||
| 120 | |||
| 121 | /// Return the size of the population, i.e., the total number of samples. | ||
| 122 | 22 | inline uint64_t size() const { return mSize; } | |
| 123 | |||
| 124 | /// Return the minimum value. | ||
| 125 |
16/32✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 2 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 2 times.
✗ Branch 47 not taken.
|
53 | inline double min() const { return mMin; } |
| 126 | |||
| 127 | /// Return the maximum value. | ||
| 128 |
16/32✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 2 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 2 times.
✗ Branch 47 not taken.
|
53 | inline double max() const { return mMax; } |
| 129 | |||
| 130 | /// Return the range defined as the maximum value minus the minimum value. | ||
| 131 | 4 | inline double range() const { return mMax - mMin; } | |
| 132 | |||
| 133 | /// Add the samples from the other Stats instance. | ||
| 134 | void add(const Extrema& other) | ||
| 135 | { | ||
| 136 |
7/16✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 9 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 9 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
|
50 | if (other.mSize > 0) this->join(other); |
| 137 | } | ||
| 138 | |||
| 139 | /// @brief Print extrema to the specified output stream. | ||
| 140 | void print(const std::string &name= "", std::ostream &strm=std::cout, int precision=3) const | ||
| 141 | { | ||
| 142 | // Write to a temporary string stream so as not to affect the state | ||
| 143 | // (precision, field width, etc.) of the output stream. | ||
| 144 | std::ostringstream os; | ||
| 145 | os << std::setprecision(precision) << std::setiosflags(std::ios::fixed); | ||
| 146 | os << "Extrema "; | ||
| 147 | if (!name.empty()) os << "for \"" << name << "\" "; | ||
| 148 | if (mSize>0) { | ||
| 149 | os << "with " << mSize << " samples:\n" | ||
| 150 | << " Min=" << mMin | ||
| 151 | << ", Max=" << mMax | ||
| 152 | << ", Range="<< this->range() << std::endl; | ||
| 153 | } else { | ||
| 154 | os << ": no samples were added." << std::endl; | ||
| 155 | } | ||
| 156 | strm << os.str(); | ||
| 157 | } | ||
| 158 | |||
| 159 | protected: | ||
| 160 | |||
| 161 | 110 | inline void join(const Extrema& other) | |
| 162 | { | ||
| 163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
|
110 | assert(other.mSize > 0); |
| 164 | 110 | mSize += other.mSize; | |
| 165 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 106 times.
|
110 | mMin = std::min<double>(mMin, other.mMin); |
| 166 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 99 times.
|
110 | mMax = std::max<double>(mMax, other.mMax); |
| 167 | 110 | } | |
| 168 | |||
| 169 | uint64_t mSize; | ||
| 170 | double mMin, mMax; | ||
| 171 | };//end Extrema | ||
| 172 | |||
| 173 | |||
| 174 | /// @brief This class computes statistics (minimum value, maximum | ||
| 175 | /// value, mean, variance and standard deviation) of a population | ||
| 176 | /// of floating-point values. | ||
| 177 | /// | ||
| 178 | /// @details variance = Mean[ (X-Mean[X])^2 ] = Mean[X^2] - Mean[X]^2, | ||
| 179 | /// standard deviation = sqrt(variance) | ||
| 180 | /// | ||
| 181 | /// @note This class employs incremental computation and double precision. | ||
| 182 | class Stats : public Extrema | ||
| 183 | { | ||
| 184 | public: | ||
| 185 | Stats() | ||
| 186 | 37 | : Extrema() | |
| 187 | , mAvg(0.0) | ||
| 188 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
23 | , mAux(0.0) |
| 189 | { | ||
| 190 | } | ||
| 191 | |||
| 192 | /// Add a single sample. | ||
| 193 |
2/2✓ Branch 0 taken 8977414 times.
✓ Branch 1 taken 34679764 times.
|
43657178 | void add(double val) |
| 194 | { | ||
| 195 | 43657178 | Extrema::add(val); | |
| 196 | 43657178 | const double delta = val - mAvg; | |
| 197 | 43657178 | mAvg += delta/double(mSize); | |
| 198 | 43657178 | mAux += delta*(val - mAvg); | |
| 199 | 43657178 | } | |
| 200 | |||
| 201 | /// Add @a n samples with constant value @a val. | ||
| 202 | 58841 | void add(double val, uint64_t n) | |
| 203 | { | ||
| 204 | 58841 | const double denom = 1.0/double(mSize + n); | |
| 205 | 58841 | const double delta = val - mAvg; | |
| 206 | 58841 | mAvg += denom * delta * double(n); | |
| 207 |
2/2✓ Branch 0 taken 4396 times.
✓ Branch 1 taken 54445 times.
|
58841 | mAux += denom * delta * delta * double(mSize) * double(n); |
| 208 | 58841 | Extrema::add(val, n); | |
| 209 | 58841 | } | |
| 210 | |||
| 211 | /// Add the samples from the other Stats instance. | ||
| 212 | 62 | void add(const Stats& other) | |
| 213 | { | ||
| 214 |
2/2✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1 times.
|
62 | if (other.mSize > 0) { |
| 215 | 61 | const double denom = 1.0/double(mSize + other.mSize); | |
| 216 | 61 | const double delta = other.mAvg - mAvg; | |
| 217 | 61 | mAvg += denom * delta * double(other.mSize); | |
| 218 | 61 | mAux += other.mAux + denom * delta * delta * double(mSize) * double(other.mSize); | |
| 219 | 61 | Extrema::join(other); | |
| 220 | } | ||
| 221 | 62 | } | |
| 222 | |||
| 223 | //@{ | ||
| 224 | /// Return the arithmetic mean, i.e. average, value. | ||
| 225 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | inline double avg() const { return mAvg; } |
| 226 |
5/10✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
|
26 | inline double mean() const { return mAvg; } |
| 227 | //@} | ||
| 228 | |||
| 229 | //@{ | ||
| 230 | /// @brief Return the population variance. | ||
| 231 | /// @note The unbiased sample variance = population variance * | ||
| 232 | //num/(num-1) | ||
| 233 |
39/78✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 2 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 1 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✗ Branch 43 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 1 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 1 times.
✗ Branch 54 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 57 taken 1 times.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 62 not taken.
✓ Branch 63 taken 1 times.
✗ Branch 64 not taken.
✓ Branch 65 taken 1 times.
✗ Branch 66 not taken.
✓ Branch 67 taken 1 times.
✓ Branch 68 taken 1 times.
✗ Branch 69 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 1 times.
✗ Branch 73 not taken.
✓ Branch 74 taken 1 times.
✗ Branch 75 not taken.
✓ Branch 76 taken 1 times.
✗ Branch 77 not taken.
|
34 | inline double var() const { return mSize<2 ? 0.0 : mAux/double(mSize); } |
| 234 | inline double variance() const { return this->var(); } | ||
| 235 | //@} | ||
| 236 | |||
| 237 | //@{ | ||
| 238 | /// @brief Return the standard deviation (=Sqrt(variance)) as | ||
| 239 | /// defined from the (biased) population variance. | ||
| 240 | 8 | inline double std() const { return sqrt(this->var()); } | |
| 241 | inline double stdDev() const { return this->std(); } | ||
| 242 | //@} | ||
| 243 | |||
| 244 | /// @brief Print statistics to the specified output stream. | ||
| 245 | void print(const std::string &name= "", std::ostream &strm=std::cout, int precision=3) const | ||
| 246 | { | ||
| 247 | // Write to a temporary string stream so as not to affect the state | ||
| 248 | // (precision, field width, etc.) of the output stream. | ||
| 249 | std::ostringstream os; | ||
| 250 | os << std::setprecision(precision) << std::setiosflags(std::ios::fixed); | ||
| 251 | os << "Statistics "; | ||
| 252 | if (!name.empty()) os << "for \"" << name << "\" "; | ||
| 253 | if (mSize>0) { | ||
| 254 | os << "with " << mSize << " samples:\n" | ||
| 255 | << " Min=" << mMin | ||
| 256 | << ", Max=" << mMax | ||
| 257 | << ", Ave=" << mAvg | ||
| 258 | << ", Std=" << this->stdDev() | ||
| 259 | << ", Var=" << this->variance() << std::endl; | ||
| 260 | } else { | ||
| 261 | os << ": no samples were added." << std::endl; | ||
| 262 | } | ||
| 263 | strm << os.str(); | ||
| 264 | } | ||
| 265 | |||
| 266 | protected: | ||
| 267 | using Extrema::mSize; | ||
| 268 | using Extrema::mMin; | ||
| 269 | using Extrema::mMax; | ||
| 270 | double mAvg, mAux; | ||
| 271 | }; // end Stats | ||
| 272 | |||
| 273 | |||
| 274 | //////////////////////////////////////// | ||
| 275 | |||
| 276 | |||
| 277 | /// @brief This class computes a histogram, with a fixed interval width, | ||
| 278 | /// of a population of floating-point values. | ||
| 279 |
6/12✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
26 | class Histogram |
| 280 | { | ||
| 281 | public: | ||
| 282 | /// Construct with given minimum and maximum values and the given bin count. | ||
| 283 | 5 | Histogram(double min, double max, size_t numBins = 10) | |
| 284 | 5 | : mSize(0), mMin(min), mMax(max + 1e-10), | |
| 285 | 5 | mDelta(double(numBins)/(max-min)), mBins(numBins) | |
| 286 | { | ||
| 287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if ( mMax <= mMin ) { |
| 288 | ✗ | OPENVDB_THROW(ValueError, "Histogram: expected min < max"); | |
| 289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | } else if ( numBins == 0 ) { |
| 290 | ✗ | OPENVDB_THROW(ValueError, "Histogram: expected at least one bin"); | |
| 291 | } | ||
| 292 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 5 times.
|
51 | for (size_t i=0; i<numBins; ++i) mBins[i]=0; |
| 293 | 5 | } | |
| 294 | |||
| 295 | /// @brief Construct with the given bin count and with minimum and maximum values | ||
| 296 | /// taken from a Stats object. | ||
| 297 | 2 | Histogram(const Stats& s, size_t numBins = 10): | |
| 298 | 2 | mSize(0), mMin(s.min()), mMax(s.max()+1e-10), | |
| 299 | 2 | mDelta(double(numBins)/(mMax-mMin)), mBins(numBins) | |
| 300 | { | ||
| 301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if ( mMax <= mMin ) { |
| 302 | ✗ | OPENVDB_THROW(ValueError, "Histogram: expected min < max"); | |
| 303 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | } else if ( numBins == 0 ) { |
| 304 | ✗ | OPENVDB_THROW(ValueError, "Histogram: expected at least one bin"); | |
| 305 | } | ||
| 306 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2 times.
|
37 | for (size_t i=0; i<numBins; ++i) mBins[i]=0; |
| 307 | 2 | } | |
| 308 | |||
| 309 | /// @brief Add @a n samples with constant value @a val, provided that the | ||
| 310 | /// @a val falls within this histogram's value range. | ||
| 311 | /// @return @c true if the sample value falls within this histogram's value range. | ||
| 312 | inline bool add(double val, uint64_t n = 1) | ||
| 313 | { | ||
| 314 |
12/24✓ Branch 0 taken 680660 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 680660 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8788 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8788 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 680661 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 680661 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8788 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8788 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 5 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 500000 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 500000 times.
✗ Branch 23 not taken.
|
1878902 | if (val<mMin || val>mMax) return false; |
| 315 | 1878902 | mBins[size_t(mDelta*(val-mMin))] += n; | |
| 316 | 1878902 | mSize += n; | |
| 317 | 1878902 | return true; | |
| 318 | } | ||
| 319 | |||
| 320 | /// @brief Add all the contributions from the other histogram, provided that | ||
| 321 | /// it has the same configuration as this histogram. | ||
| 322 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
16 | bool add(const Histogram& other) |
| 323 | { | ||
| 324 |
3/6✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | if (!isApproxEqual(mMin, other.mMin) || !isApproxEqual(mMax, other.mMax) || |
| 325 | mBins.size() != other.mBins.size()) return false; | ||
| 326 |
2/2✓ Branch 0 taken 144 times.
✓ Branch 1 taken 16 times.
|
160 | for (size_t i=0, e=mBins.size(); i!=e; ++i) mBins[i] += other.mBins[i]; |
| 327 | 16 | mSize += other.mSize; | |
| 328 | 16 | return true; | |
| 329 | } | ||
| 330 | |||
| 331 | /// Return the number of bins in this histogram. | ||
| 332 | inline size_t numBins() const { return mBins.size(); } | ||
| 333 | /// Return the lower bound of this histogram's value range. | ||
| 334 | inline double min() const { return mMin; } | ||
| 335 | /// Return the upper bound of this histogram's value range. | ||
| 336 | inline double max() const { return mMax; } | ||
| 337 | /// Return the minimum value in the <i>n</i>th bin. | ||
| 338 |
4/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 29 times.
✓ Branch 3 taken 21 times.
|
60 | inline double min(int n) const { return mMin+n/mDelta; } |
| 339 | /// Return the maximum value in the <i>n</i>th bin. | ||
| 340 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 24 times.
|
34 | inline double max(int n) const { return mMin+(n+1)/mDelta; } |
| 341 | /// Return the number of samples in the <i>n</i>th bin. | ||
| 342 |
6/12✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 5 times.
✗ Branch 17 not taken.
|
51 | inline uint64_t count(int n) const { return mBins[n]; } |
| 343 | /// Return the population size, i.e., the total number of samples. | ||
| 344 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | inline uint64_t size() const { return mSize; } |
| 345 | |||
| 346 | /// Print the histogram to the specified output stream. | ||
| 347 | void print(const std::string& name = "", std::ostream& strm = std::cout) const | ||
| 348 | { | ||
| 349 | // Write to a temporary string stream so as not to affect the state | ||
| 350 | // (precision, field width, etc.) of the output stream. | ||
| 351 | std::ostringstream os; | ||
| 352 | os << std::setprecision(6) << std::setiosflags(std::ios::fixed) << std::endl; | ||
| 353 | os << "Histogram "; | ||
| 354 | if (!name.empty()) os << "for \"" << name << "\" "; | ||
| 355 | if (mSize > 0) { | ||
| 356 | os << "with " << mSize << " samples:\n"; | ||
| 357 | os << "==============================================================\n"; | ||
| 358 | os << "|| # | Min | Max | Frequency | % ||\n"; | ||
| 359 | os << "==============================================================\n"; | ||
| 360 | for (int i = 0, e = int(mBins.size()); i != e; ++i) { | ||
| 361 | os << "|| " << std::setw(4) << i << " | " << std::setw(14) << this->min(i) << " | " | ||
| 362 | << std::setw(14) << this->max(i) << " | " << std::setw(9) << mBins[i] << " | " | ||
| 363 | << std::setw(3) << (100*mBins[i]/mSize) << " ||\n"; | ||
| 364 | } | ||
| 365 | os << "==============================================================\n"; | ||
| 366 | } else { | ||
| 367 | os << ": no samples were added." << std::endl; | ||
| 368 | } | ||
| 369 | strm << os.str(); | ||
| 370 | } | ||
| 371 | |||
| 372 | private: | ||
| 373 | uint64_t mSize; | ||
| 374 | double mMin, mMax, mDelta; | ||
| 375 | std::vector<uint64_t> mBins; | ||
| 376 | };// end Histogram | ||
| 377 | |||
| 378 | } // namespace math | ||
| 379 | } // namespace OPENVDB_VERSION_NAME | ||
| 380 | } // namespace openvdb | ||
| 381 | |||
| 382 | #endif // OPENVDB_MATH_STATS_HAS_BEEN_INCLUDED | ||
| 383 |