use std::ops::{Add,Sub};
use anyhow::{Result,bail};
pub fn naive_median<T>(s:&mut[T]) -> Result<f64>
where T: PartialOrd+Copy+Add<Output=T>,f64:From<T> {
let n = s.len();
match n {
0 => bail!("empty vector!"),
1 => return Ok(f64::from(s[0])),
2 => return Ok(f64::from(s[0]+s[1])/2.0),
_ => {}
}
s.sort_unstable_by(|a, b| a.partial_cmp(b).unwrap());
let mid = n/2;
Ok(if (n & 1) == 0 { f64::from(s[mid-1] + s[mid]) / 2.0 }
else { f64::from(s[mid]) })
}
pub fn indxmedian<T>(set:&[T]) -> Result<f64>
where T: PartialOrd+Copy+Sub<Output=T>+Add<Output=T>,f64:From<T> {
let n = set.len();
match n {
0 => bail!("empty vector!"),
1 => return Ok(f64::from(set[0])),
2 => return Ok(f64::from(set[0]+set[1])/2.0),
_ => {}
}
let mut x1 = set[0];
let mut x2 = x1;
set.iter().skip(1).for_each(|&s| {
if s < x1 { x1 = s }
else if s > x2 { x2 = s };
});
let minf = f64::from(x1);
let hashit = (n-1)as f64 / (f64::from(x2)-minf);
let mut freqvec = vec![0_usize;n];
for s in set { freqvec[((f64::from(*s)-minf)*hashit).floor()as usize] += 1 }
let mut freqsum:usize = 0;
let mut i:usize = 0;
while 2*freqsum < n {
freqsum += freqvec[i];
i += 1;
};
Ok((i as f64/hashit+minf).floor())
}
fn partition<T>(set:&[T],pivot:f64) -> (Vec<T>,Vec<T>)
where T: PartialOrd+Copy+Sub<Output=T>,f64:From<T> {
let n = set.len()-1;
let mut smaller:Vec<T> = Vec::with_capacity(n);
let mut greater:Vec<T> = Vec::with_capacity(n);
for &st in set {
let s = f64::from(st);
if s<pivot { smaller.push(st) } else if s>pivot { greater.push(st) };
}
(smaller,greater)
}