crypto-simd 0.1.1

Crypto-oriented SIMD wrapper abstracting over multiple backends
Documentation
macro_rules! def_swap {
    ($swap:ident, $fn:ident) => {
        pub trait $swap {
            type Output;
            fn $fn(self) -> Self::Output;
        }
    };
}
def_swap!(Swap1, swap1);
def_swap!(Swap2, swap2);
def_swap!(Swap4, swap4);
def_swap!(Swap8, swap8);
def_swap!(Swap16, swap16);
def_swap!(Swap32, swap32);
def_swap!(Swap64, swap64);
pub trait AndNot {
    type Output;
    fn andnot(self, rhs: Self) -> Self::Output;
}
pub trait RotateWordsRight {
    type Output;
    fn rotate_words_right(self, i: u32) -> Self::Output;
}
pub trait SplatRotateRight {
    type Output;
    fn splat_rotate_right(self, i: u32) -> Self::Output;
}

#[cfg(feature = "packed_simd")]
#[macro_use]
extern crate packed_simd_crate;
#[cfg(feature = "packed_simd")]
pub mod packed_simd {
    use super::*;
    use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, BitXorAssign};
    use packed_simd_crate::{u128x1, u128x2, u32x16, u32x4, u64x4};
    impl AndNot for u128x2 {
        type Output = u128x2;
        #[inline(always)]
        fn andnot(self, rhs: Self) -> Self::Output {
            !self & rhs
        }
    }
    #[inline(always)]
    fn swap128(x: u128x1, m: u128, i: u32) -> u128x1 {
        let m = u128x1::new(m);
        ((x & m) >> i) | ((x << i) & m)
    }
    macro_rules! impl_swap {
        ($swap:ident, $fn:ident, $mask:expr, $n:expr) => {
            impl $swap for u128x1 {
                type Output = u128x1;
                #[inline(always)]
                fn $fn(self) -> Self::Output {
                    swap128(self, $mask, $n)
                }
            }
        };
    }
    impl_swap!(Swap1, swap1, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 1);
    impl_swap!(Swap2, swap2, 0xcccccccccccccccccccccccccccccccc, 2);
    impl_swap!(Swap4, swap4, 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0, 4);
    impl_swap!(Swap8, swap8, 0xff00ff00ff00ff00ff00ff00ff00ff00, 8);
    impl_swap!(Swap16, swap16, 0xffff0000ffff0000ffff0000ffff0000, 16);
    impl_swap!(Swap32, swap32, 0xffffffff00000000ffffffff00000000, 32);
    impl Swap64 for u128x1 {
        type Output = u128x1;
        #[inline(always)]
        fn swap64(self) -> Self::Output {
            (self << 64) | (self >> 64)
        }
    }
    macro_rules! impl_rotate_words_right {
        ($vec:ident) => {
            impl RotateWordsRight for $vec {
                type Output = Self;
                fn rotate_words_right(self, i: u32) -> Self::Output {
                    debug_assert_eq!(i & !3, 0);
                    match i & 3 {
                        0 => self,
                        1 => shuffle!(self, [3, 0, 1, 2]),
                        2 => shuffle!(self, [2, 3, 0, 1]),
                        3 => shuffle!(self, [1, 2, 3, 0]),
                        _ => unreachable!(),
                    }
                }
            }
        };
    }
    impl_rotate_words_right!(u32x4);
    impl_rotate_words_right!(u64x4);
    macro_rules! impl_splat_rotate_right {
        ($vec:ident, $word:ty) => {
            impl SplatRotateRight for $vec {
                type Output = Self;
                fn splat_rotate_right(self, i: u32) -> Self::Output {
                    self.rotate_right(Self::splat(i as $word))
                }
            }
        };
    }
    impl_splat_rotate_right!(u32x4, u32);
    impl_splat_rotate_right!(u64x4, u64);

    #[allow(non_camel_case_types)]
    #[derive(Copy, Clone)]
    pub struct u32x4x4(u32x16);
    impl u32x4x4 {
        #[inline(always)]
        pub fn from((a, b, c, d): (u32x4, u32x4, u32x4, u32x4)) -> Self {
            u32x4x4(u32x16::new(
                a.extract(0),
                a.extract(1),
                a.extract(2),
                a.extract(3),
                b.extract(0),
                b.extract(1),
                b.extract(2),
                b.extract(3),
                c.extract(0),
                c.extract(1),
                c.extract(2),
                c.extract(3),
                d.extract(0),
                d.extract(1),
                d.extract(2),
                d.extract(3),
            ))
        }
        #[inline(always)]
        pub fn splat(a: u32x4) -> Self {
            u32x4x4::from((a, a, a, a))
        }
        #[inline(always)]
        pub fn into_parts(self) -> (u32x4, u32x4, u32x4, u32x4) {
            let a = u32x4::new(
                self.0.extract(0),
                self.0.extract(1),
                self.0.extract(2),
                self.0.extract(3),
            );
            let b = u32x4::new(
                self.0.extract(4),
                self.0.extract(5),
                self.0.extract(6),
                self.0.extract(7),
            );
            let c = u32x4::new(
                self.0.extract(8),
                self.0.extract(9),
                self.0.extract(10),
                self.0.extract(11),
            );
            let d = u32x4::new(
                self.0.extract(12),
                self.0.extract(13),
                self.0.extract(14),
                self.0.extract(15),
            );
            (a, b, c, d)
        }
    }
    impl BitXor for u32x4x4 {
        type Output = u32x4x4;
        #[inline(always)]
        fn bitxor(self, rhs: Self) -> Self::Output {
            u32x4x4(self.0 ^ rhs.0)
        }
    }
    impl BitOr for u32x4x4 {
        type Output = Self;
        #[inline(always)]
        fn bitor(self, rhs: Self) -> Self::Output {
            u32x4x4(self.0 | rhs.0)
        }
    }
    impl BitAnd for u32x4x4 {
        type Output = Self;
        #[inline(always)]
        fn bitand(self, rhs: Self) -> Self::Output {
            u32x4x4(self.0 & rhs.0)
        }
    }
    impl BitXorAssign for u32x4x4 {
        #[inline(always)]
        fn bitxor_assign(&mut self, rhs: Self) {
            self.0 ^= rhs.0;
        }
    }
    impl Add for u32x4x4 {
        type Output = Self;
        #[inline(always)]
        fn add(self, rhs: Self) -> Self::Output {
            u32x4x4(self.0 + rhs.0)
        }
    }
    impl AddAssign for u32x4x4 {
        #[inline(always)]
        fn add_assign(&mut self, rhs: Self) {
            self.0 += rhs.0;
        }
    }
    impl RotateWordsRight for u32x4x4 {
        type Output = Self;
        #[inline(always)]
        fn rotate_words_right(self, i: u32) -> Self::Output {
            match i {
                0 => self,
                1 => u32x4x4(shuffle!(
                    self.0,
                    [3, 0, 1, 2, 7, 4, 5, 6, 11, 8, 9, 10, 15, 12, 13, 14]
                )),
                2 => u32x4x4(shuffle!(
                    self.0,
                    [2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13]
                )),
                3 => u32x4x4(shuffle!(
                    self.0,
                    [1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12]
                )),
                _ => panic!("rotate_words_right index must be in the range 0..4"),
            }
        }
    }
    impl SplatRotateRight for u32x4x4 {
        type Output = Self;
        #[inline(always)]
        fn splat_rotate_right(self, i: u32) -> Self::Output {
            u32x4x4(self.0.rotate_right(u32x16::splat(i)))
        }
    }
}