radiate_core/stats/
statistics.rs1use core::f32;
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5#[derive(PartialEq, Clone)]
6#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7pub struct Adder {
8 compensation: f32,
9 simple_sum: f32,
10 sum: f32,
11}
12
13impl Adder {
14 pub fn value(&self) -> f32 {
15 let result = self.sum + self.compensation;
16 if result.is_nan() {
17 self.simple_sum
18 } else {
19 result
20 }
21 }
22
23 pub fn add(&mut self, value: f32) {
24 let y = value - self.compensation;
25 let t = self.sum + y;
26
27 self.compensation = (t - self.sum) - y;
28 self.sum = t;
29 self.simple_sum += value;
30 }
31}
32
33impl Default for Adder {
34 fn default() -> Self {
35 Adder {
36 compensation: 0_f32,
37 simple_sum: 0_f32,
38 sum: 0_f32,
39 }
40 }
41}
42
43#[derive(PartialEq, Clone)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45pub struct Statistic {
46 m1: Adder,
47 m2: Adder,
48 m3: Adder,
49 m4: Adder,
50 sum: Adder,
51 count: i32,
52 last_value: f32,
53 max: f32,
54 min: f32,
55}
56
57impl Statistic {
58 pub fn new(initial_val: f32) -> Self {
59 let mut result = Statistic::default();
60 result.add(initial_val);
61 result
62 }
63
64 pub fn last_value(&self) -> f32 {
65 self.last_value
66 }
67
68 pub fn count(&self) -> i32 {
69 self.count
70 }
71
72 pub fn min(&self) -> f32 {
73 self.min
74 }
75
76 pub fn max(&self) -> f32 {
77 self.max
78 }
79
80 pub fn mean(&self) -> f32 {
81 if self.count == 0 {
82 0_f32
83 } else {
84 self.m1.value()
85 }
86 }
87
88 pub fn sum(&self) -> f32 {
89 self.sum.value()
90 }
91
92 #[inline(always)]
93 pub fn variance(&self) -> f32 {
94 let mut value = f32::NAN;
95 if self.count == 1 {
96 value = self.m2.value();
97 } else if self.count > 1 {
98 value = self.m2.value() / (self.count - 1) as f32;
99 }
100
101 value
102 }
103
104 #[inline(always)]
105 pub fn std_dev(&self) -> f32 {
106 self.variance().sqrt()
107 }
108
109 #[inline(always)]
110 pub fn skewness(&self) -> f32 {
111 let mut value = f32::NAN;
112 if self.count >= 3 {
113 let temp = self.m2.value() / self.count as f32 - 1_f32;
114 if temp < 10e-10_f32 {
115 value = 0_f32;
116 } else {
117 value = self.count as f32 * self.m3.value()
118 / ((self.count as f32 - 1_f32)
119 * (self.count as f32 - 2_f32)
120 * temp.sqrt()
121 * temp)
122 }
123 }
124
125 value
126 }
127
128 #[inline(always)]
129 pub fn kurtosis(&self) -> f32 {
130 let mut value = f32::NAN;
131 if self.count >= 4 {
132 let temp = self.m2.value() / self.count as f32 - 1_f32;
133 if temp < 10e-10_f32 {
134 value = 0_f32;
135 } else {
136 value = self.count as f32 * (self.count as f32 + 1_f32) * self.m4.value()
137 / ((self.count as f32 - 1_f32)
138 * (self.count as f32 - 2_f32)
139 * (self.count as f32 - 3_f32)
140 * temp
141 * temp)
142 }
143 }
144
145 value
146 }
147
148 #[inline(always)]
149 pub fn add(&mut self, value: f32) {
150 self.count += 1;
151
152 let n = self.count as f32;
153 let d = value - self.m1.value();
154 let dn = d / n;
155 let dn2 = dn * dn;
156 let t1 = d * dn * (n - 1_f32);
157
158 self.m1.add(dn);
159
160 self.m4.add(t1 * dn2 * (n * n - 3_f32 * n + 3_f32));
161 self.m4
162 .add(6_f32 * dn2 * self.m2.value() - 4_f32 * dn * self.m3.value());
163
164 self.m3
165 .add(t1 * dn * (n - 2_f32) - 3_f32 * dn * self.m2.value());
166 self.m2.add(t1);
167
168 self.last_value = value;
169 self.max = if value > self.max { value } else { self.max };
170 self.min = if value < self.min { value } else { self.min };
171 self.sum.add(value);
172 }
173
174 pub fn clear(&mut self) {
175 self.m1 = Adder::default();
176 self.m2 = Adder::default();
177 self.m3 = Adder::default();
178 self.m4 = Adder::default();
179 self.sum = Adder::default();
180 self.count = 0;
181 self.last_value = 0_f32;
182 self.max = f32::MIN;
183 self.min = f32::MAX;
184 }
185}
186
187impl Default for Statistic {
188 fn default() -> Self {
189 Statistic {
190 m1: Adder::default(),
191 m2: Adder::default(),
192 m3: Adder::default(),
193 m4: Adder::default(),
194 sum: Adder::default(),
195 count: 0,
196 last_value: 0_f32,
197 max: f32::MIN,
198 min: f32::MAX,
199 }
200 }
201}
202
203impl From<f32> for Statistic {
204 fn from(value: f32) -> Self {
205 Statistic::new(value)
206 }
207}
208
209impl From<i32> for Statistic {
210 fn from(value: i32) -> Self {
211 Statistic::new(value as f32)
212 }
213}
214
215impl From<usize> for Statistic {
216 fn from(value: usize) -> Self {
217 Statistic::new(value as f32)
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224
225 #[test]
226 fn test_adder() {
227 let mut adder = Adder::default();
228 adder.add(1_f32);
229 adder.add(2_f32);
230 adder.add(3_f32);
231 adder.add(4_f32);
232 adder.add(5_f32);
233
234 assert_eq!(adder.value(), 15_f32);
235 }
236
237 #[test]
238 fn test_statistic() {
239 let mut statistic = Statistic::default();
240 statistic.add(1_f32);
241 statistic.add(2_f32);
242 statistic.add(3_f32);
243 statistic.add(4_f32);
244 statistic.add(5_f32);
245
246 assert_eq!(statistic.mean(), 3_f32);
247 assert_eq!(statistic.variance(), 2.5_f32);
248 assert_eq!(statistic.std_dev(), 1.5811388_f32);
249 assert_eq!(statistic.skewness(), 0_f32);
250 }
251}