use num_traits::{Float, FromPrimitive};
use crate::statistics::*;
#[derive(Debug, Clone, Copy)]
pub struct Variance {
pub ddof: usize,
}
impl Variance {
pub fn new(ddof: usize) -> Self {
Variance { ddof }
}
}
impl Default for Variance {
fn default() -> Self {
Variance { ddof: 1 }
}
}
impl<D, T> Statistic<D, T> for Variance
where
D: AsRef<[T]>,
T: Float + FromPrimitive + Copy,
{
fn compute(&self, data: &D) -> T {
let slice = data.as_ref();
if slice.len() < 2 {
return T::nan();
}
let mean = Mean.compute(data);
let mut sq_sum = T::zero();
let mut c2 = T::zero();
for &x in slice {
let dev = x - mean;
let y = dev * dev - c2;
let t = sq_sum + y;
c2 = (t - sq_sum) - y;
sq_sum = t;
}
let dof = T::from_usize(slice.len() - self.ddof).expect("usize fits in float");
sq_sum / dof
}
}