pub mod algos;
pub mod implementations;
use core::cmp::Ordering;
use core::fmt::Debug;
use crate::algos::{evenmedianu64, evenmedianu8, midof3, oddmedianu64, oddmedianu8, oddmedu64};
pub type Me = MedError<String>;
#[derive(Debug)]
pub enum MedError<T> {
Size(T),
Nan(T),
Other(T),
}
pub fn merror<T>(kind: &str, msg: impl Into<String>) -> Result<T, MedError<String>> {
match kind {
"size" => Err(MedError::Size(msg.into())),
"nan" => Err(MedError::Nan(msg.into())),
"other" => Err(MedError::Other(msg.into())),
_ => Err(MedError::Other("Wrong error kind given to merror".into())),
}
}
pub enum Medians<'a, T> {
Odd(&'a T),
Even((&'a T, &'a T)),
}
pub fn medianu8(s: &[u8]) -> Result<(u8, u8), Me> {
let n = s.len();
if n == 0 {
merror("size", "median: zero length data")?;
};
if (n & 1) == 1 {
match n {
1 => Ok((s[0], s[0])),
3 => {
let indx = midof3(s, 0, 1, 2, &mut |a, b| a.cmp(b));
Ok((s[indx], s[indx]))
}
_ => {
let m = oddmedianu8(s);
Ok((m, m))
}
}
} else if n == 2 {
Ok((s[0], s[1]))
} else {
let (m1, m2) = evenmedianu8(s);
Ok((m1, m2))
}
}
pub fn medianu64(s: &mut [u64]) -> Result<Medians<u64>, Me> {
let n = s.len();
match n {
0 => return merror("size", "medu: zero length data"),
1 => return Ok(Medians::Odd(&s[0])),
2 => return Ok(Medians::Even((&s[0], &s[1]))),
_ => (),
};
if (n & 1) == 1 {
Ok(Medians::Odd(oddmedianu64(s)))
} else {
Ok(Medians::Even(evenmedianu64(s)))
}
}
pub fn medu64(s: &mut [u64]) -> Result<(u64, u64), Me> {
if (s.len() & 1) == 1 {
let byteslice = s.iter().map(|x| x.to_be_bytes()).collect::<Vec<[u8; 8]>>();
let res = oddmedu64(&byteslice, 0, s.len() / 2);
Ok((res, res))
} else {
let (&m1, &m2) = evenmedianu64(s);
Ok((m1, m2))
}
}
pub trait Medianf64 {
fn medf_checked(self) -> Result<f64, Me>;
fn medf_unchecked(self) -> f64;
fn medf_weighted(self, ws: Self, eps: f64) -> Result<f64, Me>;
fn medf_zeroed(self, centre: f64) -> Vec<f64>;
fn medf_correlation(self, v: Self) -> Result<f64, Me>;
fn madf(self, centre: f64) -> f64;
}
pub trait Median<'a, T> {
fn qmedian_by(
self,
c: &mut impl FnMut(&T, &T) -> Ordering,
q: impl Fn(&T) -> f64,
) -> Result<f64, Me>;
fn uqmedian(self, q: impl Fn(&T) -> u64) -> Result<f64, Me>;
fn median_by(self, c: &mut impl FnMut(&T, &T) -> Ordering) -> Result<Medians<'a, T>, Me>;
fn zeroed(self, centre: f64, quantify: impl Fn(&T) -> f64) -> Result<Vec<f64>, Me>;
fn med_correlation(
self,
v: Self,
c: &mut impl FnMut(&T, &T) -> Ordering,
q: impl Fn(&T) -> f64,
) -> Result<f64, Me>;
fn mad(self, centre: f64, quantify: impl Fn(&T) -> f64) -> f64;
}