1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
#![no_std] macro_rules! sort { ($inputtype:ty, $storage_type:ty, $array:ident) => {{ const IS_UNSIGNED: bool = <$inputtype>::min_value() == 0; const SIZE: usize = ((IS_UNSIGNED as usize) * (<$inputtype>::max_value() as usize + 1)) + ((!IS_UNSIGNED as usize) * (((<$inputtype>::max_value() as isize) - (<$inputtype>::min_value() as isize)) as usize + 1)); let mut table: [$storage_type; SIZE] = [0; SIZE]; for value in $array.iter() { unsafe { *table.get_unchecked_mut(if IS_UNSIGNED { *value as $storage_type } else { ((*value as isize) - (<$inputtype>::min_value() as isize)) as $storage_type }) += 1; } } let mut pos = 0; for (i, amount) in table.iter().enumerate().filter(|(_, &amount)| amount > 0) { let end = *amount as $storage_type + pos; let i: $inputtype = if IS_UNSIGNED { i as $inputtype } else { (i as isize + (<$inputtype>::min_value() as isize)) as $inputtype }; if *amount % 2 == 1 { unsafe { *$array.get_unchecked_mut(pos) = i; } pos += 1; } while pos < end { unsafe { *$array.get_unchecked_mut(pos) = i; *$array.get_unchecked_mut(pos + 1) = i; } pos += 2; } } }}; } #[inline] pub fn sort_u8(array: &mut [u8]) { if array.len() < 2 { } else { sort!(u8, usize, array); } } #[inline] pub fn sort_u16(array: &mut [u16]) { if array.len() < 2 { } else { sort!(u16, usize, array); } } #[inline] pub fn sort_i8(array: &mut [i8]) { if array.len() < 2 { } else { sort!(i8, usize, array); } } #[inline] pub fn sort_i16(array: &mut [i16]) { if array.len() < 2 { } else { sort!(i16, usize, array); } }