use ndarray::Array1;
use stochastic_rs_distributions::special::ndtri;
use stochastic_rs_distributions::special::norm_cdf;
use stochastic_rs_distributions::special::norm_pdf;
#[derive(Debug, Clone, Default)]
pub struct GaussianUnivariate {
params: Option<(f64, f64)>,
}
impl GaussianUnivariate {
pub fn new() -> Self {
Self::default()
}
pub fn fit(&mut self, column: &Array1<f64>) {
let n = column.len() as f64;
if n < 2.0 {
self.params = Some((0.0, 1.0));
return;
}
let mean = column.mean().unwrap_or(0.0);
let var = column.iter().map(|&x| (x - mean).powi(2)).sum::<f64>() / (n - 1.0);
let std = var.sqrt().max(1e-12);
self.params = Some((mean, std));
}
pub fn is_fitted(&self) -> bool {
self.params.is_some()
}
pub fn cdf(&self, x: f64) -> f64 {
match self.params {
Some((mu, sigma)) => norm_cdf((x - mu) / sigma),
None => 0.5,
}
}
pub fn pdf(&self, x: f64) -> f64 {
match self.params {
Some((mu, sigma)) => norm_pdf((x - mu) / sigma) / sigma,
None => 1.0,
}
}
pub fn ppf(&self, p: f64) -> f64 {
match self.params {
Some((mu, sigma)) => mu + sigma * ndtri(p),
None => 0.0,
}
}
}