<commit_before>use super::RdxSort;

use core::ptr;

use std::mem;
use std::ops;

trait HelperTwosComplementTemplate {
    type Alias;

    fn min() -> Self;
    fn zero() -> Self;
}

trait HelperTwosComplement {
    fn rdxsort_(&mut self);
}

// TODO: directly implement `RdxSort` once https://github.com/rust-lang/rfcs/issues/1053 is solved
impl<T> HelperTwosComplement for [T]
    where T: HelperTwosComplementTemplate + Clone + ops::Neg + PartialEq + PartialOrd,
          T::Alias: Clone,
          <T as ops::Neg>::Output: Into<T>,
          Vec<T::Alias>: RdxSort
{
    fn rdxsort_(&mut self) {
        assert_eq!(mem::size_of::<T>(), mem::size_of::<T::Alias>());

        let n = self.len();
        let mut positive: Vec<T::Alias> = Vec::with_capacity(n);
        let mut negative: Vec<T::Alias> = Vec::with_capacity(n);
        let mut min: Vec<T> = Vec::new();

        for x in self.iter().cloned() {
            if x == T::min() {
                // we cannot invert this value later
                min.push(x);
            } else if x >= T::zero() {
                unsafe {
                    positive.push(mem::transmute_copy::<T, T::Alias>(&x));
                }
            } else {
                unsafe {
                    negative.push(mem::transmute_copy::<T, T::Alias>(&((x).into())));
                }
            }
        }

        positive.rdxsort();
        negative.rdxsort();

        assert!(min.len() <= self.len(), "bug: oversized bucket");
        unsafe {
            ptr::copy_nonoverlapping(min.as_ptr(), self.get_unchecked_mut(0), min.len());
        }
        let mut pos = min.len();
        assert!(pos + negative.len() <= self.len(), "bug: oversized bucket");
        unsafe {
            ptr::copy_nonoverlapping(negative.as_ptr() as *mut T,
                                     self.get_unchecked_mut(pos),
                                     negative.len());
        }
        pos += negative.len();
        assert!(pos + positive.len() <= self.len(),
                "bug: bucket sizes doe not sum up");
        unsafe {
            ptr::copy_nonoverlapping(positive.as_ptr() as *mut T,
                                     self.get_unchecked_mut(pos),
                                     positive.len());
        }
    }
}

macro_rules! impl_rdxsort {
    ($t:ty, $alias:ty, $min:expr, $zero:expr) => {
        impl HelperTwosComplementTemplate for $t {
            type Alias = $alias;

            fn min() -> Self {
                $min
            }

            fn zero() -> Self {
                $zero
            }
        }

        impl RdxSort for [$t] {
            fn rdxsort(&mut self) {
                self.rdxsort_();
            }
        }
    }
}

impl_rdxsort!(i8, u8, i8::min_value(), 0i8);
impl_rdxsort!(i16, u16, i16::min_value(), 0i16);
impl_rdxsort!(i32, u32, i32::min_value(), 0i32);
impl_rdxsort!(i64, u64, i64::min_value(), 0i64);
<commit_msg>use template for signed integers<commit_after>use template::RdxSortTemplate;

use std::cmp;
use std::mem;

macro_rules! impl_rdxsort {
    ($t:ty, $alias:ty, $min:expr, $zero:expr) => {
        impl RdxSortTemplate for $t {
            fn cfg_nbuckets() -> usize {
                cmp::max(<$alias as RdxSortTemplate>::cfg_nbuckets(), 3)
            }

            fn cfg_nrounds() -> usize {
                <$alias as RdxSortTemplate>::cfg_nrounds() + 1
            }

            fn get_bucket(&self, round: usize) -> usize {
                if round < <$alias as RdxSortTemplate>::cfg_nrounds() {
                    let alias = unsafe { mem::transmute::<$t, $alias>(*self) };
                    alias.get_bucket(round)
                } else {
                    if *self == $min {
                        0
                    } else if *self >= $zero {
                        2
                    } else {
                        1
                    }

                }
            }
        }
    }
}

impl_rdxsort!(i8, u8, i8::min_value(), 0i8);
impl_rdxsort!(i16, u16, i16::min_value(), 0i16);
impl_rdxsort!(i32, u32, i32::min_value(), 0i32);
impl_rdxsort!(i64, u64, i64::min_value(), 0i64);

{'fraction_non_alphanumeric': 0.14696640077350737, 'fraction_numerical': 0.01788735798888083, 'mean_word_length': 1.6239695624603678, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 29, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4294522', 'n_tokens_mistral': 1375, 'n_tokens_neox': 1297, 'n_words': 269}