1use super::*;
2
3pick! {
4 if #[cfg(target_feature="avx2")] {
5 #[derive(Default, Clone, Copy, PartialEq, Eq)]
6 #[repr(C, align(32))]
7 pub struct u16x16 { pub(crate) avx2: m256i }
8 } else {
9 #[derive(Default, Clone, Copy, PartialEq, Eq)]
10 #[repr(C, align(32))]
11 pub struct u16x16 { pub(crate) a : u16x8, pub(crate) b : u16x8 }
12 }
13}
14
15int_uint_consts!(u16, 16, u16x16, 256);
16
17unsafe impl Zeroable for u16x16 {}
18unsafe impl Pod for u16x16 {}
19
20impl Add for u16x16 {
21 type Output = Self;
22 #[inline]
23 #[must_use]
24 fn add(self, rhs: Self) -> Self::Output {
25 pick! {
26 if #[cfg(target_feature="avx2")] {
27 Self { avx2: add_i16_m256i(self.avx2, rhs.avx2) }
28 } else {
29 Self {
30 a : self.a.add(rhs.a),
31 b : self.b.add(rhs.b),
32 }
33 }
34 }
35 }
36}
37
38impl Sub for u16x16 {
39 type Output = Self;
40 #[inline]
41 #[must_use]
42 fn sub(self, rhs: Self) -> Self::Output {
43 pick! {
44 if #[cfg(target_feature="avx2")] {
45 Self { avx2: sub_i16_m256i(self.avx2, rhs.avx2) }
46 } else {
47 Self {
48 a : self.a.sub(rhs.a),
49 b : self.b.sub(rhs.b),
50 }
51 }
52 }
53 }
54}
55
56impl Add<u16> for u16x16 {
57 type Output = Self;
58 #[inline]
59 #[must_use]
60 fn add(self, rhs: u16) -> Self::Output {
61 self.add(Self::splat(rhs))
62 }
63}
64
65impl Sub<u16> for u16x16 {
66 type Output = Self;
67 #[inline]
68 #[must_use]
69 fn sub(self, rhs: u16) -> Self::Output {
70 self.sub(Self::splat(rhs))
71 }
72}
73
74impl Add<u16x16> for u16 {
75 type Output = u16x16;
76 #[inline]
77 #[must_use]
78 fn add(self, rhs: u16x16) -> Self::Output {
79 u16x16::splat(self).add(rhs)
80 }
81}
82
83impl Sub<u16x16> for u16 {
84 type Output = u16x16;
85 #[inline]
86 #[must_use]
87 fn sub(self, rhs: u16x16) -> Self::Output {
88 u16x16::splat(self).sub(rhs)
89 }
90}
91
92impl BitAnd for u16x16 {
93 type Output = Self;
94 #[inline]
95 #[must_use]
96 fn bitand(self, rhs: Self) -> Self::Output {
97 pick! {
98 if #[cfg(target_feature="avx2")] {
99 Self { avx2: bitand_m256i(self.avx2, rhs.avx2) }
100 } else {
101 Self {
102 a : self.a.bitand(rhs.a),
103 b : self.b.bitand(rhs.b),
104 }
105 }
106 }
107 }
108}
109
110impl BitOr for u16x16 {
111 type Output = Self;
112 #[inline]
113 #[must_use]
114 fn bitor(self, rhs: Self) -> Self::Output {
115 pick! {
116 if #[cfg(target_feature="avx2")] {
117 Self { avx2: bitor_m256i(self.avx2, rhs.avx2) }
118 } else {
119 Self {
120 a : self.a.bitor(rhs.a),
121 b : self.b.bitor(rhs.b),
122 }
123 }
124 }
125 }
126}
127
128impl BitXor for u16x16 {
129 type Output = Self;
130 #[inline]
131 #[must_use]
132 fn bitxor(self, rhs: Self) -> Self::Output {
133 pick! {
134 if #[cfg(target_feature="avx2")] {
135 Self { avx2: bitxor_m256i(self.avx2, rhs.avx2) }
136 } else {
137 Self {
138 a : self.a.bitxor(rhs.a),
139 b : self.b.bitxor(rhs.b),
140 }
141 }
142 }
143 }
144}
145
146macro_rules! impl_shl_t_for_u16x16 {
147 ($($shift_type:ty),+ $(,)?) => {
148 $(impl Shl<$shift_type> for u16x16 {
149 type Output = Self;
150 #[inline]
152 #[must_use]
153 fn shl(self, rhs: $shift_type) -> Self::Output {
154 pick! {
155 if #[cfg(target_feature="avx2")] {
156 let shift = cast([rhs as u64, 0]);
157 Self { avx2: shl_all_u16_m256i(self.avx2, shift) }
158 } else {
159 Self {
160 a : self.a.shl(rhs),
161 b : self.b.shl(rhs),
162 }
163 }
164 }
165 }
166 })+
167 };
168}
169impl_shl_t_for_u16x16!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
170
171macro_rules! impl_shr_t_for_u16x16 {
172 ($($shift_type:ty),+ $(,)?) => {
173 $(impl Shr<$shift_type> for u16x16 {
174 type Output = Self;
175 #[inline]
177 #[must_use]
178 fn shr(self, rhs: $shift_type) -> Self::Output {
179 pick! {
180 if #[cfg(target_feature="avx2")] {
181 let shift = cast([rhs as u64, 0]);
182 Self { avx2: shr_all_u16_m256i(self.avx2, shift) }
183 } else {
184 Self {
185 a : self.a.shr(rhs),
186 b : self.b.shr(rhs),
187 }
188 }
189 }
190 }
191 })+
192 };
193}
194impl_shr_t_for_u16x16!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
195
196impl CmpEq for u16x16 {
197 type Output = Self;
198 #[inline]
199 #[must_use]
200 fn cmp_eq(self, rhs: Self) -> Self::Output {
201 pick! {
202 if #[cfg(target_feature="avx2")] {
203 Self { avx2: cmp_eq_mask_i16_m256i(self.avx2, rhs.avx2) }
204 } else {
205 Self {
206 a : self.a.cmp_eq(rhs.a),
207 b : self.b.cmp_eq(rhs.b),
208 }
209 }
210 }
211 }
212}
213
214impl Mul for u16x16 {
215 type Output = Self;
216 #[inline]
217 #[must_use]
218 fn mul(self, rhs: Self) -> Self::Output {
219 pick! {
220 if #[cfg(target_feature="avx2")] {
221 Self { avx2: mul_i16_keep_low_m256i(self.avx2, rhs.avx2) }
223 } else {
224 Self {
225 a : self.a.mul(rhs.a),
226 b : self.b.mul(rhs.b),
227 }
228 }
229 }
230 }
231}
232
233impl From<u8x16> for u16x16 {
234 #[inline]
236 #[must_use]
237 fn from(v: u8x16) -> Self {
238 pick! {
239 if #[cfg(target_feature="avx2")] {
240 u16x16 { avx2:convert_to_i16_m256i_from_u8_m128i(v.sse) }
241 } else if #[cfg(target_feature="sse2")] {
242 u16x16 {
243 a: u16x8 { sse: shr_imm_u16_m128i::<8>( unpack_low_i8_m128i(v.sse, v.sse)) },
244 b: u16x8 { sse: shr_imm_u16_m128i::<8>( unpack_high_i8_m128i(v.sse, v.sse)) },
245 }
246 } else {
247
248 u16x16::new([
249 v.as_array_ref()[0] as u16,
250 v.as_array_ref()[1] as u16,
251 v.as_array_ref()[2] as u16,
252 v.as_array_ref()[3] as u16,
253 v.as_array_ref()[4] as u16,
254 v.as_array_ref()[5] as u16,
255 v.as_array_ref()[6] as u16,
256 v.as_array_ref()[7] as u16,
257 v.as_array_ref()[8] as u16,
258 v.as_array_ref()[9] as u16,
259 v.as_array_ref()[10] as u16,
260 v.as_array_ref()[11] as u16,
261 v.as_array_ref()[12] as u16,
262 v.as_array_ref()[13] as u16,
263 v.as_array_ref()[14] as u16,
264 v.as_array_ref()[15] as u16,
265 ])
266 }
267 }
268 }
269}
270
271impl u16x16 {
272 #[inline]
273 #[must_use]
274 pub const fn new(array: [u16; 16]) -> Self {
275 unsafe { core::intrinsics::transmute(array) }
276 }
277
278 #[inline]
279 #[must_use]
280 pub fn blend(self, t: Self, f: Self) -> Self {
281 pick! {
282 if #[cfg(target_feature="avx2")] {
283 Self { avx2: blend_varying_i8_m256i(f.avx2, t.avx2, self.avx2) }
284 } else {
285 Self {
286 a : self.a.blend(t.a, f.a),
287 b : self.b.blend(t.b, f.b),
288 }
289 }
290 }
291 }
292
293 #[inline]
294 #[must_use]
295 pub fn max(self, rhs: Self) -> Self {
296 pick! {
297 if #[cfg(target_feature="avx2")] {
298 Self { avx2: max_u16_m256i(self.avx2, rhs.avx2) }
299 } else {
300 Self {
301 a : self.a.max(rhs.a),
302 b : self.b.max(rhs.b),
303 }
304 }
305 }
306 }
307 #[inline]
308 #[must_use]
309 pub fn min(self, rhs: Self) -> Self {
310 pick! {
311 if #[cfg(target_feature="avx2")] {
312 Self { avx2: min_u16_m256i(self.avx2, rhs.avx2) }
313 } else {
314 Self {
315 a : self.a.min(rhs.a),
316 b : self.b.min(rhs.b),
317 }
318 }
319 }
320 }
321
322 #[inline]
323 #[must_use]
324 pub fn saturating_add(self, rhs: Self) -> Self {
325 pick! {
326 if #[cfg(target_feature="avx2")] {
327 Self { avx2: add_saturating_u16_m256i(self.avx2, rhs.avx2) }
328 } else {
329 Self {
330 a : self.a.saturating_add(rhs.a),
331 b : self.b.saturating_add(rhs.b),
332 }
333 }
334 }
335 }
336 #[inline]
337 #[must_use]
338 pub fn saturating_sub(self, rhs: Self) -> Self {
339 pick! {
340 if #[cfg(target_feature="avx2")] {
341 Self { avx2: sub_saturating_u16_m256i(self.avx2, rhs.avx2) }
342 } else {
343 Self {
344 a : self.a.saturating_sub(rhs.a),
345 b : self.b.saturating_sub(rhs.b),
346 }
347 }
348 }
349 }
350
351 #[inline]
352 pub fn to_array(self) -> [u16; 16] {
353 cast(self)
354 }
355
356 #[inline]
357 pub fn as_array_ref(&self) -> &[u16; 16] {
358 cast_ref(self)
359 }
360
361 #[inline]
362 pub fn as_array_mut(&mut self) -> &mut [u16; 16] {
363 cast_mut(self)
364 }
365}