Skip to content
File

Blob: firmware/vendor/str0m/src/util/average.rs

rust81 lines
1/// Exponential moving average
2#[derive(Debug)]
3pub struct MovingAverage {
4 smoothing_factor: f64,
5 average: Option<f64>,
6 variance: f64,
7 std: f64,
8}
9 
10impl MovingAverage {
11 pub fn new(smoothing_factor: f64) -> Self {
12 Self {
13 smoothing_factor,
14 average: None,
15 variance: 0.0,
16 std: 0.0,
17 }
18 }
19 
20 pub fn within_std(&self, value: f64, num_std: f64) -> bool {
21 let Some(average) = self.average else {
22 return false;
23 };
24 
25 let floor = average - self.std * num_std;
26 let ceil = average + self.std * num_std;
27 
28 floor <= value && value <= ceil
29 }
30 
31 pub fn upper_range(&self, num_std: f64) -> Option<f64> {
32 if self.std == 0.0 {
33 return None;
34 }
35 
36 self.average.map(|avg| avg + num_std * self.std)
37 }
38 
39 pub fn lower_range(&self, num_std: f64) -> Option<f64> {
40 if self.std == 0.0 {
41 return None;
42 }
43 
44 self.average.map(|avg| avg - num_std * self.std)
45 }
46 
47 pub fn update(&mut self, value: f64) {
48 let average = match self.average {
49 Some(average) => {
50 let delta = value - average;
51 let new_average = average + self.smoothing_factor * delta;
52 let new_variance = (1.0 - self.smoothing_factor)
53 * (self.variance + self.smoothing_factor * delta.powf(2.0));
54 
55 self.variance = new_variance;
56 self.std = new_variance.sqrt();
57 
58 new_average
59 }
60 None => value,
61 };
62 
63 self.average = Some(average);
64 }
65 
66 /// Returns the current average value, or None if no values have been added yet.
67 pub fn get(&self) -> Option<f64> {
68 self.average
69 }
70 
71 pub fn valid(&self) -> bool {
72 self.average.is_some()
73 }
74 
75 pub fn reset(&mut self) {
76 self.average = None;
77 self.std = 0.0;
78 self.variance = 0.0;
79 }
80}