use super::Edge;
pub(super) fn quick_sort_edges(edges: &mut [Edge]) {
quick_sort_by_key_with_seed(edges, |e| e.i0, INTERNAL_RND_SORT_SEED);
#[cfg(mikktspace_rs_more_assertions)]
debug_assert!(edges.is_sorted_by_key(|e| e.i0));
let last_chunk_len = edges
.chunk_by(|a, b| a.i0 == b.i0)
.next_back()
.map(<[_]>::len)
.unwrap_or(edges.len());
let (good, bad) = edges.split_at_mut(edges.len() - last_chunk_len);
good.sort_unstable();
for chunk in bad
.chunk_by_mut(|a, b| a.i1 == b.i1)
.rev()
.skip(1)
{
quick_sort_by_key_with_seed(chunk, |e| e.f, INTERNAL_RND_SORT_SEED);
#[cfg(mikktspace_rs_more_assertions)]
debug_assert!(chunk.is_sorted());
}
}
fn quick_sort_by_key_with_seed<T, K: Ord>(sort_buffer: &mut [T], key: fn(&T) -> K, seed: u32) {
if sort_buffer.len() <= 2 {
sort_buffer.sort_unstable_by_key(key);
return;
}
let seed = {
let t = seed & 31;
let t = seed.wrapping_shl(t) | seed.wrapping_shr(32_u32.wrapping_sub(t));
seed.wrapping_add(t).wrapping_add(3)
};
let pivot_index = seed.wrapping_rem(sort_buffer.len() as u32) as usize;
let pivot = key(&sort_buffer[pivot_index]);
let (mut a, mut b) = (0, sort_buffer.len().saturating_sub(1));
while a <= b {
a = (a..sort_buffer.len())
.find(|&left| key(&sort_buffer[left]) >= pivot)
.unwrap();
b = (0..=b)
.rev()
.find(|&right| key(&sort_buffer[right]) <= pivot)
.unwrap();
if a <= b {
sort_buffer.swap(a, b);
a = a.saturating_add(1);
b = b.saturating_sub(1);
}
}
debug_assert!(b < a);
let (lesser, rest) = sort_buffer.split_at_mut(b + 1);
let (_sorted, greater) = rest.split_at_mut(a - lesser.len());
#[cfg(debug_assertions)]
if let (Some(x), Some(y)) = (_sorted.first(), _sorted.last()) {
debug_assert!(lesser.iter().all(|t| key(t) <= key(x)));
debug_assert!(greater.iter().all(|t| key(t) >= key(y)));
} else {
debug_assert!(_sorted.is_empty());
debug_assert!(lesser.iter().all(|t| key(t) <= pivot));
debug_assert!(greater.iter().all(|t| key(t) >= pivot));
}
quick_sort_by_key_with_seed(lesser, key, seed);
#[cfg(mikktspace_rs_more_assertions)]
debug_assert!(_sorted.is_sorted_by_key(key));
quick_sort_by_key_with_seed(greater, key, seed);
}
const INTERNAL_RND_SORT_SEED: u32 = 39871946;