use core::ops::Range;
pub fn midof3f64(item1: f64, item2: f64, item3: f64) -> f64 {
let (min, max) = if item1 <= item2 {
(item1, item2)
} else {
(item2, item1)
};
if item3 <= min {
return min;
};
if item3 <= max {
return item3;
};
max
}
pub fn partf64(s: &mut [f64], rng: &Range<usize>) -> (f64, usize, usize, usize) {
let mut startsub = rng.start;
let mut gtsub = startsub;
let mut endsub = rng.end - 1;
let mut ltsub = endsub;
let pivot = midof3f64(s[startsub], s[(startsub + rng.end) / 2], s[endsub]);
loop {
while s[gtsub] > pivot {
if gtsub == ltsub {
return (pivot, startsub, 1 + gtsub, 1 + endsub);
};
gtsub += 1;
}
if s[gtsub] == pivot {
if gtsub > startsub {
s[gtsub] = s[startsub];
};
if gtsub == ltsub {
return (pivot, 1 + startsub, 1 + gtsub, 1 + endsub);
};
startsub += 1;
gtsub += 1;
continue;
};
'lt: loop {
if s[ltsub] < pivot {
ltsub -= 1;
if gtsub >= ltsub {
return (pivot, startsub, gtsub, 1 + endsub);
};
continue 'lt;
}
if s[ltsub] == pivot {
if ltsub < endsub {
s[ltsub] = s[endsub];
};
ltsub -= 1;
if gtsub >= ltsub {
return (pivot, startsub, gtsub, endsub);
};
endsub -= 1;
continue 'lt;
};
break 'lt;
}
s.swap(ltsub, gtsub);
gtsub += 1;
ltsub -= 1;
if gtsub > ltsub {
return (pivot, startsub, gtsub, 1 + endsub);
};
}
}
pub fn minf64(s: &[f64], rng: Range<usize>) -> f64 {
let mut min = s[rng.start];
for &si in s.iter().take(rng.end).skip(rng.start + 1) {
if si < min {
min = si;
};
}
min
}
pub fn maxf64(s: &[f64], rng: Range<usize>) -> f64 {
let mut max = s[rng.start];
for &si in s.iter().take(rng.end).skip(rng.start + 1) {
if si > max {
max = si;
};
}
max
}
pub fn min2f64(s: &[f64], rng: Range<usize>) -> (f64, f64) {
let (mut min1, mut min2) = if s[rng.start + 1] < s[rng.start] {
(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 si < min1 {
min2 = min1;
min1 = si;
} else if si < min2 {
min2 = si;
}
}
(min1, min2)
}
pub fn max2f64(s: &[f64], rng: Range<usize>) -> (f64, f64) {
let (mut max1, mut max2) = if s[rng.start + 1] > s[rng.start] {
(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 si > max1 {
max2 = max1;
max1 = si;
} else if si > max2 {
max2 = si;
}
}
(max2, max1)
}
pub fn med_oddf64(s: &mut [f64]) -> f64 {
let mut rng = 0..s.len();
let mut need = s.len() / 2; loop {
let (pivot, gtsub, ltsub, ltend) = partf64(s, &rng);
if need + ltsub - rng.start + 2 < ltend {
need += ltsub - rng.start;
rng.start = ltsub;
rng.end = ltend;
continue;
}
if need + ltsub - rng.start < rng.end {
need += ltsub - rng.start;
if need + 2 == ltend {
return max2f64(s, ltsub..ltend).0;
};
if need + 1 == ltend {
return maxf64(s, ltsub..ltend);
};
return pivot;
};
need -= rng.end - ltsub;
if need > gtsub + 1 {
rng.start = gtsub;
rng.end = ltsub;
continue;
}
if need < gtsub {
return pivot;
};
if need == gtsub {
return minf64(s, gtsub..ltsub);
};
return min2f64(s, gtsub..ltsub).1;
}
}
pub fn med_evenf64(s: &mut [f64]) -> (f64, f64) {
let mut rng = 0..s.len();
let mut need = s.len() / 2 - 1; loop {
let (pivot, gtsub, ltsub, ltend) = partf64(s, &rng);
if need + ltsub - rng.start + 2 < ltend {
need += ltsub - rng.start;
rng.start = ltsub;
rng.end = ltend;
continue;
};
if need + ltsub - rng.start < rng.end {
need += ltsub - rng.start;
if need + 2 == ltend {
return max2f64(s, ltsub..ltend);
};
if need + 1 == ltend {
return (maxf64(s, ltsub..ltend), pivot);
};
let eqend = rng.end - 1 + gtsub - rng.start;
if need < eqend {
return (pivot, pivot);
};
if need == eqend {
if gtsub > rng.start {
return (pivot, pivot);
} else {
return (pivot, minf64(s, gtsub..ltsub));
}
};
};
need -= rng.end - ltsub;
if need+1 > gtsub {
rng.start = gtsub;
rng.end = ltsub;
continue;
};
if need+1 < gtsub {
return (pivot, pivot);
};
if need+1 == gtsub {
return (pivot, minf64(s, gtsub..ltsub));
};
if need == gtsub {
return min2f64(s, gtsub..ltsub);
};
}
}