GCC Code Coverage Report


Directory: src/lib/
File: src/lib/StatisticsAccumulator.cpp
Date: 2025-12-31 18:33:11
Exec Total Coverage
Lines: 116 116 100.0%
Branches: 25 25 100.0%

Line Branch Exec Source
1 #include <algorithm>
2 #include <cmath>
3 #include <limits>
4
5 #include "stats/StatisticsAccumulator.hpp"
6 #include "stats/StatisticsUtilities.hpp"
7
8 namespace stats
9 {
10
11 37 StatisticsAccumulator::StatisticsAccumulator()
12 37 : count_(0)
13 37 , minimum_(std::numeric_limits<float>::max())
14 37 , maximum_(-std::numeric_limits<float>::max())
15 37 , moment1_(0.0)
16 37 , abs_moment1_(0.0)
17 37 , moment2_(0.0)
18 37 , moment3_(0.0)
19 37 , moment4_(0.0)
20 {
21 37 }
22
23 687 void StatisticsAccumulator::add(const float& value)
24 {
25 687 ++count_;
26
27 687 minimum_ = std::min(value, minimum_);
28 687 maximum_ = std::max(value, maximum_);
29
30 687 const double dVal = static_cast<double>(value);
31 687 const double nvals = static_cast<double>(count_);
32 687 const double delta = dVal - moment1_;
33 687 const double delta_n = delta / nvals;
34 687 const double delta_n2 = delta_n * delta_n;
35 687 const double term1 = delta * delta_n * (nvals - 1);
36 687 moment1_ += delta_n;
37 687 abs_moment1_ += (fabs(dVal) - abs_moment1_) / nvals;
38 687 moment4_ += term1 * delta_n2 * (nvals * nvals - 3 * nvals + 3) + 6.0 * delta_n2 * moment2_ -
39 687 4.0 * delta_n * moment3_;
40 687 moment3_ += term1 * delta_n * (nvals - 2) - 3.0 * delta_n * moment2_;
41 687 moment2_ += term1;
42 687 }
43
44 30 size_t StatisticsAccumulator::count() const
45 {
46 30 return count_;
47 }
48
49 24 float StatisticsAccumulator::minimum() const
50 {
51
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 21 times.
24 if (count_ == 0)
52 {
53 3 return stats::undefined();
54 }
55
56 21 return minimum_;
57 }
58
59 23 float StatisticsAccumulator::maximum() const
60 {
61
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 20 times.
23 if (count_ == 0)
62 {
63 3 return stats::undefined();
64 }
65
66 20 return maximum_;
67 }
68
69 21 float StatisticsAccumulator::mean() const
70 {
71
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
21 if (count_ == 0)
72 {
73 3 return stats::undefined();
74 }
75
76 18 return static_cast<float>(moment1_);
77 }
78
79 21 float StatisticsAccumulator::absolute_mean() const
80 {
81
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
21 if (count_ == 0)
82 {
83 3 return stats::undefined();
84 }
85
86 18 return static_cast<float>(abs_moment1_);
87 }
88
89 21 float StatisticsAccumulator::quadratic_mean() const
90 {
91
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
21 if (count_ == 0)
92 {
93 3 return stats::undefined();
94 }
95
96 18 const double mean2 = moment1_ * moment1_;
97 18 const double nvals = static_cast<double>(count_);
98 18 const double sd2 = moment2_ / nvals;
99 18 const double rms2 = mean2 + sd2;
100 18 const double rms = sqrt(rms2);
101 18 return static_cast<float>(rms);
102 }
103
104 21 float StatisticsAccumulator::standard_deviation() const
105 {
106
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 18 times.
21 if (count_ == 0)
107 {
108 3 return stats::undefined();
109 }
110
111 18 const double nvals = static_cast<double>(count_);
112 18 const double std_dev = sqrt(moment2_ / nvals);
113 18 return static_cast<float>(std_dev);
114 }
115
116 19 float StatisticsAccumulator::skewness() const
117 {
118
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16 times.
19 if (count_ == 0)
119 {
120 3 return stats::undefined();
121 }
122
123
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
16 if (moment2_ == 0.0)
124 {
125 3 return stats::undefined();
126 }
127
128 13 const double nvals = static_cast<double>(count_);
129 13 const double skew = (sqrt(nvals) * moment3_) / pow(moment2_, 1.5);
130 13 return static_cast<float>(skew);
131 }
132
133 19 float StatisticsAccumulator::kurtosis() const
134 {
135
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 16 times.
19 if (count_ == 0)
136 {
137 3 return stats::undefined();
138 }
139
140
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
16 if (moment2_ == 0.0)
141 {
142 3 return stats::undefined();
143 }
144
145 13 const double nvals = static_cast<double>(count_);
146 13 const double kurt = (nvals * moment4_) / (moment2_ * moment2_) - 3.0;
147 13 return static_cast<float>(kurt);
148 }
149
150 10 StatisticsAccumulator StatisticsAccumulator::operator+(const StatisticsAccumulator& that) const
151 {
152
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 if (this->count_ == 0)
153 {
154 4 return that;
155 }
156
157
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if (that.count_ == 0)
158 {
159 2 return *this;
160 }
161
162 4 const double a_n = static_cast<double>(this->count_);
163 4 const double b_n = static_cast<double>(that.count_);
164 4 const double c_n = static_cast<double>(this->count_ + that.count_);
165
166 4 const double& a_m1(this->moment1_);
167 4 const double& a_abs_m1(this->abs_moment1_);
168 4 const double& a_m2(this->moment2_);
169 4 const double& a_m3(this->moment3_);
170 4 const double& a_m4(this->moment4_);
171
172 4 const double& b_m1(that.moment1_);
173 4 const double& b_abs_m1(that.abs_moment1_);
174 4 const double& b_m2(that.moment2_);
175 4 const double& b_m3(that.moment3_);
176 4 const double& b_m4(that.moment4_);
177
178 4 const double delta = b_m1 - a_m1;
179 4 const double delta2 = delta * delta;
180 4 const double delta3 = delta * delta2;
181 4 const double delta4 = delta2 * delta2;
182
183 4 StatisticsAccumulator combined;
184
185 4 combined.count_ = this->count_ + that.count_;
186 4 combined.minimum_ = std::min(this->minimum_, that.minimum_);
187 4 combined.maximum_ = std::max(this->maximum_, that.maximum_);
188
189 4 combined.moment1_ = (a_n * a_m1 + b_n * b_m1) / c_n;
190
191 4 combined.abs_moment1_ = (a_n * a_abs_m1 + b_n * b_abs_m1) / c_n;
192
193 4 combined.moment2_ = a_m2 + b_m2 + delta2 * a_n * b_n / c_n;
194
195 4 combined.moment3_ = a_m3 + b_m3 + delta3 * a_n * b_n * (a_n - b_n) / (c_n * c_n);
196 4 combined.moment3_ += 3.0 * delta * (a_n * b_m2 - b_n * a_m2) / c_n;
197
198 4 combined.moment4_ =
199 4 a_m4 + b_m4 + delta4 * a_n * b_n * (a_n * a_n - a_n * b_n + b_n * b_n) / (c_n * c_n * c_n);
200 4 combined.moment4_ += 6.0 * delta2 * (a_n * a_n * b_m2 + b_n * b_n * a_m2) / (c_n * c_n) +
201 4 4.0 * delta * (a_n * b_m3 - b_n * a_m3) / c_n;
202
203 4 return combined;
204 }
205
206 2 StatisticsAccumulator& StatisticsAccumulator::operator+=(const StatisticsAccumulator& rhs)
207 {
208
1/1
✓ Branch 1 taken 2 times.
2 StatisticsAccumulator combined = *this + rhs;
209 2 *this = combined;
210 2 return *this;
211 }
212
213 } // namespace stats
214