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}