use num::traits::Pow;
use num::*;
use std::cmp::Ordering;
use std::iter::Sum;
pub fn variance<T>(values: &[T], ddof: f64) -> Option<f64>
where
T: Num + ToPrimitive,
{
let m = mean(&values)?;
let numerator = values
.iter()
.map(|v| (v.to_f64().unwrap() - m).pow(2.))
.sum::<f64>();
Some(numerator / (values.len() as f64 - ddof))
}
pub fn std<T>(values: &[T], ddof: f64) -> Option<f64>
where
T: Num + ToPrimitive,
{
let var = variance(&values, ddof)?;
Some(var.sqrt())
}
pub fn mean<T>(values: &[T]) -> Option<f64>
where
T: Num + ToPrimitive,
{
Some(values.iter().map(|v| v.to_f64().unwrap()).sum::<f64>() / values.len() as f64)
}
pub fn sum<T>(values: &[T]) -> T
where
T: Num + Copy + Sum,
{
values.iter().map(|v| *v).sum()
}
pub fn min<T>(values: &[T]) -> Option<&T>
where
T: Num + PartialOrd + Copy,
{
values.iter().min_by(|a, b| match a.partial_cmp(b) {
Some(Ordering::Less) => Ordering::Less,
Some(Ordering::Greater) => Ordering::Greater,
Some(Ordering::Equal) => Ordering::Equal,
None => Ordering::Equal,
})
}
pub fn max<T>(values: &[T]) -> Option<&T>
where
T: Num + PartialOrd + Copy,
{
values.iter().min_by(|a, b| match b.partial_cmp(a) {
Some(Ordering::Less) => Ordering::Less,
Some(Ordering::Greater) => Ordering::Greater,
Some(Ordering::Equal) => Ordering::Equal,
None => Ordering::Equal,
})
}