wide/
i8x32_.rs

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 i8x32 { avx: m256i }
8  } else {
9    #[derive(Default, Clone, Copy, PartialEq, Eq)]
10    #[repr(C, align(32))]
11    pub struct i8x32 { a : i8x16, b : i8x16 }
12  }
13}
14
15int_uint_consts!(i8, 32, i8x32, 256);
16
17unsafe impl Zeroable for i8x32 {}
18unsafe impl Pod for i8x32 {}
19
20impl AlignTo for i8x32 {
21  type Elem = i8;
22}
23
24impl Add for i8x32 {
25  type Output = Self;
26  #[inline]
27  fn add(self, rhs: Self) -> Self::Output {
28    pick! {
29      if #[cfg(target_feature="avx2")] {
30        Self { avx: add_i8_m256i(self.avx,rhs.avx) }
31      } else {
32        Self {
33          a : self.a.add(rhs.a),
34          b : self.b.add(rhs.b),
35        }
36      }
37    }
38  }
39}
40
41impl Sub for i8x32 {
42  type Output = Self;
43  #[inline]
44  fn sub(self, rhs: Self) -> Self::Output {
45    pick! {
46      if #[cfg(target_feature="avx2")] {
47        Self { avx: sub_i8_m256i(self.avx,rhs.avx) }
48      } else {
49        Self {
50          a : self.a.sub(rhs.a),
51          b : self.b.sub(rhs.b),
52        }
53      }
54    }
55  }
56}
57
58impl Add<i8> for i8x32 {
59  type Output = Self;
60  #[inline]
61  fn add(self, rhs: i8) -> Self::Output {
62    self.add(Self::splat(rhs))
63  }
64}
65
66impl Sub<i8> for i8x32 {
67  type Output = Self;
68  #[inline]
69  fn sub(self, rhs: i8) -> Self::Output {
70    self.sub(Self::splat(rhs))
71  }
72}
73
74impl Add<i8x32> for i8 {
75  type Output = i8x32;
76  #[inline]
77  fn add(self, rhs: i8x32) -> Self::Output {
78    i8x32::splat(self).add(rhs)
79  }
80}
81
82impl Sub<i8x32> for i8 {
83  type Output = i8x32;
84  #[inline]
85  fn sub(self, rhs: i8x32) -> Self::Output {
86    i8x32::splat(self).sub(rhs)
87  }
88}
89
90impl BitAnd for i8x32 {
91  type Output = Self;
92  #[inline]
93  fn bitand(self, rhs: Self) -> Self::Output {
94    pick! {
95      if #[cfg(target_feature="avx2")] {
96          Self { avx : bitand_m256i(self.avx,rhs.avx) }
97      } else {
98          Self {
99            a : self.a.bitand(rhs.a),
100            b : self.b.bitand(rhs.b),
101          }
102      }
103    }
104  }
105}
106
107impl BitOr for i8x32 {
108  type Output = Self;
109  #[inline]
110  fn bitor(self, rhs: Self) -> Self::Output {
111    pick! {
112      if #[cfg(target_feature="avx2")] {
113        Self { avx : bitor_m256i(self.avx,rhs.avx) }
114      } else {
115        Self {
116          a : self.a.bitor(rhs.a),
117          b : self.b.bitor(rhs.b),
118        }
119      }
120    }
121  }
122}
123
124impl BitXor for i8x32 {
125  type Output = Self;
126  #[inline]
127  fn bitxor(self, rhs: Self) -> Self::Output {
128    pick! {
129      if #[cfg(target_feature="avx2")] {
130        Self { avx : bitxor_m256i(self.avx,rhs.avx) }
131      } else {
132        Self {
133          a : self.a.bitxor(rhs.a),
134          b : self.b.bitxor(rhs.b),
135        }
136      }
137    }
138  }
139}
140
141impl CmpEq for i8x32 {
142  type Output = Self;
143  #[inline]
144  fn simd_eq(self, rhs: Self) -> Self::Output {
145    pick! {
146      if #[cfg(target_feature="avx2")] {
147        Self { avx : cmp_eq_mask_i8_m256i(self.avx,rhs.avx) }
148      } else {
149        Self {
150          a : self.a.simd_eq(rhs.a),
151          b : self.b.simd_eq(rhs.b),
152        }
153      }
154    }
155  }
156}
157
158impl CmpGt for i8x32 {
159  type Output = Self;
160  #[inline]
161  fn simd_gt(self, rhs: Self) -> Self::Output {
162    pick! {
163      if #[cfg(target_feature="avx2")] {
164        Self { avx : cmp_gt_mask_i8_m256i(self.avx,rhs.avx) }
165      } else {
166        Self {
167          a : self.a.simd_gt(rhs.a),
168          b : self.b.simd_gt(rhs.b),
169        }
170      }
171    }
172  }
173}
174
175impl CmpLt for i8x32 {
176  type Output = Self;
177  #[inline]
178  fn simd_lt(self, rhs: Self) -> Self::Output {
179    rhs.simd_gt(self)
180  }
181}
182
183impl Not for i8x32 {
184  type Output = Self;
185  #[inline]
186  fn not(self) -> Self {
187    pick! {
188      if #[cfg(target_feature="avx2")] {
189        Self { avx: self.avx.not()  }
190      } else {
191        Self {
192          a : self.a.not(),
193          b : self.b.not(),
194        }
195      }
196    }
197  }
198}
199
200impl i8x32 {
201  #[inline]
202  #[must_use]
203  pub const fn new(array: [i8; 32]) -> Self {
204    unsafe { core::mem::transmute(array) }
205  }
206  #[inline]
207  #[must_use]
208  pub fn blend(self, t: Self, f: Self) -> Self {
209    pick! {
210      if #[cfg(target_feature="avx2")] {
211        Self { avx: blend_varying_i8_m256i(f.avx, t.avx, self.avx) }
212      } else {
213        Self {
214          a : self.a.blend(t.a, f.a),
215          b : self.b.blend(t.b, f.b),
216        }
217      }
218    }
219  }
220  #[inline]
221  #[must_use]
222  pub fn abs(self) -> Self {
223    pick! {
224      if #[cfg(target_feature="avx2")] {
225        Self { avx: abs_i8_m256i(self.avx) }
226      } else {
227        Self {
228          a : self.a.abs(),
229          b : self.b.abs(),
230        }
231      }
232    }
233  }
234
235  #[inline]
236  #[must_use]
237  pub fn unsigned_abs(self) -> u8x32 {
238    pick! {
239      if #[cfg(target_feature="avx2")] {
240        u8x32 { avx: abs_i8_m256i(self.avx) }
241      } else {
242        u8x32 {
243          a : self.a.unsigned_abs(),
244          b : self.b.unsigned_abs(),
245        }
246      }
247    }
248  }
249
250  #[inline]
251  #[must_use]
252  pub fn max(self, rhs: Self) -> Self {
253    pick! {
254      if #[cfg(target_feature="avx2")] {
255        Self { avx: max_i8_m256i(self.avx,rhs.avx) }
256      } else {
257        Self {
258          a : self.a.max(rhs.a),
259          b : self.b.max(rhs.b),
260        }
261      }
262    }
263  }
264  #[inline]
265  #[must_use]
266  pub fn min(self, rhs: Self) -> Self {
267    pick! {
268      if #[cfg(target_feature="avx2")] {
269        Self { avx: min_i8_m256i(self.avx,rhs.avx) }
270      } else {
271        Self {
272          a : self.a.min(rhs.a),
273          b : self.b.min(rhs.b),
274        }
275      }
276    }
277  }
278
279  #[inline]
280  #[must_use]
281  pub fn saturating_add(self, rhs: Self) -> Self {
282    pick! {
283      if #[cfg(target_feature="avx2")] {
284        Self { avx: add_saturating_i8_m256i(self.avx, rhs.avx) }
285      } else {
286        Self {
287          a : self.a.saturating_add(rhs.a),
288          b : self.b.saturating_add(rhs.b),
289        }
290      }
291    }
292  }
293  #[inline]
294  #[must_use]
295  pub fn saturating_sub(self, rhs: Self) -> Self {
296    pick! {
297      if #[cfg(target_feature="avx2")] {
298        Self { avx: sub_saturating_i8_m256i(self.avx, rhs.avx) }
299      } else {
300        Self {
301          a : self.a.saturating_sub(rhs.a),
302          b : self.b.saturating_sub(rhs.b),
303        }
304      }
305    }
306  }
307
308  #[inline]
309  #[must_use]
310  #[doc(alias("movemask", "move_mask"))]
311  pub fn to_bitmask(self) -> u32 {
312    pick! {
313      if #[cfg(target_feature="avx2")] {
314        move_mask_i8_m256i(self.avx) as u32
315      } else {
316        self.a.to_bitmask() | (self.b.to_bitmask() << 16)
317      }
318    }
319  }
320
321  #[inline]
322  #[must_use]
323  pub fn any(self) -> bool {
324    pick! {
325      if #[cfg(target_feature="avx2")] {
326        move_mask_i8_m256i(self.avx) != 0
327      } else {
328        (self.a | self.b).any()
329      }
330    }
331  }
332
333  #[inline]
334  #[must_use]
335  pub fn all(self) -> bool {
336    pick! {
337      if #[cfg(target_feature="avx2")] {
338        move_mask_i8_m256i(self.avx) == -1
339      } else {
340        (self.a & self.b).all()
341      }
342    }
343  }
344
345  #[inline]
346  #[must_use]
347  pub fn none(self) -> bool {
348    !self.any()
349  }
350
351  /// Returns a new vector with lanes selected from the lanes of the first input
352  /// vector a specified in the second input vector `rhs`.
353  /// The indices i in range `[0, 15]` select the i-th element of `self`. For
354  /// indices outside of the range the resulting lane is `0`.
355  ///
356  /// This note that is the equivalent of two parallel swizzle operations on the
357  /// two halves of the vector, and the indexes each refer to the
358  /// corresponding half.
359  #[inline]
360  pub fn swizzle_half(self, rhs: i8x32) -> i8x32 {
361    pick! {
362      if #[cfg(target_feature="avx2")] {
363        Self { avx: shuffle_av_i8z_half_m256i(self.avx, rhs.saturating_add(i8x32::splat(0x60)).avx) }
364      } else {
365          Self {
366            a : self.a.swizzle(rhs.a),
367            b : self.b.swizzle(rhs.b),
368          }
369      }
370    }
371  }
372
373  /// Indices in the range `[0, 15]` will select the i-th element of `self`. If
374  /// the high bit of any element of `rhs` is set (negative) then the
375  /// corresponding output lane is guaranteed to be zero. Otherwise if the
376  /// element of `rhs` is within the range `[32, 127]` then the output lane is
377  /// either `0` or `self[rhs[i] % 16]` depending on the implementation.
378  ///
379  /// This is the equivalent to two parallel swizzle operations on the two
380  /// halves of the vector, and the indexes each refer to their corresponding
381  /// half.
382  #[inline]
383  pub fn swizzle_half_relaxed(self, rhs: i8x32) -> i8x32 {
384    pick! {
385      if #[cfg(target_feature="avx2")] {
386        Self { avx: shuffle_av_i8z_half_m256i(self.avx, rhs.avx) }
387      } else {
388        Self {
389          a : self.a.swizzle_relaxed(rhs.a),
390          b : self.b.swizzle_relaxed(rhs.b),
391        }
392      }
393    }
394  }
395
396  #[inline]
397  pub fn to_array(self) -> [i8; 32] {
398    cast(self)
399  }
400
401  #[inline]
402  pub fn as_array(&self) -> &[i8; 32] {
403    cast_ref(self)
404  }
405
406  #[inline]
407  pub fn as_mut_array(&mut self) -> &mut [i8; 32] {
408    cast_mut(self)
409  }
410}