Skip to main content

dynamo_mocker/common/
running_mean.rs

1// SPDX-FileCopyrightText: Copyright (c) 2024-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::collections::VecDeque;
5use std::ops::{Add, Div, Sub};
6
7/// A generic running mean calculator with a fixed-size sliding window.
8/// Maintains a running sum and count to compute the mean in O(1) time.
9#[derive(Debug, Clone)]
10pub struct RunningMean<T>
11where
12    T: Copy + Add<Output = T> + Sub<Output = T> + Div<Output = T> + Default + From<u16>,
13{
14    max_size: u16,
15    sum: T,
16    values: VecDeque<T>,
17}
18
19impl<T> RunningMean<T>
20where
21    T: Copy + Add<Output = T> + Sub<Output = T> + Div<Output = T> + Default + From<u16>,
22{
23    pub fn new(max_size: u16) -> Self {
24        Self {
25            max_size,
26            sum: T::default(),
27            values: VecDeque::with_capacity(max_size as usize),
28        }
29    }
30
31    pub fn push(&mut self, value: T) {
32        // If at capacity, remove the oldest value from sum
33        if self.values.len() >= self.max_size as usize
34            && let Some(old_value) = self.values.pop_front()
35        {
36            self.sum = self.sum - old_value;
37        }
38
39        // Add new value
40        self.sum = self.sum + value;
41        self.values.push_back(value);
42    }
43
44    pub fn mean(&self) -> T {
45        if self.values.is_empty() {
46            T::default()
47        } else {
48            self.sum / T::from(self.values.len() as u16)
49        }
50    }
51
52    pub fn len(&self) -> usize {
53        self.values.len()
54    }
55
56    pub fn is_empty(&self) -> bool {
57        self.values.is_empty()
58    }
59
60    /// Clear all values from the window.
61    pub fn clear(&mut self) {
62        self.sum = T::default();
63        self.values.clear();
64    }
65}