use generic_array::{GenericArray, typenum};
use super::*;
#[inline(always)]
fn cmp_merge<R, const PERM_MASK: i32, const BLEND_MASK: i32>(v: Storage<R>) -> Storage<R>
where
R: NumericRegister + BlendRegister + PermuteRegister,
{
let v_shuf = R::permute::<PERM_MASK>(v);
let v_min = R::min(v, v_shuf);
let v_max = R::max(v, v_shuf);
R::blend::<BLEND_MASK>(v_min, v_max)
}
#[inline(always)]
pub fn sort_2<R>(v: Storage<R>) -> Storage<R>
where
R: NumericRegister<Lanes = typenum::U2> + BlendRegister + PermuteRegister,
{
let v_shuf = R::permute::<0x01>(v);
let v_min = R::min(v, v_shuf);
let v_max = R::max(v, v_shuf);
R::blend::<0x02>(v_min, v_max)
}
#[inline(always)]
pub fn sort_4<R>(v: Storage<R>) -> Storage<R>
where
R: NumericRegister<Lanes = typenum::U4> + BlendRegister + PermuteRegister,
{
let v = cmp_merge::<R, 0xB1, 0xA>(v);
let v = cmp_merge::<R, 0x4E, 0xC>(v);
cmp_merge::<R, 0xD8, 0x4>(v)
}
#[inline(always)]
pub fn sort_8<R>(v: Storage<R>) -> Storage<R>
where
R: NumericRegister<Lanes = typenum::U8> + BlendRegister + PermuteRegister,
{
let v = cmp_merge::<R, 0xB1, 0xAA>(v);
let v = cmp_merge::<R, 0x4E, 0xCC>(v);
let v = cmp_merge::<R, 0xD8, 0x44>(v);
let v = R::permutev(v, GenericArray::from_array([0, 1, 2, 3, 7, 6, 5, 4]));
let v_shuf = R::permutev(v, GenericArray::from_array([4, 5, 6, 7, 0, 1, 2, 3]));
let v_min = R::min(v, v_shuf);
let v_max = R::max(v, v_shuf);
let v = R::blend::<0xF0>(v_min, v_max);
let v = cmp_merge::<R, 0x4E, 0xCC>(v);
cmp_merge::<R, 0xB1, 0xAA>(v)
}
#[inline(always)]
pub fn sort_any<R: NumericRegister>(mut value: Storage<R>) -> Storage<R> {
let s = R::as_mut_slice(&mut value);
#[inline(always)]
fn cas<T: PartialOrd>(s: &mut [T], i: usize, j: usize) {
if s[i] > s[j] {
s.swap(i, j);
}
}
#[rustfmt::skip]
let () = match s.len() {
2 => cas(s, 0, 1),
4 => {
cas(s, 0, 1); cas(s, 2, 3); cas(s, 0, 2); cas(s, 1, 3); cas(s, 1, 2); },
_ => {
for i in 1..s.len() {
let mut j = i;
while j > 0 && s[j - 1] > s[j] {
s.swap(j - 1, j);
j -= 1;
}
}
}
};
value
}