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
146impl Not for u16x16 {
147 type Output = Self;
148 #[inline]
149 fn not(self) -> Self {
150 pick! {
151 if #[cfg(target_feature="avx2")] {
152 Self { avx2: self.avx2.not() }
153 } else {
154 Self {
155 a : self.a.not(),
156 b : self.b.not(),
157 }
158 }
159 }
160 }
161}
162
163macro_rules! impl_shl_t_for_u16x16 {
164 ($($shift_type:ty),+ $(,)?) => {
165 $(impl Shl<$shift_type> for u16x16 {
166 type Output = Self;
167 #[inline]
169 #[must_use]
170 fn shl(self, rhs: $shift_type) -> Self::Output {
171 pick! {
172 if #[cfg(target_feature="avx2")] {
173 let shift = cast([rhs as u64, 0]);
174 Self { avx2: shl_all_u16_m256i(self.avx2, shift) }
175 } else {
176 Self {
177 a : self.a.shl(rhs),
178 b : self.b.shl(rhs),
179 }
180 }
181 }
182 }
183 })+
184 };
185}
186impl_shl_t_for_u16x16!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
187
188macro_rules! impl_shr_t_for_u16x16 {
189 ($($shift_type:ty),+ $(,)?) => {
190 $(impl Shr<$shift_type> for u16x16 {
191 type Output = Self;
192 #[inline]
194 #[must_use]
195 fn shr(self, rhs: $shift_type) -> Self::Output {
196 pick! {
197 if #[cfg(target_feature="avx2")] {
198 let shift = cast([rhs as u64, 0]);
199 Self { avx2: shr_all_u16_m256i(self.avx2, shift) }
200 } else {
201 Self {
202 a : self.a.shr(rhs),
203 b : self.b.shr(rhs),
204 }
205 }
206 }
207 }
208 })+
209 };
210}
211impl_shr_t_for_u16x16!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
212
213impl CmpEq for u16x16 {
214 type Output = Self;
215 #[inline]
216 #[must_use]
217 fn cmp_eq(self, rhs: Self) -> Self::Output {
218 pick! {
219 if #[cfg(target_feature="avx2")] {
220 Self { avx2: cmp_eq_mask_i16_m256i(self.avx2, rhs.avx2) }
221 } else {
222 Self {
223 a : self.a.cmp_eq(rhs.a),
224 b : self.b.cmp_eq(rhs.b),
225 }
226 }
227 }
228 }
229}
230
231impl Mul for u16x16 {
232 type Output = Self;
233 #[inline]
234 #[must_use]
235 fn mul(self, rhs: Self) -> Self::Output {
236 pick! {
237 if #[cfg(target_feature="avx2")] {
238 Self { avx2: mul_i16_keep_low_m256i(self.avx2, rhs.avx2) }
240 } else {
241 Self {
242 a : self.a.mul(rhs.a),
243 b : self.b.mul(rhs.b),
244 }
245 }
246 }
247 }
248}
249
250impl From<u8x16> for u16x16 {
251 #[inline]
253 #[must_use]
254 fn from(v: u8x16) -> Self {
255 pick! {
256 if #[cfg(target_feature="avx2")] {
257 u16x16 { avx2:convert_to_i16_m256i_from_u8_m128i(v.sse) }
258 } else if #[cfg(target_feature="sse2")] {
259 u16x16 {
260 a: u16x8 { sse: shr_imm_u16_m128i::<8>( unpack_low_i8_m128i(v.sse, v.sse)) },
261 b: u16x8 { sse: shr_imm_u16_m128i::<8>( unpack_high_i8_m128i(v.sse, v.sse)) },
262 }
263 } else {
264
265 u16x16::new([
266 v.as_array_ref()[0] as u16,
267 v.as_array_ref()[1] as u16,
268 v.as_array_ref()[2] as u16,
269 v.as_array_ref()[3] as u16,
270 v.as_array_ref()[4] as u16,
271 v.as_array_ref()[5] as u16,
272 v.as_array_ref()[6] as u16,
273 v.as_array_ref()[7] as u16,
274 v.as_array_ref()[8] as u16,
275 v.as_array_ref()[9] as u16,
276 v.as_array_ref()[10] as u16,
277 v.as_array_ref()[11] as u16,
278 v.as_array_ref()[12] as u16,
279 v.as_array_ref()[13] as u16,
280 v.as_array_ref()[14] as u16,
281 v.as_array_ref()[15] as u16,
282 ])
283 }
284 }
285 }
286}
287
288impl u16x16 {
289 #[inline]
290 #[must_use]
291 pub const fn new(array: [u16; 16]) -> Self {
292 unsafe { core::mem::transmute(array) }
293 }
294
295 #[inline]
296 #[must_use]
297 pub fn blend(self, t: Self, f: Self) -> Self {
298 pick! {
299 if #[cfg(target_feature="avx2")] {
300 Self { avx2: blend_varying_i8_m256i(f.avx2, t.avx2, self.avx2) }
301 } else {
302 Self {
303 a : self.a.blend(t.a, f.a),
304 b : self.b.blend(t.b, f.b),
305 }
306 }
307 }
308 }
309
310 #[inline]
311 #[must_use]
312 pub fn max(self, rhs: Self) -> Self {
313 pick! {
314 if #[cfg(target_feature="avx2")] {
315 Self { avx2: max_u16_m256i(self.avx2, rhs.avx2) }
316 } else {
317 Self {
318 a : self.a.max(rhs.a),
319 b : self.b.max(rhs.b),
320 }
321 }
322 }
323 }
324 #[inline]
325 #[must_use]
326 pub fn min(self, rhs: Self) -> Self {
327 pick! {
328 if #[cfg(target_feature="avx2")] {
329 Self { avx2: min_u16_m256i(self.avx2, rhs.avx2) }
330 } else {
331 Self {
332 a : self.a.min(rhs.a),
333 b : self.b.min(rhs.b),
334 }
335 }
336 }
337 }
338
339 #[inline]
340 #[must_use]
341 pub fn saturating_add(self, rhs: Self) -> Self {
342 pick! {
343 if #[cfg(target_feature="avx2")] {
344 Self { avx2: add_saturating_u16_m256i(self.avx2, rhs.avx2) }
345 } else {
346 Self {
347 a : self.a.saturating_add(rhs.a),
348 b : self.b.saturating_add(rhs.b),
349 }
350 }
351 }
352 }
353 #[inline]
354 #[must_use]
355 pub fn saturating_sub(self, rhs: Self) -> Self {
356 pick! {
357 if #[cfg(target_feature="avx2")] {
358 Self { avx2: sub_saturating_u16_m256i(self.avx2, rhs.avx2) }
359 } else {
360 Self {
361 a : self.a.saturating_sub(rhs.a),
362 b : self.b.saturating_sub(rhs.b),
363 }
364 }
365 }
366 }
367
368 #[inline]
369 pub fn to_array(self) -> [u16; 16] {
370 cast(self)
371 }
372
373 #[inline]
374 pub fn as_array_ref(&self) -> &[u16; 16] {
375 cast_ref(self)
376 }
377
378 #[inline]
379 pub fn as_array_mut(&mut self) -> &mut [u16; 16] {
380 cast_mut(self)
381 }
382}