use core::cmp::{Ordering, Ordering::*};
use indxvec::{Mutops, Vecops};
use std::ops::Range;
pub const FIRST_BIT: u64 = 0x80_00_00_00_00_00_00_00;
pub fn midof3<T>(
s: &[T],
indx0: usize,
indx1: usize,
indx2: usize,
c: &mut impl FnMut(&T, &T) -> Ordering,
) -> usize {
let (min, max) = if c(&s[indx0], &s[indx1]) == Less {
(indx0, indx1)
} else {
(indx1, indx0)
};
let lastref = &s[indx2];
if c(&s[min], lastref) != Less {
return min;
};
if c(lastref, &s[max]) != Less {
return max;
};
indx2
}
fn midof3_refs<T>(
s: &[&T],
indx0: usize,
indx1: usize,
indx2: usize,
c: &mut impl FnMut(&T, &T) -> Ordering,
) -> usize {
let (min, max) = if c(s[indx0], s[indx1]) == Less {
(indx0, indx1)
} else {
(indx1, indx0)
};
let lastref = s[indx2];
if c(s[min], lastref) != Less {
return min;
};
if c(lastref, s[max]) != Less {
return max;
};
indx2
}
pub fn nans(v: &[f64]) -> bool {
for &f in v {
if f.is_nan() {
return true;
};
}
false
}
pub fn best_k<T, F>(s: &[T], k: usize, rng: Range<usize>, c: F) -> &T
where
F: Fn(&T, &T) -> Ordering,
{
let n = rng.len();
assert!((k > 0) & (k <= n));
let mut k_sorted: Vec<&T> = s.iter().skip(rng.start).take(k).collect();
k_sorted.sort_unstable_by(|&a, &b| c(a, b));
let mut k_max = k_sorted[k - 1];
for si in s.iter() {
if c(si, k_max) == Less {
let insert_pos = match k_sorted.binary_search_by(|j| c(j, si)) {
Ok(ins) => ins + 1,
Err(ins) => ins,
};
k_sorted.insert(insert_pos, si);
k_sorted.pop();
k_max = k_sorted[k - 1];
};
}
k_max
}
pub fn extremum<'a, T>(s: &'a[T], rng: Range<usize>, c: &mut impl FnMut(&T, &T) -> Ordering) -> &'a T {
let mut min = &s[rng.start];
for si in s.iter().take(rng.end).skip(rng.start + 1) {
if c(si, min) == Ordering::Less {
min = si;
};
}
min
}
pub fn best_two<'a, T>(s: &'a[T], rng: Range<usize>, c: &mut impl FnMut(&T, &T) -> Ordering) -> (&'a T, &'a T) {
let (mut m1, mut m2) = if c(&s[rng.start+1], &s[rng.start]) == Ordering::Less {
(&s[rng.start+1], &s[rng.start])
} else {
(&s[rng.start], &s[rng.start+1])
};
for si in s.iter().take(rng.end).skip(rng.start + 2) {
if c(si,m2) == Ordering::Less {
if c(si,m1) == Ordering::Less {
m2 = m1;
m1 = si;
} else {
m2 = si;
};
};
};
(m1, m2)
}
pub fn extremum_refs<'a, T>(s: &[&'a T], rng: Range<usize>, c: &mut impl FnMut(&T, &T) -> Ordering) -> &'a T {
let mut m = s[rng.start];
for si in s.iter().take(rng.end).skip(rng.start + 1) {
if c(si, m) == Ordering::Less {
m = si;
};
}
m
}
pub fn best_two_refs<'a, T>(
s: &[&'a T],
rng: Range<usize>,
c: &mut impl FnMut(&T, &T) -> Ordering
) -> (&'a T, &'a T) {
let (mut m1, mut m2) = if c(s[rng.start+1], s[rng.start]) == Ordering::Less {
(s[rng.start+1], s[rng.start])
} else {
(s[rng.start], s[rng.start+1])
};
for si in s.iter().take(rng.end).skip(rng.start + 2) {
if c(si,m2) == Ordering::Less {
if c(si,m1) == Ordering::Less {
m2 = m1;
m1 = si;
} else {
m2 = si;
};
};
};
(m1, m2)
}
pub fn qbalance<T>(s: &[T], centre: &f64, q: impl Fn(&T) -> f64) -> i64 {
let mut bal = 0_i64;
let mut eq = 0_i64;
for si in s {
match &q(si).total_cmp(centre) {
Less => bal -= 1,
Greater => bal += 1,
_ => eq += 1,
};
}
if bal == 0 {
return 0;
};
if bal.abs() <= eq {
return 0;
};
1
}
pub fn oddmedianu8(s: &[u8]) -> u8 {
let need = s.len() / 2; let mut histogram = [0_usize; 256];
let mut cummulator = 0_usize;
for &u in s.iter() {
histogram[u as usize] += 1;
}
for i in 0_u8..255 {
let hist = histogram[i as usize];
if hist == 0 {
continue;
};
cummulator += hist;
if need < cummulator {
return i;
};
}
255
}
pub fn evenmedianu8(s: &[u8]) -> (u8,u8) {
let need = s.len() / 2; let mut histogram = [0_usize; 256];
let mut cummulator = 0_usize;
let mut firstres = true;
let mut res1 = 255_u8;
for &u in s.iter() {
histogram[u as usize] += 1;
}
for i in 0_u8..255 {
let hist = histogram[i as usize];
if hist == 0 {
continue;
};
cummulator += hist;
if firstres {
if cummulator > need {
return (i, i);
}; if cummulator == need {
res1 = i;
firstres = false;
}; } else {
return (res1,i);
}; }
if firstres {
(255, 255)
} else {
(res1, 255)
}
}
pub fn oddmedianu64(s: &mut [u64]) -> &u64 {
let mut rng = 0..s.len();
let need = s.len() / 2; let mut bitval = FIRST_BIT; loop {
let gtsub = s.part_binary(&rng, bitval);
if bitval == 1 {
if need < gtsub {
return &s[gtsub - 1];
};
return &s[gtsub];
};
if need + 2 < gtsub {
rng.end = gtsub;
bitval >>= 1; continue;
};
if need > gtsub + 1 {
rng.start = gtsub;
bitval >>= 1; continue;
};
if need + 2 == gtsub {
return best_two(s, rng.start..gtsub,&mut |a,b| b.cmp(a)).1;
};
if need + 1 == gtsub {
return extremum(s, rng.start..gtsub,&mut |a,b| b.cmp(a));
};
if need == gtsub {
return extremum(s, gtsub..rng.end, &mut |a,b| a.cmp(b));
};
return best_two(s, gtsub..rng.end, &mut |a,b| a.cmp(b)).1;
}
}
pub fn evenmedianu64(s: &mut [u64]) -> (&u64, &u64) {
let mut rng = 0..s.len();
let need = s.len() / 2 - 1; let mut bitval = FIRST_BIT; loop {
let gtsub = s.part_binary(&rng, bitval);
if bitval == 1 {
if need + 1 < gtsub {
return (&s[gtsub - 2], &s[gtsub - 1]);
};
if need + 1 == gtsub {
return (&s[gtsub - 1], &s[gtsub]);
};
return (&s[gtsub], &s[gtsub + 1]);
};
if need + 2 < gtsub {
rng.end = gtsub;
bitval >>= 1; continue;
};
if need > gtsub {
rng.start = gtsub;
bitval >>= 1; continue;
};
if need + 2 == gtsub {
let (m1,m2) = best_two(s, rng.start..gtsub,&mut |a,b| b.cmp(a));
return (m2,m1)
};
if need + 1 == gtsub {
return (extremum(s, rng.start..gtsub,&mut |a,b| b.cmp(a)),
extremum(s, gtsub..rng.end,&mut |a,b| a.cmp(b)));
};
if need == gtsub {
return best_two(s, gtsub..rng.end,&mut |a,b| a.cmp(b));
};
}
}
pub fn select(bytes: &[[u8; 8]], byteno: usize, val: u8) -> Vec<[u8; 8]> {
let mut res = Vec::new();
for &item in bytes {
if item[byteno] == val {
res.push(item);
};
}
res
}
pub(super) fn oddmedu64(bytes: &[[u8; 8]], byteno: usize, need: usize) -> u64 {
let n = bytes.len();
assert_ne!(n, 0, "oddmedu64 failed to find median");
if n == 1 {
return u64::from_be_bytes(bytes[0]);
};
if n < 8 { let idx = bytes.isort_refs(0..bytes.len(), |a:&[u8; 8],b| a.cmp(b));
return u64::from_be_bytes(*idx[need]);
};
let mut histogram = [0_usize; 256];
let mut cummulator = 0_usize;
for &u in bytes {
histogram[u[byteno] as usize] += 1;
};
let mut medianbyte = 255_u8;
for (i, &h) in histogram.iter().enumerate() {
if h == 0_usize { continue };
cummulator += h;
if cummulator > need {
medianbyte = i as u8;
cummulator -= h; break;
};
}
if byteno == 7 {
let mut res = bytes[0]; res[7] = medianbyte; return u64::from_be_bytes(res);
};
oddmedu64(
&select(bytes, byteno, medianbyte),
byteno + 1,
need - cummulator,
) }
pub(super) fn oddmedian_by<'a, T>(
s: &mut [&'a T],
c: &mut impl FnMut(&T, &T) -> Ordering,
) -> &'a T {
let mut rng = 0..s.len();
let need = s.len() / 2; loop {
let mut pivotsub = midof3_refs(s, rng.start, rng.start + need, rng.end - 1, c);
if rng.len() == 3 {
return s[pivotsub];
};
if rng.len() > 100 {
let pivotsub2 = midof3_refs(s, rng.start + 1, rng.start + need + 1, rng.end - 2, c);
let pivotsub3 = midof3_refs(s, rng.start + 2, rng.start + need + 2, rng.end - 3, c);
pivotsub = midof3_refs(s, pivotsub, pivotsub2, pivotsub3, c);
}
if pivotsub != rng.start {
s.swap(rng.start, pivotsub);
};
let pivotref = s[rng.start];
let (eqsub, gtsub) = <&mut [T]>::part(s, &rng, c);
if need + 2 < eqsub {
rng.end = eqsub;
continue;
};
if need + 2 == eqsub {
return best_two_refs(s, rng.start..eqsub, &mut |a, b| c(b, a)).1;
};
if need + 1 == eqsub {
return extremum_refs(s, rng.start..eqsub, &mut |a, b| c(b, a));
};
if need < gtsub {
return pivotref;
};
if need == gtsub {
return extremum_refs(s, gtsub..rng.end, c);
};
if need == gtsub + 1 {
return best_two_refs(s, gtsub..rng.end, c).1;
};
rng.start = gtsub;
}
}
pub(super) fn evenmedian_by<'a, T>(
s: &mut [&'a T],
c: &mut impl FnMut(&T, &T) -> Ordering,
) -> (&'a T, &'a T) {
let mut rng = 0..s.len();
let need = s.len() / 2 - 1; loop {
let mut pivotsub = midof3_refs(s, rng.start, rng.start + need, rng.end - 1, c);
if rng.len() > 100 {
let pivotsub2 = midof3_refs(s, rng.start + 1, rng.start + need + 1, rng.end - 2, c);
let pivotsub3 = midof3_refs(s, rng.start + 2, rng.start + need + 2, rng.end - 3, c);
pivotsub = midof3_refs(s, pivotsub, pivotsub2, pivotsub3, c);
};
if pivotsub != rng.start {
s.swap(rng.start, pivotsub);
};
let pivotref = s[rng.start];
let (eqsub, gtsub) = <&mut [T]>::part(s, &rng, c);
if need + 2 < eqsub {
rng.end = eqsub;
continue;
};
if need + 2 == eqsub {
let (m1, m2) = best_two_refs(s, rng.start..eqsub, &mut |a, b| c(b, a));
return (m2,m1); };
if need + 1 == eqsub {
return (extremum_refs(s, rng.start..eqsub, &mut |a, b| c(b, a)), pivotref);
};
if need + 1 < gtsub {
return (pivotref, pivotref);
};
if need + 1 == gtsub {
return (pivotref, extremum_refs(s, gtsub..rng.end, c));
};
if need == gtsub {
return best_two_refs(s, gtsub..rng.end, c);
};
rng.start = gtsub;
}
}