idsp/
accu.rs

1use core::ops::{Add, AddAssign, Mul, Sub};
2
3/// Accumulator
4///
5/// Use [`core::num::Wrapping`].
6///
7/// ```
8/// use core::num::Wrapping;
9/// use idsp::Accu;
10/// let mut a = Accu::new(Wrapping(0i8), Wrapping(127));
11/// assert_eq!(a.next(), Some(Wrapping(127)));
12/// assert_eq!(a.next(), Some(Wrapping(-2)));
13/// ```
14#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Debug)]
15pub struct Accu<T> {
16    /// Current accumulator state
17    pub state: T,
18    /// Step
19    pub step: T,
20}
21
22impl<T> Accu<T> {
23    /// Create a new accumulator with given initial state and step.
24    pub const fn new(state: T, step: T) -> Self {
25        Self { state, step }
26    }
27}
28
29impl<T: Copy> Iterator for Accu<T>
30where
31    T: AddAssign,
32{
33    type Item = T;
34    fn next(&mut self) -> Option<T> {
35        self.state += self.step;
36        Some(self.state)
37    }
38}
39
40impl<T: Copy + Mul<Output = T>> Mul<T> for Accu<T> {
41    type Output = Self;
42
43    fn mul(self, rhs: T) -> Self::Output {
44        Self::new(self.state * rhs, self.step * rhs)
45    }
46}
47
48impl<T: Copy + Add<Output = T>> Add for Accu<T> {
49    type Output = Self;
50
51    fn add(self, rhs: Self) -> Self::Output {
52        Self::new(self.state + rhs.state, self.step + rhs.step)
53    }
54}
55
56impl<T: Copy + Sub<Output = T>> Sub for Accu<T> {
57    type Output = Self;
58
59    fn sub(self, rhs: Self) -> Self::Output {
60        Self::new(self.state - rhs.state, self.step - rhs.step)
61    }
62}