1 use super::*;
2 
3 pick! {
4   if #[cfg(target_feature="sse2")] {
5     #[derive(Default, Clone, Copy, PartialEq, Eq)]
6     #[repr(C, align(16))]
7     pub struct i8x16 { sse: m128i }
8   } else if #[cfg(target_feature="simd128")] {
9     use core::arch::wasm32::*;
10 
11     #[derive(Clone, Copy)]
12     #[repr(transparent)]
13     pub struct i8x16 { simd: v128 }
14 
15     impl Default for i8x16 {
16       fn default() -> Self {
17         Self::splat(0)
18       }
19     }
20 
21     impl PartialEq for i8x16 {
22       fn eq(&self, other: &Self) -> bool {
23         u8x16_all_true(i8x16_eq(self.simd, other.simd))
24       }
25     }
26 
27     impl Eq for i8x16 { }
28   } else {
29     #[derive(Default, Clone, Copy, PartialEq, Eq)]
30     #[repr(C, align(16))]
31     pub struct i8x16 { arr: [i8;16] }
32   }
33 }
34 
35 int_uint_consts!(i8, 16, i8x16, i8x16, i8a16, const_i8_as_i8x16, 128);
36 
37 unsafe impl Zeroable for i8x16 {}
38 unsafe impl Pod for i8x16 {}
39 
40 impl Add for i8x16 {
41   type Output = Self;
42   #[inline]
43   #[must_use]
add(self, rhs: Self) -> Self::Output44   fn add(self, rhs: Self) -> Self::Output {
45     pick! {
46       if #[cfg(target_feature="sse2")] {
47         Self { sse: add_i8_m128i(self.sse, rhs.sse) }
48       } else if #[cfg(target_feature="simd128")] {
49         Self { simd: i8x16_add(self.simd, rhs.simd) }
50       } else {
51         Self { arr: [
52           self.arr[0].wrapping_add(rhs.arr[0]),
53           self.arr[1].wrapping_add(rhs.arr[1]),
54           self.arr[2].wrapping_add(rhs.arr[2]),
55           self.arr[3].wrapping_add(rhs.arr[3]),
56           self.arr[4].wrapping_add(rhs.arr[4]),
57           self.arr[5].wrapping_add(rhs.arr[5]),
58           self.arr[6].wrapping_add(rhs.arr[6]),
59           self.arr[7].wrapping_add(rhs.arr[7]),
60           self.arr[8].wrapping_add(rhs.arr[8]),
61           self.arr[9].wrapping_add(rhs.arr[9]),
62           self.arr[10].wrapping_add(rhs.arr[10]),
63           self.arr[11].wrapping_add(rhs.arr[11]),
64           self.arr[12].wrapping_add(rhs.arr[12]),
65           self.arr[13].wrapping_add(rhs.arr[13]),
66           self.arr[14].wrapping_add(rhs.arr[14]),
67           self.arr[15].wrapping_add(rhs.arr[15]),
68         ]}
69       }
70     }
71   }
72 }
73 
74 impl Sub for i8x16 {
75   type Output = Self;
76   #[inline]
77   #[must_use]
sub(self, rhs: Self) -> Self::Output78   fn sub(self, rhs: Self) -> Self::Output {
79     pick! {
80       if #[cfg(target_feature="sse2")] {
81         Self { sse: sub_i8_m128i(self.sse, rhs.sse) }
82       } else if #[cfg(target_feature="simd128")] {
83         Self { simd: i8x16_sub(self.simd, rhs.simd) }
84       } else {
85         Self { arr: [
86           self.arr[0].wrapping_sub(rhs.arr[0]),
87           self.arr[1].wrapping_sub(rhs.arr[1]),
88           self.arr[2].wrapping_sub(rhs.arr[2]),
89           self.arr[3].wrapping_sub(rhs.arr[3]),
90           self.arr[4].wrapping_sub(rhs.arr[4]),
91           self.arr[5].wrapping_sub(rhs.arr[5]),
92           self.arr[6].wrapping_sub(rhs.arr[6]),
93           self.arr[7].wrapping_sub(rhs.arr[7]),
94           self.arr[8].wrapping_sub(rhs.arr[8]),
95           self.arr[9].wrapping_sub(rhs.arr[9]),
96           self.arr[10].wrapping_sub(rhs.arr[10]),
97           self.arr[11].wrapping_sub(rhs.arr[11]),
98           self.arr[12].wrapping_sub(rhs.arr[12]),
99           self.arr[13].wrapping_sub(rhs.arr[13]),
100           self.arr[14].wrapping_sub(rhs.arr[14]),
101           self.arr[15].wrapping_sub(rhs.arr[15]),
102         ]}
103       }
104     }
105   }
106 }
107 
108 impl Add<i8> for i8x16 {
109   type Output = Self;
110   #[inline]
111   #[must_use]
add(self, rhs: i8) -> Self::Output112   fn add(self, rhs: i8) -> Self::Output {
113     self.add(Self::splat(rhs))
114   }
115 }
116 
117 impl Sub<i8> for i8x16 {
118   type Output = Self;
119   #[inline]
120   #[must_use]
sub(self, rhs: i8) -> Self::Output121   fn sub(self, rhs: i8) -> Self::Output {
122     self.sub(Self::splat(rhs))
123   }
124 }
125 
126 impl Add<i8x16> for i8 {
127   type Output = i8x16;
128   #[inline]
129   #[must_use]
add(self, rhs: i8x16) -> Self::Output130   fn add(self, rhs: i8x16) -> Self::Output {
131     i8x16::splat(self).add(rhs)
132   }
133 }
134 
135 impl Sub<i8x16> for i8 {
136   type Output = i8x16;
137   #[inline]
138   #[must_use]
sub(self, rhs: i8x16) -> Self::Output139   fn sub(self, rhs: i8x16) -> Self::Output {
140     i8x16::splat(self).sub(rhs)
141   }
142 }
143 
144 impl BitAnd for i8x16 {
145   type Output = Self;
146   #[inline]
147   #[must_use]
bitand(self, rhs: Self) -> Self::Output148   fn bitand(self, rhs: Self) -> Self::Output {
149     pick! {
150       if #[cfg(target_feature="sse2")] {
151         Self { sse: bitand_m128i(self.sse, rhs.sse) }
152       } else if #[cfg(target_feature="simd128")] {
153         Self { simd: v128_and(self.simd, rhs.simd) }
154       } else {
155         Self { arr: [
156           self.arr[0].bitand(rhs.arr[0]),
157           self.arr[1].bitand(rhs.arr[1]),
158           self.arr[2].bitand(rhs.arr[2]),
159           self.arr[3].bitand(rhs.arr[3]),
160           self.arr[4].bitand(rhs.arr[4]),
161           self.arr[5].bitand(rhs.arr[5]),
162           self.arr[6].bitand(rhs.arr[6]),
163           self.arr[7].bitand(rhs.arr[7]),
164           self.arr[8].bitand(rhs.arr[8]),
165           self.arr[9].bitand(rhs.arr[9]),
166           self.arr[10].bitand(rhs.arr[10]),
167           self.arr[11].bitand(rhs.arr[11]),
168           self.arr[12].bitand(rhs.arr[12]),
169           self.arr[13].bitand(rhs.arr[13]),
170           self.arr[14].bitand(rhs.arr[14]),
171           self.arr[15].bitand(rhs.arr[15]),
172         ]}
173       }
174     }
175   }
176 }
177 
178 impl BitOr for i8x16 {
179   type Output = Self;
180   #[inline]
181   #[must_use]
bitor(self, rhs: Self) -> Self::Output182   fn bitor(self, rhs: Self) -> Self::Output {
183     pick! {
184       if #[cfg(target_feature="sse2")] {
185         Self { sse: bitor_m128i(self.sse, rhs.sse) }
186       } else if #[cfg(target_feature="simd128")] {
187         Self { simd: v128_or(self.simd, rhs.simd) }
188       } else {
189         Self { arr: [
190           self.arr[0].bitor(rhs.arr[0]),
191           self.arr[1].bitor(rhs.arr[1]),
192           self.arr[2].bitor(rhs.arr[2]),
193           self.arr[3].bitor(rhs.arr[3]),
194           self.arr[4].bitor(rhs.arr[4]),
195           self.arr[5].bitor(rhs.arr[5]),
196           self.arr[6].bitor(rhs.arr[6]),
197           self.arr[7].bitor(rhs.arr[7]),
198           self.arr[8].bitor(rhs.arr[8]),
199           self.arr[9].bitor(rhs.arr[9]),
200           self.arr[10].bitor(rhs.arr[10]),
201           self.arr[11].bitor(rhs.arr[11]),
202           self.arr[12].bitor(rhs.arr[12]),
203           self.arr[13].bitor(rhs.arr[13]),
204           self.arr[14].bitor(rhs.arr[14]),
205           self.arr[15].bitor(rhs.arr[15]),
206         ]}
207       }
208     }
209   }
210 }
211 
212 impl BitXor for i8x16 {
213   type Output = Self;
214   #[inline]
215   #[must_use]
bitxor(self, rhs: Self) -> Self::Output216   fn bitxor(self, rhs: Self) -> Self::Output {
217     pick! {
218       if #[cfg(target_feature="sse2")] {
219         Self { sse: bitxor_m128i(self.sse, rhs.sse) }
220       } else if #[cfg(target_feature="simd128")] {
221         Self { simd: v128_xor(self.simd, rhs.simd) }
222       } else {
223         Self { arr: [
224           self.arr[0].bitxor(rhs.arr[0]),
225           self.arr[1].bitxor(rhs.arr[1]),
226           self.arr[2].bitxor(rhs.arr[2]),
227           self.arr[3].bitxor(rhs.arr[3]),
228           self.arr[4].bitxor(rhs.arr[4]),
229           self.arr[5].bitxor(rhs.arr[5]),
230           self.arr[6].bitxor(rhs.arr[6]),
231           self.arr[7].bitxor(rhs.arr[7]),
232           self.arr[8].bitxor(rhs.arr[8]),
233           self.arr[9].bitxor(rhs.arr[9]),
234           self.arr[10].bitxor(rhs.arr[10]),
235           self.arr[11].bitxor(rhs.arr[11]),
236           self.arr[12].bitxor(rhs.arr[12]),
237           self.arr[13].bitxor(rhs.arr[13]),
238           self.arr[14].bitxor(rhs.arr[14]),
239           self.arr[15].bitxor(rhs.arr[15]),
240         ]}
241       }
242     }
243   }
244 }
245 
246 impl CmpEq for i8x16 {
247   type Output = Self;
248   #[inline]
249   #[must_use]
cmp_eq(self, rhs: Self) -> Self::Output250   fn cmp_eq(self, rhs: Self) -> Self::Output {
251     pick! {
252       if #[cfg(target_feature="sse2")] {
253         Self { sse: cmp_eq_mask_i8_m128i(self.sse, rhs.sse) }
254       } else if #[cfg(target_feature="simd128")] {
255         Self { simd: i8x16_eq(self.simd, rhs.simd) }
256       } else {
257         Self { arr: [
258           if self.arr[0] == rhs.arr[0] { -1 } else { 0 },
259           if self.arr[1] == rhs.arr[1] { -1 } else { 0 },
260           if self.arr[2] == rhs.arr[2] { -1 } else { 0 },
261           if self.arr[3] == rhs.arr[3] { -1 } else { 0 },
262           if self.arr[4] == rhs.arr[4] { -1 } else { 0 },
263           if self.arr[5] == rhs.arr[5] { -1 } else { 0 },
264           if self.arr[6] == rhs.arr[6] { -1 } else { 0 },
265           if self.arr[7] == rhs.arr[7] { -1 } else { 0 },
266           if self.arr[8] == rhs.arr[8] { -1 } else { 0 },
267           if self.arr[9] == rhs.arr[9] { -1 } else { 0 },
268           if self.arr[10] == rhs.arr[10] { -1 } else { 0 },
269           if self.arr[11] == rhs.arr[11] { -1 } else { 0 },
270           if self.arr[12] == rhs.arr[12] { -1 } else { 0 },
271           if self.arr[13] == rhs.arr[13] { -1 } else { 0 },
272           if self.arr[14] == rhs.arr[14] { -1 } else { 0 },
273           if self.arr[15] == rhs.arr[15] { -1 } else { 0 },
274         ]}
275       }
276     }
277   }
278 }
279 
280 impl CmpGt for i8x16 {
281   type Output = Self;
282   #[inline]
283   #[must_use]
cmp_gt(self, rhs: Self) -> Self::Output284   fn cmp_gt(self, rhs: Self) -> Self::Output {
285     pick! {
286       if #[cfg(target_feature="sse2")] {
287         Self { sse: cmp_gt_mask_i8_m128i(self.sse, rhs.sse) }
288       } else if #[cfg(target_feature="simd128")] {
289         Self { simd: i8x16_gt(self.simd, rhs.simd) }
290       } else {
291         Self { arr: [
292           if self.arr[0] > rhs.arr[0] { -1 } else { 0 },
293           if self.arr[1] > rhs.arr[1] { -1 } else { 0 },
294           if self.arr[2] > rhs.arr[2] { -1 } else { 0 },
295           if self.arr[3] > rhs.arr[3] { -1 } else { 0 },
296           if self.arr[4] > rhs.arr[4] { -1 } else { 0 },
297           if self.arr[5] > rhs.arr[5] { -1 } else { 0 },
298           if self.arr[6] > rhs.arr[6] { -1 } else { 0 },
299           if self.arr[7] > rhs.arr[7] { -1 } else { 0 },
300           if self.arr[8] > rhs.arr[8] { -1 } else { 0 },
301           if self.arr[9] > rhs.arr[9] { -1 } else { 0 },
302           if self.arr[10] > rhs.arr[10] { -1 } else { 0 },
303           if self.arr[11] > rhs.arr[11] { -1 } else { 0 },
304           if self.arr[12] > rhs.arr[12] { -1 } else { 0 },
305           if self.arr[13] > rhs.arr[13] { -1 } else { 0 },
306           if self.arr[14] > rhs.arr[14] { -1 } else { 0 },
307           if self.arr[15] > rhs.arr[15] { -1 } else { 0 },
308         ]}
309       }
310     }
311   }
312 }
313 
314 impl CmpLt for i8x16 {
315   type Output = Self;
316   #[inline]
317   #[must_use]
cmp_lt(self, rhs: Self) -> Self::Output318   fn cmp_lt(self, rhs: Self) -> Self::Output {
319     pick! {
320       if #[cfg(target_feature="sse2")] {
321         Self { sse: cmp_lt_mask_i8_m128i(self.sse, rhs.sse) }
322       } else if #[cfg(target_feature="simd128")] {
323         Self { simd: i8x16_lt(self.simd, rhs.simd) }
324       } else {
325         Self { arr: [
326           if self.arr[0] < rhs.arr[0] { -1 } else { 0 },
327           if self.arr[1] < rhs.arr[1] { -1 } else { 0 },
328           if self.arr[2] < rhs.arr[2] { -1 } else { 0 },
329           if self.arr[3] < rhs.arr[3] { -1 } else { 0 },
330           if self.arr[4] < rhs.arr[4] { -1 } else { 0 },
331           if self.arr[5] < rhs.arr[5] { -1 } else { 0 },
332           if self.arr[6] < rhs.arr[6] { -1 } else { 0 },
333           if self.arr[7] < rhs.arr[7] { -1 } else { 0 },
334           if self.arr[8] < rhs.arr[8] { -1 } else { 0 },
335           if self.arr[9] < rhs.arr[9] { -1 } else { 0 },
336           if self.arr[10] < rhs.arr[10] { -1 } else { 0 },
337           if self.arr[11] < rhs.arr[11] { -1 } else { 0 },
338           if self.arr[12] < rhs.arr[12] { -1 } else { 0 },
339           if self.arr[13] < rhs.arr[13] { -1 } else { 0 },
340           if self.arr[14] < rhs.arr[14] { -1 } else { 0 },
341           if self.arr[15] < rhs.arr[15] { -1 } else { 0 },
342         ]}
343       }
344     }
345   }
346 }
347 
348 impl i8x16 {
349   #[inline]
350   #[must_use]
new(array: [i8; 16]) -> Self351   pub fn new(array: [i8; 16]) -> Self {
352     Self::from(array)
353   }
354   #[inline]
355   #[must_use]
blend(self, t: Self, f: Self) -> Self356   pub fn blend(self, t: Self, f: Self) -> Self {
357     pick! {
358       if #[cfg(target_feature="sse4.1")] {
359         Self { sse: blend_varying_i8_m128i(f.sse, t.sse, self.sse) }
360       } else if #[cfg(target_feature="simd128")] {
361         Self { simd: v128_bitselect(t.simd, f.simd, self.simd) }
362       } else {
363         generic_bit_blend(self, t, f)
364       }
365     }
366   }
367   #[inline]
368   #[must_use]
abs(self) -> Self369   pub fn abs(self) -> Self {
370     pick! {
371       if #[cfg(target_feature="ssse3")] {
372         Self { sse: abs_i8_m128i(self.sse) }
373       } else if #[cfg(target_feature="simd128")] {
374         Self { simd: i8x16_abs(self.simd) }
375       } else {
376         let arr: [i8; 16] = cast(self);
377         cast([
378           arr[0].wrapping_abs(),
379           arr[1].wrapping_abs(),
380           arr[2].wrapping_abs(),
381           arr[3].wrapping_abs(),
382           arr[4].wrapping_abs(),
383           arr[5].wrapping_abs(),
384           arr[6].wrapping_abs(),
385           arr[7].wrapping_abs(),
386           arr[8].wrapping_abs(),
387           arr[9].wrapping_abs(),
388           arr[10].wrapping_abs(),
389           arr[11].wrapping_abs(),
390           arr[12].wrapping_abs(),
391           arr[13].wrapping_abs(),
392           arr[14].wrapping_abs(),
393           arr[15].wrapping_abs(),
394         ])
395       }
396     }
397   }
398   #[inline]
399   #[must_use]
max(self, rhs: Self) -> Self400   pub fn max(self, rhs: Self) -> Self {
401     pick! {
402       if #[cfg(target_feature="sse4.1")] {
403         Self { sse: max_i8_m128i(self.sse, rhs.sse) }
404       } else if #[cfg(target_feature="simd128")] {
405         Self { simd: i8x16_max(self.simd, rhs.simd) }
406       } else {
407         self.cmp_lt(rhs).blend(rhs, self)
408       }
409     }
410   }
411   #[inline]
412   #[must_use]
min(self, rhs: Self) -> Self413   pub fn min(self, rhs: Self) -> Self {
414     pick! {
415       if #[cfg(target_feature="sse4.1")] {
416         Self { sse: min_i8_m128i(self.sse, rhs.sse) }
417       } else if #[cfg(target_feature="simd128")] {
418         Self { simd: i8x16_min(self.simd, rhs.simd) }
419       } else {
420         self.cmp_lt(rhs).blend(self, rhs)
421       }
422     }
423   }
424 
425   #[inline]
426   #[must_use]
move_mask(self) -> i32427   pub fn move_mask(self) -> i32 {
428     pick! {
429       if #[cfg(target_feature="sse2")] {
430         move_mask_i8_m128i(self.sse)
431       } else if #[cfg(target_feature="simd128")] {
432         i8x16_bitmask(self.simd) as i32
433       } else {
434         ((self.arr[0] < 0) as i32) << 0 |
435         ((self.arr[1] < 0) as i32) << 1 |
436         ((self.arr[2] < 0) as i32) << 2 |
437         ((self.arr[3] < 0) as i32) << 3 |
438         ((self.arr[4] < 0) as i32) << 4 |
439         ((self.arr[5] < 0) as i32) << 5 |
440         ((self.arr[6] < 0) as i32) << 6 |
441         ((self.arr[7] < 0) as i32) << 7 |
442         ((self.arr[8] < 0) as i32) << 8 |
443         ((self.arr[9] < 0) as i32) << 9 |
444         ((self.arr[10] < 0) as i32) << 10 |
445         ((self.arr[11] < 0) as i32) << 11 |
446         ((self.arr[12] < 0) as i32) << 12 |
447         ((self.arr[13] < 0) as i32) << 13 |
448         ((self.arr[14] < 0) as i32) << 14 |
449         ((self.arr[15] < 0) as i32) << 15
450       }
451     }
452   }
453   #[inline]
454   #[must_use]
any(self) -> bool455   pub fn any(self) -> bool {
456     pick! {
457       if #[cfg(target_feature="simd128")] {
458         v128_any_true(self.simd)
459       } else {
460         self.move_mask() != 0
461       }
462     }
463   }
464   #[inline]
465   #[must_use]
all(self) -> bool466   pub fn all(self) -> bool {
467     pick! {
468       if #[cfg(target_feature="simd128")] {
469         u8x16_all_true(self.simd)
470       } else {
471         // sixteen lanes
472         self.move_mask() == 0b1111_1111_1111_1111
473       }
474     }
475   }
476   #[inline]
477   #[must_use]
none(self) -> bool478   pub fn none(self) -> bool {
479     !self.any()
480   }
481 
to_array(self) -> [i8; 16]482   pub fn to_array(self) -> [i8; 16] {
483     cast(self)
484   }
485 
as_array_ref(&self) -> &[i8; 16]486   pub fn as_array_ref(&self) -> &[i8; 16] {
487     cast_ref(self)
488   }
489 }
490