hopr_statistics/moving/
exponential.rs1#[derive(Debug, Copy, Clone, Default, PartialEq)]
10pub struct ExponentialMovingAverage<const FACTOR: usize> {
11 count: usize,
12 average: f64,
13}
14
15impl<const FACTOR: usize> ExponentialMovingAverage<FACTOR> {
16 pub fn update(&mut self, value: impl Into<f64>) {
18 let value: f64 = value.into();
19 self.count += 1;
20 self.average = self.average + (value - self.average) / (std::cmp::min(self.count, FACTOR) as f64);
21 }
22
23 pub fn get(&self) -> f64 {
25 self.average
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use assertables::{assert_f64_eq, assert_in_delta};
32
33 #[test]
34 fn running_average_should_compute_the_windowed_average_correctly() {
35 let mut avg = super::ExponentialMovingAverage::<5>::default();
36
37 for i in 1..=10 {
38 avg.update(i);
39 }
40
41 assert_in_delta!(avg.get(), 6.6, 0.1);
42 }
43
44 #[test]
45 fn running_average_should_compute_the_average_from_constant_correctly() {
46 let mut avg = super::ExponentialMovingAverage::<5>::default();
47
48 for _ in 1..=10 {
49 avg.update(3);
50 }
51
52 assert_f64_eq!(avg.get(), 3.0);
53 }
54}