use core::fmt;
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Statistics {
pub mean: f64,
pub sd: f64,
}
impl fmt::Display for Statistics {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.mean.fmt(f)?;
" ± ".fmt(f)?;
self.sd.fmt(f)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Accumulator {
pub count: usize,
pub mean: f64,
pub sdm: f64,
}
impl Accumulator {
#[must_use]
pub const fn new() -> Self {
Self {
count: 0,
mean: 0.0,
sdm: 0.0,
}
}
#[allow(clippy::cast_precision_loss)]
pub fn push(&mut self, x: f64) {
let delta = x - self.mean;
self.count += 1;
self.mean += delta / self.count as f64;
self.sdm += delta * (x - self.mean);
}
#[must_use]
#[allow(clippy::cast_precision_loss)]
pub fn population(self) -> Statistics {
Statistics {
mean: if self.count == 0 { f64::NAN } else { self.mean },
sd: (self.sdm / self.count as f64).sqrt(),
}
}
#[must_use]
#[allow(clippy::cast_precision_loss)]
pub fn sample(self) -> Statistics {
Statistics {
mean: if self.count == 0 { f64::NAN } else { self.mean },
sd: (self.sdm / (self.count.max(1) - 1) as f64).sqrt(),
}
}
}