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 |