use ndarray::{s, ArrayViewMut1};
#[cold]
pub fn heap_sort<T, F>(mut v: ArrayViewMut1<'_, T>, mut is_less: F)
where
F: FnMut(&T, &T) -> bool,
{
let mut sift_down = |mut v: ArrayViewMut1<'_, T>, mut node| {
loop {
let mut child = 2 * node + 1;
if child >= v.len() {
break;
}
if child + 1 < v.len() && is_less(&v[child], &v[child + 1]) {
child += 1;
}
if !is_less(&v[node], &v[child]) {
break;
}
v.swap(node, child);
node = child;
}
};
for i in (0..v.len() / 2).rev() {
sift_down(v.view_mut(), i);
}
for i in (1..v.len()).rev() {
v.swap(0, i);
sift_down(v.slice_mut(s![..i]), 0);
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod test {
use super::heap_sort;
use ndarray::Array1;
use quickcheck_macros::quickcheck;
#[quickcheck]
fn sorted(xs: Vec<u32>) {
let mut array = Array1::from_vec(xs);
heap_sort(array.view_mut(), &mut u32::lt);
for i in 1..array.len() {
assert!(array[i - 1] <= array[i]);
}
}
}