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 {
17 { $(#[$attr:meta])* struct $name:ident<const $lanes:ident: usize>($type:ty); } => {
19 #[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
21 pub struct $name<const $lanes: usize>($type);
23 impl<const $lanes: usize> $name<$lanes> {
24 /// Construct a mask by setting all lanes to the given value.
25 pub fn splat(value: bool) -> Self {
35 /// Tests the value of the specified lane.
38 /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
40 pub fn test(&self, lane: usize) -> bool {
41 assert!(lane < LANES, "lane index out of range");
45 /// Sets the value of the specified lane.
48 /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
50 pub fn set(&mut self, lane: usize, value: bool) {
51 assert!(lane < LANES, "lane index out of range");
52 self.0[lane] = if value {
60 impl<const $lanes: usize> core::convert::From<bool> for $name<$lanes> {
61 fn from(value: bool) -> Self {
66 impl<const $lanes: usize> core::convert::TryFrom<$type> for $name<$lanes> {
67 type Error = TryFromMaskError;
68 fn try_from(value: $type) -> Result<Self, Self::Error> {
69 if value.as_slice().iter().all(|x| *x == 0 || *x == -1) {
72 Err(TryFromMaskError(()))
77 impl<const $lanes: usize> core::convert::From<$name<$lanes>> for $type {
78 fn from(value: $name<$lanes>) -> Self {
83 impl<const $lanes: usize> core::convert::From<crate::BitMask<$lanes>> for $name<$lanes>
85 crate::BitMask<$lanes>: crate::LanesAtMost64,
87 fn from(value: crate::BitMask<$lanes>) -> Self {
88 // TODO use an intrinsic to do this efficiently (with LLVM's sext instruction)
89 let mut mask = Self::splat(false);
90 for lane in 0..LANES {
91 mask.set(lane, value.test(lane));
97 impl<const $lanes: usize> core::convert::From<$name<$lanes>> for crate::BitMask<$lanes>
99 crate::BitMask<$lanes>: crate::LanesAtMost64,
101 fn from(value: $name<$lanes>) -> Self {
102 // TODO use an intrinsic to do this efficiently (with LLVM's trunc instruction)
103 let mut mask = Self::splat(false);
104 for lane in 0..LANES {
105 mask.set(lane, value.test(lane));
111 impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
112 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
114 .entries((0..LANES).map(|lane| self.test(lane)))
119 impl<const $lanes: usize> core::fmt::Binary for $name<$lanes> {
120 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
121 core::fmt::Binary::fmt(&self.0, f)
125 impl<const $lanes: usize> core::fmt::Octal for $name<$lanes> {
126 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
127 core::fmt::Octal::fmt(&self.0, f)
131 impl<const $lanes: usize> core::fmt::LowerHex for $name<$lanes> {
132 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
133 core::fmt::LowerHex::fmt(&self.0, f)
137 impl<const $lanes: usize> core::fmt::UpperHex for $name<$lanes> {
138 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
139 core::fmt::UpperHex::fmt(&self.0, f)
143 impl<const LANES: usize> core::ops::BitAnd for $name<LANES> {
146 fn bitand(self, rhs: Self) -> Self {
151 impl<const LANES: usize> core::ops::BitAnd<bool> for $name<LANES> {
154 fn bitand(self, rhs: bool) -> Self {
155 self & Self::splat(rhs)
159 impl<const LANES: usize> core::ops::BitAnd<$name<LANES>> for bool {
160 type Output = $name<LANES>;
162 fn bitand(self, rhs: $name<LANES>) -> $name<LANES> {
163 $name::<LANES>::splat(self) & rhs
167 impl<const LANES: usize> core::ops::BitOr for $name<LANES> {
170 fn bitor(self, rhs: Self) -> Self {
175 impl<const LANES: usize> core::ops::BitOr<bool> for $name<LANES> {
178 fn bitor(self, rhs: bool) -> Self {
179 self | Self::splat(rhs)
183 impl<const LANES: usize> core::ops::BitOr<$name<LANES>> for bool {
184 type Output = $name<LANES>;
186 fn bitor(self, rhs: $name<LANES>) -> $name<LANES> {
187 $name::<LANES>::splat(self) | rhs
191 impl<const LANES: usize> core::ops::BitXor for $name<LANES> {
194 fn bitxor(self, rhs: Self) -> Self::Output {
199 impl<const LANES: usize> core::ops::BitXor<bool> for $name<LANES> {
202 fn bitxor(self, rhs: bool) -> Self::Output {
203 self ^ Self::splat(rhs)
207 impl<const LANES: usize> core::ops::BitXor<$name<LANES>> for bool {
208 type Output = $name<LANES>;
210 fn bitxor(self, rhs: $name<LANES>) -> Self::Output {
211 $name::<LANES>::splat(self) ^ rhs
215 impl<const LANES: usize> core::ops::Not for $name<LANES> {
216 type Output = $name<LANES>;
218 fn not(self) -> Self::Output {
223 impl<const LANES: usize> core::ops::BitAndAssign for $name<LANES> {
225 fn bitand_assign(&mut self, rhs: Self) {
230 impl<const LANES: usize> core::ops::BitAndAssign<bool> for $name<LANES> {
232 fn bitand_assign(&mut self, rhs: bool) {
233 *self &= Self::splat(rhs);
237 impl<const LANES: usize> core::ops::BitOrAssign for $name<LANES> {
239 fn bitor_assign(&mut self, rhs: Self) {
244 impl<const LANES: usize> core::ops::BitOrAssign<bool> for $name<LANES> {
246 fn bitor_assign(&mut self, rhs: bool) {
247 *self |= Self::splat(rhs);
251 impl<const LANES: usize> core::ops::BitXorAssign for $name<LANES> {
253 fn bitxor_assign(&mut self, rhs: Self) {
258 impl<const LANES: usize> core::ops::BitXorAssign<bool> for $name<LANES> {
260 fn bitxor_assign(&mut self, rhs: bool) {
261 *self ^= Self::splat(rhs);
268 /// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
270 struct SimdMask8<const LANES: usize>(crate::SimdI8<LANES>);
274 /// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
276 struct SimdMask16<const LANES: usize>(crate::SimdI16<LANES>);
280 /// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
282 struct SimdMask32<const LANES: usize>(crate::SimdI32<LANES>);
286 /// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
288 struct SimdMask64<const LANES: usize>(crate::SimdI64<LANES>);
292 /// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
294 struct SimdMask128<const LANES: usize>(crate::SimdI64<LANES>);
298 /// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
300 struct SimdMaskSize<const LANES: usize>(crate::SimdI64<LANES>);