crypto_simd/
lib.rs

1macro_rules! def_swap {
2    ($swap:ident, $fn:ident) => {
3        pub trait $swap {
4            type Output;
5            fn $fn(self) -> Self::Output;
6        }
7    };
8}
9def_swap!(Swap1, swap1);
10def_swap!(Swap2, swap2);
11def_swap!(Swap4, swap4);
12def_swap!(Swap8, swap8);
13def_swap!(Swap16, swap16);
14def_swap!(Swap32, swap32);
15def_swap!(Swap64, swap64);
16pub trait AndNot {
17    type Output;
18    fn andnot(self, rhs: Self) -> Self::Output;
19}
20pub trait RotateWordsRight {
21    type Output;
22    fn rotate_words_right(self, i: u32) -> Self::Output;
23}
24pub trait SplatRotateRight {
25    type Output;
26    fn splat_rotate_right(self, i: u32) -> Self::Output;
27}
28
29#[cfg(feature = "packed_simd")]
30#[macro_use]
31extern crate packed_simd_crate;
32#[cfg(feature = "packed_simd")]
33pub mod packed_simd {
34    use super::*;
35    use core::ops::{Add, AddAssign, BitAnd, BitOr, BitXor, BitXorAssign};
36    use packed_simd_crate::{u128x1, u128x2, u32x16, u32x4, u64x4};
37    impl AndNot for u128x2 {
38        type Output = u128x2;
39        #[inline(always)]
40        fn andnot(self, rhs: Self) -> Self::Output {
41            !self & rhs
42        }
43    }
44    #[inline(always)]
45    fn swap128(x: u128x1, m: u128, i: u32) -> u128x1 {
46        let m = u128x1::new(m);
47        ((x & m) >> i) | ((x << i) & m)
48    }
49    macro_rules! impl_swap {
50        ($swap:ident, $fn:ident, $mask:expr, $n:expr) => {
51            impl $swap for u128x1 {
52                type Output = u128x1;
53                #[inline(always)]
54                fn $fn(self) -> Self::Output {
55                    swap128(self, $mask, $n)
56                }
57            }
58        };
59    }
60    impl_swap!(Swap1, swap1, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, 1);
61    impl_swap!(Swap2, swap2, 0xcccccccccccccccccccccccccccccccc, 2);
62    impl_swap!(Swap4, swap4, 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0, 4);
63    impl_swap!(Swap8, swap8, 0xff00ff00ff00ff00ff00ff00ff00ff00, 8);
64    impl_swap!(Swap16, swap16, 0xffff0000ffff0000ffff0000ffff0000, 16);
65    impl_swap!(Swap32, swap32, 0xffffffff00000000ffffffff00000000, 32);
66    impl Swap64 for u128x1 {
67        type Output = u128x1;
68        #[inline(always)]
69        fn swap64(self) -> Self::Output {
70            (self << 64) | (self >> 64)
71        }
72    }
73    macro_rules! impl_rotate_words_right {
74        ($vec:ident) => {
75            impl RotateWordsRight for $vec {
76                type Output = Self;
77                fn rotate_words_right(self, i: u32) -> Self::Output {
78                    debug_assert_eq!(i & !3, 0);
79                    match i & 3 {
80                        0 => self,
81                        1 => shuffle!(self, [3, 0, 1, 2]),
82                        2 => shuffle!(self, [2, 3, 0, 1]),
83                        3 => shuffle!(self, [1, 2, 3, 0]),
84                        _ => unreachable!(),
85                    }
86                }
87            }
88        };
89    }
90    impl_rotate_words_right!(u32x4);
91    impl_rotate_words_right!(u64x4);
92    macro_rules! impl_splat_rotate_right {
93        ($vec:ident, $word:ty) => {
94            impl SplatRotateRight for $vec {
95                type Output = Self;
96                fn splat_rotate_right(self, i: u32) -> Self::Output {
97                    self.rotate_right(Self::splat(i as $word))
98                }
99            }
100        };
101    }
102    impl_splat_rotate_right!(u32x4, u32);
103    impl_splat_rotate_right!(u64x4, u64);
104
105    #[allow(non_camel_case_types)]
106    #[derive(Copy, Clone)]
107    pub struct u32x4x4(u32x16);
108    impl u32x4x4 {
109        #[inline(always)]
110        pub fn from((a, b, c, d): (u32x4, u32x4, u32x4, u32x4)) -> Self {
111            u32x4x4(u32x16::new(
112                a.extract(0),
113                a.extract(1),
114                a.extract(2),
115                a.extract(3),
116                b.extract(0),
117                b.extract(1),
118                b.extract(2),
119                b.extract(3),
120                c.extract(0),
121                c.extract(1),
122                c.extract(2),
123                c.extract(3),
124                d.extract(0),
125                d.extract(1),
126                d.extract(2),
127                d.extract(3),
128            ))
129        }
130        #[inline(always)]
131        pub fn splat(a: u32x4) -> Self {
132            u32x4x4::from((a, a, a, a))
133        }
134        #[inline(always)]
135        pub fn into_parts(self) -> (u32x4, u32x4, u32x4, u32x4) {
136            let a = u32x4::new(
137                self.0.extract(0),
138                self.0.extract(1),
139                self.0.extract(2),
140                self.0.extract(3),
141            );
142            let b = u32x4::new(
143                self.0.extract(4),
144                self.0.extract(5),
145                self.0.extract(6),
146                self.0.extract(7),
147            );
148            let c = u32x4::new(
149                self.0.extract(8),
150                self.0.extract(9),
151                self.0.extract(10),
152                self.0.extract(11),
153            );
154            let d = u32x4::new(
155                self.0.extract(12),
156                self.0.extract(13),
157                self.0.extract(14),
158                self.0.extract(15),
159            );
160            (a, b, c, d)
161        }
162    }
163    impl BitXor for u32x4x4 {
164        type Output = u32x4x4;
165        #[inline(always)]
166        fn bitxor(self, rhs: Self) -> Self::Output {
167            u32x4x4(self.0 ^ rhs.0)
168        }
169    }
170    impl BitOr for u32x4x4 {
171        type Output = Self;
172        #[inline(always)]
173        fn bitor(self, rhs: Self) -> Self::Output {
174            u32x4x4(self.0 | rhs.0)
175        }
176    }
177    impl BitAnd for u32x4x4 {
178        type Output = Self;
179        #[inline(always)]
180        fn bitand(self, rhs: Self) -> Self::Output {
181            u32x4x4(self.0 & rhs.0)
182        }
183    }
184    impl BitXorAssign for u32x4x4 {
185        #[inline(always)]
186        fn bitxor_assign(&mut self, rhs: Self) {
187            self.0 ^= rhs.0;
188        }
189    }
190    impl Add for u32x4x4 {
191        type Output = Self;
192        #[inline(always)]
193        fn add(self, rhs: Self) -> Self::Output {
194            u32x4x4(self.0 + rhs.0)
195        }
196    }
197    impl AddAssign for u32x4x4 {
198        #[inline(always)]
199        fn add_assign(&mut self, rhs: Self) {
200            self.0 += rhs.0;
201        }
202    }
203    impl RotateWordsRight for u32x4x4 {
204        type Output = Self;
205        #[inline(always)]
206        fn rotate_words_right(self, i: u32) -> Self::Output {
207            match i {
208                0 => self,
209                1 => u32x4x4(shuffle!(
210                    self.0,
211                    [3, 0, 1, 2, 7, 4, 5, 6, 11, 8, 9, 10, 15, 12, 13, 14]
212                )),
213                2 => u32x4x4(shuffle!(
214                    self.0,
215                    [2, 3, 0, 1, 6, 7, 4, 5, 10, 11, 8, 9, 14, 15, 12, 13]
216                )),
217                3 => u32x4x4(shuffle!(
218                    self.0,
219                    [1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12]
220                )),
221                _ => panic!("rotate_words_right index must be in the range 0..4"),
222            }
223        }
224    }
225    impl SplatRotateRight for u32x4x4 {
226        type Output = Self;
227        #[inline(always)]
228        fn splat_rotate_right(self, i: u32) -> Self::Output {
229            u32x4x4(self.0.rotate_right(u32x16::splat(i)))
230        }
231    }
232}