extern crate num;
use self::num::traits::Float;
use math::{MeanVec, Var};
use math::{Dimension, Normalization};
pub trait GaussianEstimator<T> {
fn gaussian(&self, nrm: Normalization) -> Gaussian<T>;
}
pub struct Gaussian<T> {
mean: T,
var: T
}
impl <T: Float> Gaussian<T> {
pub fn new(mean: T, var: T) -> Gaussian<T> {
Gaussian {
mean: mean,
var: var
}
}
}
pub trait GaussianFunctions<T> {
fn mean(&self) -> T;
fn var(&self) -> T;
fn std(&self) -> T;
fn pr(&self, x: T) -> T;
}
macro_rules! gaussian_impl {
($($t:ty)*) => ($(
impl GaussianFunctions<$t> for Gaussian<$t> {
fn mean(&self) -> $t { self.mean.clone() }
fn var(&self) -> $t { self.var.clone() }
fn std(&self) -> $t { self.var().sqrt() }
fn pr(&self, x: $t) -> $t {
let s = self.std();
let m = self.mean();
let a = s * ((2.0 as $t) * 3.14159265 as $t).sqrt();
let b = (-(x-m)*(x-m) / ((2.0 as $t) * s * s)).exp();
b / a
}
}
impl GaussianEstimator<$t> for Vec<$t> {
fn gaussian(&self, nrm: Normalization) -> Gaussian<$t> {
(&self[..]).gaussian(nrm)
}
}
impl GaussianEstimator<$t> for [$t] {
fn gaussian(&self, nrm: Normalization) -> Gaussian<$t> {
Gaussian {
mean: self.mean(),
var: self.var(Dimension::Row, nrm)
}
}
}
)*)
}
gaussian_impl!{ f32 f64 }
#[cfg(test)]
mod tests {
use super::*;
use math::Normalization;
#[test]
fn test_parameters() {
let a = vec![1.0f32, 2.0, 3.0, 2.0, 1.0, 2.0];
let mut p = a.gaussian(Normalization::N);
assert!(p.mean() - 1.8333 <= 0.0001);
assert!(p.var() - 0.47222 <= 0.00001);
assert!(p.std() - 0.68718 <= 0.00001);
assert!(p.pr(2.0) - 0.56372 <= 0.00001);
assert!(p.pr(1.5) - 0.51613 <= 0.00001);
p = a.gaussian(Normalization::MinusOne);
assert!(p.mean() - 1.8333 <= 0.0001);
assert!(p.var() - 0.56667 <= 0.00001);
assert!(p.std() - 0.75277 <= 0.00001);
assert!(p.pr(2.0) - 0.51713 <= 0.00001);
assert!(p.pr(1.5) - 0.48048 <= 0.00001);
}
}