1#[derive(Default)]
12pub(crate) struct Variance {
13 mean: f64,
14 mean2: f64,
15 n: u64,
16}
17
18impl Variance {
19 #[inline]
20 pub fn add(&mut self, sample: f64) {
21 self.n += 1;
22 let n_f = self.n as f64;
23 let delta_sq = (sample - self.mean).powi(2);
24 self.mean2 += ((n_f - 1.0) * delta_sq) / n_f;
25 self.mean += (sample - self.mean) / n_f;
26 }
27
28 #[inline]
29 pub fn mean(&self) -> f64 {
30 self.mean
31 }
32
33 #[inline]
34 pub fn mean_error(&self) -> f64 {
35 if self.n < 2 {
36 return 0.0;
37 }
38
39 let n_f = self.n as f64;
40 let sd = (self.mean2 / (n_f - 1.0)).sqrt();
41 sd / n_f.sqrt()
42 }
43
44 #[inline]
45 pub fn mean_with_error(&self) -> f64 {
46 let mean = self.mean.abs();
47 mean + self.mean_error().abs()
48 }
49
50 #[inline]
51 pub fn has_significant_result(&self) -> bool {
52 self.n >= 2
53 }
54
55 #[inline]
56 pub fn samples(&self) -> u64 {
57 self.n
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::Variance;
64
65 #[test]
66 fn basic() {
67 let inputs = &[5.0, 10.0, 12.0, 15.0, 20.0];
68 let mut variance = Variance::default();
69 for input in inputs {
70 variance.add(*input);
71 }
72
73 assert_eq!(variance.mean(), 12.4);
74
75 let expected_mean_error = 2.5019;
76 assert!((variance.mean_error() - expected_mean_error).abs() < 0.001);
77 }
78}