#![warn(missing_docs)]
pub mod algos;
use crate::algos::{w_median,r_median};
use indxvec::{Vecops,printing::{GR,UN}};
#[derive(Default)]
pub struct Med {
pub median: f64,
pub lq: f64,
pub uq: f64,
pub mad: f64,
pub ste: f64
}
impl std::fmt::Display for Med {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!( f,
"median:
\tLower Q: {GR}{:>.16}{UN}
\tMedian: {GR}{:>.16}{UN}
\tUpper Q: {GR}{:>.16}{UN}
\tMad: {GR}{:>.16}{UN}
\tStd Err: {GR}{:>.16}{UN}",
self.lq,
self.median,
self.uq,
self.mad,
self.ste
)
}
}
#[derive(Default)]
pub struct MStats {
pub centre: f64,
pub dispersion: f64
}
impl std::fmt::Display for MStats {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f,"centre: {GR}{:<10e}{UN}\tdispersion: {GR}{:<10e}{UN}",
self.centre, self.dispersion )
}
}
pub trait Median {
fn median(self) -> f64;
fn mad(self,median:f64) -> f64;
fn medstats(self) -> MStats;
fn medinfo(self) -> Med;
}
impl<T> Median for &[T] where T:Copy+PartialOrd,f64:From<T> {
fn median(self) -> f64 {
let n = self.len();
if n == 0 { return 0_f64 };
if n < 90 { w_median(self) }
else { r_median(self) }
}
fn mad(self,med:f64) -> f64 {
self.iter().map(|&s| ((f64::from(s)-med).abs())).collect::<Vec<f64>>().median()
}
fn medstats(self) -> MStats {
let centre = self.median();
MStats { centre, dispersion: self.mad(centre) }
}
fn medinfo(self) -> Med {
let mut equals = 0_usize;
let mut posdifs:Vec<f64> = Vec::new();
let mut negdifs:Vec<f64> = Vec::new();
let med = self.median();
for &s in self {
let sf = f64::from(s);
if sf > med { posdifs.push(sf-med) }
else if sf < med { negdifs.push(med-sf) }
else { equals += 1 };
}
if equals > 1 {
let eqhalf = vec!(0.;equals/2);
let eqslice = vec!(0.;equals);
let lq = med - negdifs.unite_unsorted(&eqhalf).median();
let uq = med + eqhalf.unite_unsorted(&posdifs).median();
let mad = [negdifs,eqslice,posdifs].concat().median();
Med{ median:med,
lq,
uq,
mad,
ste: mad/med } }
else {
let lq = med-negdifs.median();
let uq = med+posdifs.median();
let mad = [negdifs,posdifs].concat().median();
Med { median:med,
lq,
uq,
mad,
ste: mad/med } }
}
}