1 //! Masks that take up full SIMD vector registers.
3 /// The error type returned when converting an integer to a mask fails.
4 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
5 pub struct TryFromMaskError(());
7 impl core::fmt::Display for TryFromMaskError {
8 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
11 "mask vector must have all bits set or unset in each lane"
16 macro_rules! define_mask {
19 struct $name:ident<const $lanes:ident: usize>(
20 crate::$type:ident<$lanes2:ident>
24 #[derive(Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
26 pub struct $name<const $lanes: usize>(crate::$type<$lanes2>)
28 crate::$type<LANES>: crate::LanesAtMost32;
30 impl<const LANES: usize> Copy for $name<LANES>
32 crate::$type<LANES>: crate::LanesAtMost32,
35 impl<const LANES: usize> Clone for $name<LANES>
37 crate::$type<LANES>: crate::LanesAtMost32,
40 fn clone(&self) -> Self {
45 impl<const LANES: usize> $name<LANES>
47 crate::$type<LANES>: crate::LanesAtMost32,
49 /// Construct a mask by setting all lanes to the given value.
50 pub fn splat(value: bool) -> Self {
51 Self(<crate::$type<LANES>>::splat(
60 /// Tests the value of the specified lane.
63 /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
65 pub fn test(&self, lane: usize) -> bool {
66 assert!(lane < LANES, "lane index out of range");
70 /// Sets the value of the specified lane.
73 /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
75 pub fn set(&mut self, lane: usize, value: bool) {
76 assert!(lane < LANES, "lane index out of range");
77 self.0[lane] = if value {
84 /// Converts the mask to the equivalent integer representation, where -1 represents
85 /// "set" and 0 represents "unset".
87 pub fn to_int(self) -> crate::$type<LANES> {
91 /// Creates a mask from the equivalent integer representation, where -1 represents
92 /// "set" and 0 represents "unset".
94 /// Each provided lane must be either 0 or -1.
96 pub unsafe fn from_int_unchecked(value: crate::$type<LANES>) -> Self {
100 /// Creates a mask from the equivalent integer representation, where -1 represents
101 /// "set" and 0 represents "unset".
104 /// Panics if any lane is not 0 or -1.
106 pub fn from_int(value: crate::$type<LANES>) -> Self {
107 use core::convert::TryInto;
108 value.try_into().unwrap()
112 impl<const LANES: usize> core::convert::From<bool> for $name<LANES>
114 crate::$type<LANES>: crate::LanesAtMost32,
116 fn from(value: bool) -> Self {
121 impl<const LANES: usize> core::convert::TryFrom<crate::$type<LANES>> for $name<LANES>
123 crate::$type<LANES>: crate::LanesAtMost32,
125 type Error = TryFromMaskError;
126 fn try_from(value: crate::$type<LANES>) -> Result<Self, Self::Error> {
127 let valid = (value.lanes_eq(crate::$type::<LANES>::splat(0)) | value.lanes_eq(crate::$type::<LANES>::splat(-1))).all();
131 Err(TryFromMaskError(()))
136 impl<const LANES: usize> core::convert::From<$name<LANES>> for crate::$type<LANES>
138 crate::$type<LANES>: crate::LanesAtMost32,
140 fn from(value: $name<LANES>) -> Self {
145 impl<const LANES: usize> core::convert::From<crate::BitMask<LANES>> for $name<LANES>
147 crate::$type<LANES>: crate::LanesAtMost32,
148 crate::BitMask<LANES>: crate::LanesAtMost32,
150 fn from(value: crate::BitMask<LANES>) -> Self {
151 // TODO use an intrinsic to do this efficiently (with LLVM's sext instruction)
152 let mut mask = Self::splat(false);
153 for lane in 0..LANES {
154 mask.set(lane, value.test(lane));
160 impl<const LANES: usize> core::convert::From<$name<LANES>> for crate::BitMask<LANES>
162 crate::$type<LANES>: crate::LanesAtMost32,
163 crate::BitMask<LANES>: crate::LanesAtMost32,
165 fn from(value: $name<$lanes>) -> Self {
166 // TODO use an intrinsic to do this efficiently (with LLVM's trunc instruction)
167 let mut mask = Self::splat(false);
168 for lane in 0..LANES {
169 mask.set(lane, value.test(lane));
175 impl<const LANES: usize> core::fmt::Debug for $name<LANES>
177 crate::$type<LANES>: crate::LanesAtMost32,
179 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
181 .entries((0..LANES).map(|lane| self.test(lane)))
186 impl<const LANES: usize> core::fmt::Binary for $name<LANES>
188 crate::$type<LANES>: crate::LanesAtMost32,
190 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
191 core::fmt::Binary::fmt(&self.0, f)
195 impl<const LANES: usize> core::fmt::Octal for $name<LANES>
197 crate::$type<LANES>: crate::LanesAtMost32,
199 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
200 core::fmt::Octal::fmt(&self.0, f)
204 impl<const LANES: usize> core::fmt::LowerHex for $name<LANES>
206 crate::$type<LANES>: crate::LanesAtMost32,
208 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
209 core::fmt::LowerHex::fmt(&self.0, f)
213 impl<const LANES: usize> core::fmt::UpperHex for $name<LANES>
215 crate::$type<LANES>: crate::LanesAtMost32,
217 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
218 core::fmt::UpperHex::fmt(&self.0, f)
222 impl<const LANES: usize> core::ops::BitAnd for $name<LANES>
224 crate::$type<LANES>: crate::LanesAtMost32,
228 fn bitand(self, rhs: Self) -> Self {
233 impl<const LANES: usize> core::ops::BitAnd<bool> for $name<LANES>
235 crate::$type<LANES>: crate::LanesAtMost32,
239 fn bitand(self, rhs: bool) -> Self {
240 self & Self::splat(rhs)
244 impl<const LANES: usize> core::ops::BitAnd<$name<LANES>> for bool
246 crate::$type<LANES>: crate::LanesAtMost32,
248 type Output = $name<LANES>;
250 fn bitand(self, rhs: $name<LANES>) -> $name<LANES> {
251 $name::<LANES>::splat(self) & rhs
255 impl<const LANES: usize> core::ops::BitOr for $name<LANES>
257 crate::$type<LANES>: crate::LanesAtMost32,
261 fn bitor(self, rhs: Self) -> Self {
266 impl<const LANES: usize> core::ops::BitOr<bool> for $name<LANES>
268 crate::$type<LANES>: crate::LanesAtMost32,
272 fn bitor(self, rhs: bool) -> Self {
273 self | Self::splat(rhs)
277 impl<const LANES: usize> core::ops::BitOr<$name<LANES>> for bool
279 crate::$type<LANES>: crate::LanesAtMost32,
281 type Output = $name<LANES>;
283 fn bitor(self, rhs: $name<LANES>) -> $name<LANES> {
284 $name::<LANES>::splat(self) | rhs
288 impl<const LANES: usize> core::ops::BitXor for $name<LANES>
290 crate::$type<LANES>: crate::LanesAtMost32,
294 fn bitxor(self, rhs: Self) -> Self::Output {
299 impl<const LANES: usize> core::ops::BitXor<bool> for $name<LANES>
301 crate::$type<LANES>: crate::LanesAtMost32,
305 fn bitxor(self, rhs: bool) -> Self::Output {
306 self ^ Self::splat(rhs)
310 impl<const LANES: usize> core::ops::BitXor<$name<LANES>> for bool
312 crate::$type<LANES>: crate::LanesAtMost32,
314 type Output = $name<LANES>;
316 fn bitxor(self, rhs: $name<LANES>) -> Self::Output {
317 $name::<LANES>::splat(self) ^ rhs
321 impl<const LANES: usize> core::ops::Not for $name<LANES>
323 crate::$type<LANES>: crate::LanesAtMost32,
325 type Output = $name<LANES>;
327 fn not(self) -> Self::Output {
332 impl<const LANES: usize> core::ops::BitAndAssign for $name<LANES>
334 crate::$type<LANES>: crate::LanesAtMost32,
337 fn bitand_assign(&mut self, rhs: Self) {
342 impl<const LANES: usize> core::ops::BitAndAssign<bool> for $name<LANES>
344 crate::$type<LANES>: crate::LanesAtMost32,
347 fn bitand_assign(&mut self, rhs: bool) {
348 *self &= Self::splat(rhs);
352 impl<const LANES: usize> core::ops::BitOrAssign for $name<LANES>
354 crate::$type<LANES>: crate::LanesAtMost32,
357 fn bitor_assign(&mut self, rhs: Self) {
362 impl<const LANES: usize> core::ops::BitOrAssign<bool> for $name<LANES>
364 crate::$type<LANES>: crate::LanesAtMost32,
367 fn bitor_assign(&mut self, rhs: bool) {
368 *self |= Self::splat(rhs);
372 impl<const LANES: usize> core::ops::BitXorAssign for $name<LANES>
374 crate::$type<LANES>: crate::LanesAtMost32,
377 fn bitxor_assign(&mut self, rhs: Self) {
382 impl<const LANES: usize> core::ops::BitXorAssign<bool> for $name<LANES>
384 crate::$type<LANES>: crate::LanesAtMost32,
387 fn bitxor_assign(&mut self, rhs: bool) {
388 *self ^= Self::splat(rhs);
392 impl_full_mask_reductions! { $name, $type }
397 /// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
399 struct SimdMask8<const LANES: usize>(crate::SimdI8<LANES>);
403 /// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
405 struct SimdMask16<const LANES: usize>(crate::SimdI16<LANES>);
409 /// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
411 struct SimdMask32<const LANES: usize>(crate::SimdI32<LANES>);
415 /// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
417 struct SimdMask64<const LANES: usize>(crate::SimdI64<LANES>);
421 /// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
423 struct SimdMask128<const LANES: usize>(crate::SimdI128<LANES>);
427 /// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
429 struct SimdMaskSize<const LANES: usize>(crate::SimdIsize<LANES>);