]> git.lizzy.rs Git - rust.git/blob - crates/core_simd/src/masks/mod.rs
fbb934b96424624a9e0efa00caca9f7fe45dbd17
[rust.git] / crates / core_simd / src / masks / mod.rs
1 //! Types and traits associated with masking lanes of vectors.
2 //! Types representing
3 #![allow(non_camel_case_types)]
4
5 #[cfg_attr(not(all(target_arch = "x86_64", target_feature = "avx512f")), path = "full_masks.rs")]
6 #[cfg_attr(all(target_arch = "x86_64", target_feature = "avx512f"), path = "bitmask.rs")]
7 mod mask_impl;
8
9 use crate::{LanesAtMost32, SimdI16, SimdI32, SimdI64, SimdI8, SimdIsize};
10
11 macro_rules! define_opaque_mask {
12     {
13         $(#[$attr:meta])*
14         struct $name:ident<const $lanes:ident: usize>($inner_ty:ty);
15         @bits $bits_ty:ident
16     } => {
17         $(#[$attr])*
18         #[allow(non_camel_case_types)]
19         pub struct $name<const LANES: usize>($inner_ty) where $bits_ty<LANES>: LanesAtMost32;
20
21         impl_opaque_mask_reductions! { $name, $bits_ty }
22
23         impl<const LANES: usize> $name<LANES>
24         where
25             $bits_ty<LANES>: LanesAtMost32
26         {
27             /// Construct a mask by setting all lanes to the given value.
28             pub fn splat(value: bool) -> Self {
29                 Self(<$inner_ty>::splat(value))
30             }
31
32             /// Converts an array to a SIMD vector.
33             pub fn from_array(array: [bool; LANES]) -> Self {
34                 let mut vector = Self::splat(false);
35                 let mut i = 0;
36                 while i < $lanes {
37                     vector.set(i, array[i]);
38                     i += 1;
39                 }
40                 vector
41             }
42
43             /// Converts a SIMD vector to an array.
44             pub fn to_array(self) -> [bool; LANES] {
45                 let mut array = [false; LANES];
46                 let mut i = 0;
47                 while i < $lanes {
48                     array[i] = self.test(i);
49                     i += 1;
50                 }
51                 array
52             }
53
54             /// Converts a vector of integers to a mask, where 0 represents `false` and -1
55             /// represents `true`.
56             ///
57             /// # Safety
58             /// All lanes must be either 0 or -1.
59             #[inline]
60             pub unsafe fn from_int_unchecked(value: $bits_ty<LANES>) -> Self {
61                 Self(<$inner_ty>::from_int_unchecked(value))
62             }
63
64             /// Tests the value of the specified lane.
65             ///
66             /// # Panics
67             /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
68             #[inline]
69             pub fn test(&self, lane: usize) -> bool {
70                 self.0.test(lane)
71             }
72
73             /// Sets the value of the specified lane.
74             ///
75             /// # Panics
76             /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
77             #[inline]
78             pub fn set(&mut self, lane: usize, value: bool) {
79                 self.0.set(lane, value);
80             }
81         }
82
83         // vector/array conversion
84         impl<const LANES: usize> From<[bool; LANES]> for $name<LANES>
85         where
86             $bits_ty<LANES>: crate::LanesAtMost32
87         {
88             fn from(array: [bool; LANES]) -> Self {
89                 Self::from_array(array)
90             }
91         }
92
93         impl <const LANES: usize> From<$name<LANES>> for [bool; LANES]
94         where
95             $bits_ty<LANES>: crate::LanesAtMost32
96         {
97             fn from(vector: $name<LANES>) -> Self {
98                 vector.to_array()
99             }
100         }
101
102         impl<const LANES: usize> Copy for $name<LANES>
103         where
104             $inner_ty: Copy,
105             $bits_ty<LANES>: LanesAtMost32,
106         {}
107
108         impl<const LANES: usize> Clone for $name<LANES>
109         where
110             $bits_ty<LANES>: LanesAtMost32,
111         {
112             #[inline]
113             fn clone(&self) -> Self {
114                 *self
115             }
116         }
117
118         impl<const LANES: usize> Default for $name<LANES>
119         where
120             $bits_ty<LANES>: LanesAtMost32,
121         {
122             #[inline]
123             fn default() -> Self {
124                 Self::splat(false)
125             }
126         }
127
128         impl<const LANES: usize> PartialEq for $name<LANES>
129         where
130             $bits_ty<LANES>: LanesAtMost32,
131         {
132             #[inline]
133             fn eq(&self, other: &Self) -> bool {
134                 self.0 == other.0
135             }
136         }
137
138         impl<const LANES: usize> PartialOrd for $name<LANES>
139         where
140             $bits_ty<LANES>: LanesAtMost32,
141         {
142             #[inline]
143             fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
144                 self.0.partial_cmp(&other.0)
145             }
146         }
147
148         impl<const LANES: usize> core::fmt::Debug for $name<LANES>
149         where
150             $bits_ty<LANES>: LanesAtMost32,
151         {
152             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
153                 core::fmt::Debug::fmt(&self.0, f)
154             }
155         }
156
157         impl<const LANES: usize> core::ops::BitAnd for $name<LANES>
158         where
159             $bits_ty<LANES>: LanesAtMost32,
160         {
161             type Output = Self;
162             #[inline]
163             fn bitand(self, rhs: Self) -> Self {
164                 Self(self.0 & rhs.0)
165             }
166         }
167
168         impl<const LANES: usize> core::ops::BitAnd<bool> for $name<LANES>
169         where
170             $bits_ty<LANES>: LanesAtMost32,
171         {
172             type Output = Self;
173             #[inline]
174             fn bitand(self, rhs: bool) -> Self {
175                 self & Self::splat(rhs)
176             }
177         }
178
179         impl<const LANES: usize> core::ops::BitAnd<$name<LANES>> for bool
180         where
181             $bits_ty<LANES>: LanesAtMost32,
182         {
183             type Output = $name<LANES>;
184             #[inline]
185             fn bitand(self, rhs: $name<LANES>) -> $name<LANES> {
186                 $name::<LANES>::splat(self) & rhs
187             }
188         }
189
190         impl<const LANES: usize> core::ops::BitOr for $name<LANES>
191         where
192             $bits_ty<LANES>: LanesAtMost32,
193         {
194             type Output = Self;
195             #[inline]
196             fn bitor(self, rhs: Self) -> Self {
197                 Self(self.0 | rhs.0)
198             }
199         }
200
201         impl<const LANES: usize> core::ops::BitOr<bool> for $name<LANES>
202         where
203             $bits_ty<LANES>: LanesAtMost32,
204         {
205             type Output = Self;
206             #[inline]
207             fn bitor(self, rhs: bool) -> Self {
208                 self | Self::splat(rhs)
209             }
210         }
211
212         impl<const LANES: usize> core::ops::BitOr<$name<LANES>> for bool
213         where
214             $bits_ty<LANES>: LanesAtMost32,
215         {
216             type Output = $name<LANES>;
217             #[inline]
218             fn bitor(self, rhs: $name<LANES>) -> $name<LANES> {
219                 $name::<LANES>::splat(self) | rhs
220             }
221         }
222
223         impl<const LANES: usize> core::ops::BitXor for $name<LANES>
224         where
225             $bits_ty<LANES>: LanesAtMost32,
226         {
227             type Output = Self;
228             #[inline]
229             fn bitxor(self, rhs: Self) -> Self::Output {
230                 Self(self.0 ^ rhs.0)
231             }
232         }
233
234         impl<const LANES: usize> core::ops::BitXor<bool> for $name<LANES>
235         where
236             $bits_ty<LANES>: LanesAtMost32,
237         {
238             type Output = Self;
239             #[inline]
240             fn bitxor(self, rhs: bool) -> Self::Output {
241                 self ^ Self::splat(rhs)
242             }
243         }
244
245         impl<const LANES: usize> core::ops::BitXor<$name<LANES>> for bool
246         where
247             $bits_ty<LANES>: LanesAtMost32,
248         {
249             type Output = $name<LANES>;
250             #[inline]
251             fn bitxor(self, rhs: $name<LANES>) -> Self::Output {
252                 $name::<LANES>::splat(self) ^ rhs
253             }
254         }
255
256         impl<const LANES: usize> core::ops::Not for $name<LANES>
257         where
258             $bits_ty<LANES>: LanesAtMost32,
259         {
260             type Output = $name<LANES>;
261             #[inline]
262             fn not(self) -> Self::Output {
263                 Self(!self.0)
264             }
265         }
266
267         impl<const LANES: usize> core::ops::BitAndAssign for $name<LANES>
268         where
269             $bits_ty<LANES>: LanesAtMost32,
270         {
271             #[inline]
272             fn bitand_assign(&mut self, rhs: Self) {
273                 self.0 &= rhs.0;
274             }
275         }
276
277         impl<const LANES: usize> core::ops::BitAndAssign<bool> for $name<LANES>
278         where
279             $bits_ty<LANES>: LanesAtMost32,
280         {
281             #[inline]
282             fn bitand_assign(&mut self, rhs: bool) {
283                 *self &= Self::splat(rhs);
284             }
285         }
286
287         impl<const LANES: usize> core::ops::BitOrAssign for $name<LANES>
288         where
289             $bits_ty<LANES>: LanesAtMost32,
290         {
291             #[inline]
292             fn bitor_assign(&mut self, rhs: Self) {
293                 self.0 |= rhs.0;
294             }
295         }
296
297         impl<const LANES: usize> core::ops::BitOrAssign<bool> for $name<LANES>
298         where
299             $bits_ty<LANES>: LanesAtMost32,
300         {
301             #[inline]
302             fn bitor_assign(&mut self, rhs: bool) {
303                 *self |= Self::splat(rhs);
304             }
305         }
306
307         impl<const LANES: usize> core::ops::BitXorAssign for $name<LANES>
308         where
309             $bits_ty<LANES>: LanesAtMost32,
310         {
311             #[inline]
312             fn bitxor_assign(&mut self, rhs: Self) {
313                 self.0 ^= rhs.0;
314             }
315         }
316
317         impl<const LANES: usize> core::ops::BitXorAssign<bool> for $name<LANES>
318         where
319             $bits_ty<LANES>: LanesAtMost32,
320         {
321             #[inline]
322             fn bitxor_assign(&mut self, rhs: bool) {
323                 *self ^= Self::splat(rhs);
324             }
325         }
326     };
327 }
328
329 define_opaque_mask! {
330     /// Mask for vectors with `LANES` 8-bit elements.
331     ///
332     /// The layout of this type is unspecified.
333     struct Mask8<const LANES: usize>(mask_impl::Mask8<LANES>);
334     @bits SimdI8
335 }
336
337 define_opaque_mask! {
338     /// Mask for vectors with `LANES` 16-bit elements.
339     ///
340     /// The layout of this type is unspecified.
341     struct Mask16<const LANES: usize>(mask_impl::Mask16<LANES>);
342     @bits SimdI16
343 }
344
345 define_opaque_mask! {
346     /// Mask for vectors with `LANES` 32-bit elements.
347     ///
348     /// The layout of this type is unspecified.
349     struct Mask32<const LANES: usize>(mask_impl::Mask32<LANES>);
350     @bits SimdI32
351 }
352
353 define_opaque_mask! {
354     /// Mask for vectors with `LANES` 64-bit elements.
355     ///
356     /// The layout of this type is unspecified.
357     struct Mask64<const LANES: usize>(mask_impl::Mask64<LANES>);
358     @bits SimdI64
359 }
360
361 define_opaque_mask! {
362     /// Mask for vectors with `LANES` pointer-width elements.
363     ///
364     /// The layout of this type is unspecified.
365     struct MaskSize<const LANES: usize>(mask_impl::MaskSize<LANES>);
366     @bits SimdIsize
367 }
368
369 /// Vector of eight 8-bit masks
370 pub type mask8x8 = Mask8<8>;
371
372 /// Vector of 16 8-bit masks
373 pub type mask8x16 = Mask8<16>;
374
375 /// Vector of 32 8-bit masks
376 pub type mask8x32 = Mask8<32>;
377
378 /// Vector of 16 8-bit masks
379 pub type mask8x64 = Mask8<64>;
380
381 /// Vector of four 16-bit masks
382 pub type mask16x4 = Mask16<4>;
383
384 /// Vector of eight 16-bit masks
385 pub type mask16x8 = Mask16<8>;
386
387 /// Vector of 16 16-bit masks
388 pub type mask16x16 = Mask16<16>;
389
390 /// Vector of 32 16-bit masks
391 pub type mask16x32 = Mask32<32>;
392
393 /// Vector of two 32-bit masks
394 pub type mask32x2 = Mask32<2>;
395
396 /// Vector of four 32-bit masks
397 pub type mask32x4 = Mask32<4>;
398
399 /// Vector of eight 32-bit masks
400 pub type mask32x8 = Mask32<8>;
401
402 /// Vector of 16 32-bit masks
403 pub type mask32x16 = Mask32<16>;
404
405 /// Vector of two 64-bit masks
406 pub type mask64x2 = Mask64<2>;
407
408 /// Vector of four 64-bit masks
409 pub type mask64x4 = Mask64<4>;
410
411 /// Vector of eight 64-bit masks
412 pub type mask64x8 = Mask64<8>;
413
414 /// Vector of two pointer-width masks
415 pub type masksizex2 = MaskSize<2>;
416
417 /// Vector of four pointer-width masks
418 pub type masksizex4 = MaskSize<4>;
419
420 /// Vector of eight pointer-width masks
421 pub type masksizex8 = MaskSize<8>;