use num::{Float, FromPrimitive};
use std::ops::{AddAssign, SubAssign};
use crate::mean::Mean;
use crate::stats::{Bivariate, Univariate};
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Covariance<F: Float + FromPrimitive + AddAssign + SubAssign> {
pub ddof: u32,
pub mean_x: Mean<F>,
pub mean_y: Mean<F>,
c: F,
pub cov: F,
}
impl<F: Float + FromPrimitive + AddAssign + SubAssign> Covariance<F> {
pub fn new(ddof: u32) -> Self {
Self {
mean_x: Mean::new(),
mean_y: Mean::new(),
ddof,
c: F::from_f64(0.).unwrap(),
cov: F::from_f64(0.).unwrap(),
}
}
}
impl<F> Default for Covariance<F>
where
F: Float + FromPrimitive + AddAssign + SubAssign,
{
fn default() -> Self {
Self {
ddof: 1,
mean_x: Mean::new(),
mean_y: Mean::new(),
c: F::from_f64(0.).unwrap(),
cov: F::from_f64(0.).unwrap(),
}
}
}
impl<F: Float + FromPrimitive + AddAssign + SubAssign> Bivariate<F> for Covariance<F> {
fn update(&mut self, x: F, y: F) {
let dx = x - self.mean_x.get();
self.mean_x.update(x);
self.mean_y.update(y);
self.c += dx * (y - self.mean_y.get());
self.cov = self.c
/ (F::from_f64(1.)
.unwrap()
.max(self.mean_x.n.get() - F::from_u32(self.ddof).unwrap()));
}
fn get(&self) -> F {
self.cov
}
}