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 Add for i8x32 {
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 { avx: add_i8_m256i(self.avx,rhs.avx) }
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 i8x32 {
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 { avx: sub_i8_m256i(self.avx,rhs.avx) }
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<i8> for i8x32 {
57  type Output = Self;
58  #[inline]
59  #[must_use]
60  fn add(self, rhs: i8) -> Self::Output {
61    self.add(Self::splat(rhs))
62  }
63}
64
65impl Sub<i8> for i8x32 {
66  type Output = Self;
67  #[inline]
68  #[must_use]
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  #[must_use]
78  fn add(self, rhs: i8x32) -> Self::Output {
79    i8x32::splat(self).add(rhs)
80  }
81}
82
83impl Sub<i8x32> for i8 {
84  type Output = i8x32;
85  #[inline]
86  #[must_use]
87  fn sub(self, rhs: i8x32) -> Self::Output {
88    i8x32::splat(self).sub(rhs)
89  }
90}
91
92impl BitAnd for i8x32 {
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 { avx : bitand_m256i(self.avx,rhs.avx) }
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 i8x32 {
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 { avx : bitor_m256i(self.avx,rhs.avx) }
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 i8x32 {
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 { avx : bitxor_m256i(self.avx,rhs.avx) }
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 CmpEq for i8x32 {
147  type Output = Self;
148  #[inline]
149  #[must_use]
150  fn cmp_eq(self, rhs: Self) -> Self::Output {
151    pick! {
152      if #[cfg(target_feature="avx2")] {
153        Self { avx : cmp_eq_mask_i8_m256i(self.avx,rhs.avx) }
154      } else {
155        Self {
156          a : self.a.cmp_eq(rhs.a),
157          b : self.b.cmp_eq(rhs.b),
158        }
159      }
160    }
161  }
162}
163
164impl CmpGt for i8x32 {
165  type Output = Self;
166  #[inline]
167  #[must_use]
168  fn cmp_gt(self, rhs: Self) -> Self::Output {
169    pick! {
170      if #[cfg(target_feature="avx2")] {
171        Self { avx : cmp_gt_mask_i8_m256i(self.avx,rhs.avx) }
172      } else {
173        Self {
174          a : self.a.cmp_gt(rhs.a),
175          b : self.b.cmp_gt(rhs.b),
176        }
177      }
178    }
179  }
180}
181
182impl CmpLt for i8x32 {
183  type Output = Self;
184  #[inline]
185  #[must_use]
186  fn cmp_lt(self, rhs: Self) -> Self::Output {
187    pick! {
188      if #[cfg(target_feature="avx2")] {
189        Self { avx : !(cmp_gt_mask_i8_m256i(self.avx,rhs.avx) ^ cmp_eq_mask_i8_m256i(self.avx,rhs.avx)) }
190      } else {
191        Self {
192          a : self.a.cmp_lt(rhs.a),
193          b : self.b.cmp_lt(rhs.b),
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::intrinsics::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  #[inline]
235  #[must_use]
236  pub fn max(self, rhs: Self) -> Self {
237    pick! {
238      if #[cfg(target_feature="avx2")] {
239        Self { avx: max_i8_m256i(self.avx,rhs.avx) }
240      } else {
241        Self {
242          a : self.a.max(rhs.a),
243          b : self.b.max(rhs.b),
244        }
245      }
246    }
247  }
248  #[inline]
249  #[must_use]
250  pub fn min(self, rhs: Self) -> Self {
251    pick! {
252      if #[cfg(target_feature="avx2")] {
253        Self { avx: min_i8_m256i(self.avx,rhs.avx) }
254      } else {
255        Self {
256          a : self.a.min(rhs.a),
257          b : self.b.min(rhs.b),
258        }
259      }
260    }
261  }
262
263  #[inline]
264  #[must_use]
265  pub fn saturating_add(self, rhs: Self) -> Self {
266    pick! {
267      if #[cfg(target_feature="avx2")] {
268        Self { avx: add_saturating_i8_m256i(self.avx, rhs.avx) }
269      } else {
270        Self {
271          a : self.a.saturating_add(rhs.a),
272          b : self.b.saturating_add(rhs.b),
273        }
274      }
275    }
276  }
277  #[inline]
278  #[must_use]
279  pub fn saturating_sub(self, rhs: Self) -> Self {
280    pick! {
281      if #[cfg(target_feature="avx2")] {
282        Self { avx: sub_saturating_i8_m256i(self.avx, rhs.avx) }
283      } else {
284        Self {
285          a : self.a.saturating_sub(rhs.a),
286          b : self.b.saturating_sub(rhs.b),
287        }
288      }
289    }
290  }
291
292  #[inline]
293  #[must_use]
294  pub fn move_mask(self) -> i32 {
295    pick! {
296      if #[cfg(target_feature="avx2")] {
297        move_mask_i8_m256i(self.avx)
298      } else {
299        self.a.move_mask() | (self.b.move_mask() << 16)
300      }
301    }
302  }
303
304  #[inline]
305  #[must_use]
306  pub fn any(self) -> bool {
307    pick! {
308      if #[cfg(target_feature="avx2")] {
309        move_mask_i8_m256i(self.avx) != 0
310      } else {
311        (self.a | self.b).any()
312      }
313    }
314  }
315
316  #[inline]
317  #[must_use]
318  pub fn all(self) -> bool {
319    pick! {
320      if #[cfg(target_feature="avx2")] {
321        move_mask_i8_m256i(self.avx) == -1
322      } else {
323        (self.a & self.b).all()
324      }
325    }
326  }
327
328  #[inline]
329  #[must_use]
330  pub fn none(self) -> bool {
331    !self.any()
332  }
333
334  /// Returns a new vector with lanes selected from the lanes of the first input
335  /// vector a specified in the second input vector `rhs`.
336  /// The indices i in range `[0, 15]` select the i-th element of `self`. For
337  /// indices outside of the range the resulting lane is `0`.
338  ///
339  /// This note that is the equivalent of two parallel swizzle operations on the
340  /// two halves of the vector, and the indexes each refer to the
341  /// corresponding half.
342  #[inline]
343  pub fn swizzle_half(self, rhs: i8x32) -> i8x32 {
344    pick! {
345      if #[cfg(target_feature="avx2")] {
346        Self { avx: shuffle_av_i8z_half_m256i(self.avx, rhs.saturating_add(i8x32::splat(0x60)).avx) }
347      } else {
348          Self {
349            a : self.a.swizzle(rhs.a),
350            b : self.b.swizzle(rhs.b),
351          }
352      }
353    }
354  }
355
356  /// Indices in the range `[0, 15]` will select the i-th element of `self`. If
357  /// the high bit of any element of `rhs` is set (negative) then the
358  /// corresponding output lane is guaranteed to be zero. Otherwise if the
359  /// element of `rhs` is within the range `[32, 127]` then the output lane is
360  /// either `0` or `self[rhs[i] % 16]` depending on the implementation.
361  ///
362  /// This is the equivalent to two parallel swizzle operations on the two
363  /// halves of the vector, and the indexes each refer to their corresponding
364  /// half.
365  #[inline]
366  pub fn swizzle_half_relaxed(self, rhs: i8x32) -> i8x32 {
367    pick! {
368      if #[cfg(target_feature="avx2")] {
369        Self { avx: shuffle_av_i8z_half_m256i(self.avx, rhs.avx) }
370      } else {
371        Self {
372          a : self.a.swizzle_relaxed(rhs.a),
373          b : self.b.swizzle_relaxed(rhs.b),
374        }
375      }
376    }
377  }
378
379  #[inline]
380  pub fn to_array(self) -> [i8; 32] {
381    cast(self)
382  }
383
384  #[inline]
385  pub fn as_array_ref(&self) -> &[i8; 32] {
386    cast_ref(self)
387  }
388
389  #[inline]
390  pub fn as_array_mut(&mut self) -> &mut [i8; 32] {
391    cast_mut(self)
392  }
393}