#[cfg(test)]
mod tests;
use num_traits::real::Real;
use std::ops::Index;
#[derive(Clone, Copy, Debug)]
pub struct Series<R: Real, const N: usize> {
buf: [R; N],
offset: usize,
n: R,
mean: R,
variance: R,
sum: R,
}
impl<R: Real, const N: usize> Series<R, N> {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, new: R) {
self.offset = (self.offset + 1) % N;
let old = self.buf[self.offset];
self.buf[self.offset] = new;
let old_mean = self.mean;
self.mean = self.mean + (new - old) / self.n;
self.variance = self.variance + (new - old) * (new - self.mean + old - old_mean) / self.n;
self.sum = self.sum - old + new;
}
pub fn mean(&self) -> R {
self.mean
}
pub fn var(&self) -> R {
self.variance
}
pub fn stdev(&self) -> R {
self.var().sqrt()
}
pub fn curr(&self) -> R {
self.buf[self.offset]
}
pub fn norm(&self) -> R {
if self.stdev() == R::zero() {
R::zero()
} else {
(self.curr() - self.mean()) / self.stdev()
}
}
pub fn sum(&self) -> R {
self.sum
}
}
impl<R: Real, const N: usize> From<[R; N]> for Series<R, N> {
fn from(buf: [R; N]) -> Self {
let n = R::from(N).expect("Couldn't convert N to type R.");
let mean = buf.iter().fold(R::zero(), |acc, &x| acc + x) / n;
let variance = buf
.iter()
.map(|&x| (x - mean).powi(2))
.fold(R::zero(), |acc, x| acc + x)
/ n;
let sum = buf
.iter()
.fold(R::zero(), |acc, &x| acc + x);
Series {
buf,
offset: buf.len() - 1,
n,
mean,
variance,
sum,
}
}
}
impl<R: Real, const N: usize> Index<usize> for Series<R, N> {
type Output = R;
fn index(&self, index: usize) -> &Self::Output {
assert!(index < N, "Index wasn't less than N.");
let index = (N + self.offset - index) % N;
&self.buf[index]
}
}
impl<R: Real, const N: usize> Default for Series<R, N> {
fn default() -> Self {
Self::from([R::zero(); N])
}
}