use core::marker::Destruct;
#[allow(warnings, clippy::undocumented_unsafe_blocks, clippy::ptr_as_ptr)]
pub const fn cont2<T: [const] Clone>(
array: &[T],
key: &mut (impl const FnMut(&T) -> usize + [const] Destruct),
shift: usize,
counts: &mut [usize; 256],
) -> &'static [T] {
if array.is_empty() {
return &[];
}
let mut i = 0;
while i < array.len() {
counts[(key(&array[i]) >> shift) & 0xff] += 1;
i += 1;
}
let mut i = 1;
while i < 256 as usize {
counts[i] += counts[i - 1];
i += 1;
}
let outputs = unsafe {
core::intrinsics::const_allocate(
core::mem::size_of::<T>() * array.len(),
core::mem::align_of::<T>(),
)
}
.cast::<T>();
let mut i = array.len() - 1;
while {
let j = (key(&array[i]) >> shift) & 0xff;
counts[j] -= 1;
unsafe { outputs.add(counts[j]).write(array[i].clone()) };
i > 0
} {
i -= 1;
}
unsafe {
core::slice::from_raw_parts(
core::intrinsics::const_make_global(outputs as _) as _,
array.len(),
)
}
}
#[allow(clippy::manual_bit_width)]
pub(crate) const fn radixsort<T: [const] Clone>(
mut array: &'static [T],
mut key: impl const FnMut(&T) -> usize + [const] Destruct,
) -> &'static [T] {
let mut c = [0usize; 256];
let mut i = 0;
let bits = if array.len() < 50 {
let mut m = 0;
while i < array.len() {
m = m.max(key(&array[i]));
i += 1;
}
usize::BITS - m.leading_zeros()
} else {
usize::BITS
};
let mut shift = 0;
while shift < bits {
array = cont2(array, &mut key, shift as _, &mut c);
shift += 8;
c = [0; 256];
}
array
}