pub mod histogram;
pub mod prefix_sum;
pub mod scatter;
#[cfg(feature = "alloc")]
extern crate alloc;
use crate::key::{SortableKey, UnsignedKey};
#[cfg(feature = "alloc")]
pub fn sort<T: SortableKey>(slice: &mut [T]) {
if slice.len() <= 1 {
return;
}
let mut buffer = alloc::vec![unsafe { core::mem::zeroed() }; slice.len()];
sort_with_buffer(slice, &mut buffer);
}
pub fn sort_with_buffer<T: SortableKey>(slice: &mut [T], buffer: &mut [T]) {
assert!(buffer.len() >= slice.len());
let len = slice.len();
if len <= 1 {
return;
}
let passes = T::Key::BYTES;
let mut h = [[0usize; 8 * 256]; 4];
let chunks = len / 4;
for i in 0..chunks {
let k0 = slice[i * 4].to_radix_key();
let k1 = slice[i * 4 + 1].to_radix_key();
let k2 = slice[i * 4 + 2].to_radix_key();
let k3 = slice[i * 4 + 3].to_radix_key();
for pass in 0..passes {
h[0][pass * 256 + k0.radix_digit(pass) as usize] += 1;
h[1][pass * 256 + k1.radix_digit(pass) as usize] += 1;
h[2][pass * 256 + k2.radix_digit(pass) as usize] += 1;
h[3][pass * 256 + k3.radix_digit(pass) as usize] += 1;
}
}
for elem in slice[chunks * 4..].iter() {
let key = elem.to_radix_key();
for pass in 0..passes {
h[0][pass * 256 + key.radix_digit(pass) as usize] += 1;
}
}
let mut histograms = [0usize; 8 * 256];
for copy in &h {
for (g, c) in histograms.iter_mut().zip(copy.iter()) {
*g += c;
}
}
let mut in_buffer = false;
for pass in 0..passes {
let hist_slice = &histograms[pass * 256..(pass + 1) * 256];
if histogram::is_pass_trivial(hist_slice, len) {
continue;
}
let mut offsets = [0usize; 256];
offsets.copy_from_slice(hist_slice);
prefix_sum::exclusive_prefix_sum(&mut offsets);
if in_buffer {
scatter::scatter_pass(buffer, slice, &mut offsets, pass);
} else {
scatter::scatter_pass(slice, buffer, &mut offsets, pass);
}
in_buffer = !in_buffer;
}
if in_buffer {
slice.copy_from_slice(buffer);
}
}