use crate::Float;
#[derive(Clone, Debug)]
pub struct EstimatorResult<F> {
pub value: F,
pub estimate: F,
pub sample_variance: F,
pub standard_error: F,
pub num_samples: usize,
}
#[derive(Clone, Debug)]
pub struct DivergenceResult<F> {
pub values: Vec<F>,
pub estimate: F,
pub sample_variance: F,
pub standard_error: F,
pub num_samples: usize,
}
pub(super) struct WelfordAccumulator<F> {
mean: F,
m2: F,
count: usize,
}
impl<F: Float> WelfordAccumulator<F> {
pub(super) fn new() -> Self {
Self {
mean: F::zero(),
m2: F::zero(),
count: 0,
}
}
pub(super) fn update(&mut self, sample: F) {
assert!(
sample.is_finite(),
"WelfordAccumulator::update: sample must be finite"
);
self.count += 1;
let k1 = F::from(self.count).unwrap();
let delta = sample - self.mean;
self.mean = self.mean + delta / k1;
let delta2 = sample - self.mean;
self.m2 = self.m2 + delta * delta2;
}
pub(super) fn finalize(&self) -> (F, F, F) {
let nf = F::from(self.count).unwrap();
if self.count > 1 {
let var = (self.m2 / (nf - F::one())).max(F::zero());
(self.mean, var, (var / nf).sqrt())
} else {
(self.mean, F::zero(), F::zero())
}
}
}