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 {
9 write!(f, "mask vector must have all bits set or unset in each lane")
13 macro_rules! define_mask {
14 { $(#[$attr:meta])* struct $name:ident<const $lanes:ident: usize>($type:ty); } => {
16 #[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
18 pub struct $name<const $lanes: usize>($type);
20 delegate_ops_to_inner! { $name }
22 impl<const $lanes: usize> $name<$lanes> {
23 /// Construct a mask by setting all lanes to the given value.
24 pub fn splat(value: bool) -> Self {
34 /// Tests the value of the specified lane.
37 /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
39 pub fn test(&self, lane: usize) -> bool {
43 /// Sets the value of the specified lane.
46 /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
48 pub fn set(&mut self, lane: usize, value: bool) {
49 self.0[lane] = if value {
57 impl<const $lanes: usize> core::convert::From<bool> for $name<$lanes> {
58 fn from(value: bool) -> Self {
63 impl<const $lanes: usize> core::convert::TryFrom<$type> for $name<$lanes> {
64 type Error = TryFromMaskError;
65 fn try_from(value: $type) -> Result<Self, Self::Error> {
66 if value.as_slice().iter().all(|x| *x == 0 || *x == -1) {
69 Err(TryFromMaskError(()))
74 impl<const $lanes: usize> core::convert::From<$name<$lanes>> for $type {
75 fn from(value: $name<$lanes>) -> Self {
80 impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
81 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
83 .entries((0..LANES).map(|lane| self.test(lane)))
88 impl<const $lanes: usize> core::fmt::Binary for $name<$lanes> {
89 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
90 core::fmt::Binary::fmt(&self.0, f)
94 impl<const $lanes: usize> core::fmt::Octal for $name<$lanes> {
95 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
96 core::fmt::Octal::fmt(&self.0, f)
100 impl<const $lanes: usize> core::fmt::LowerHex for $name<$lanes> {
101 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
102 core::fmt::LowerHex::fmt(&self.0, f)
106 impl<const $lanes: usize> core::fmt::UpperHex for $name<$lanes> {
107 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
108 core::fmt::UpperHex::fmt(&self.0, f)
115 /// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
117 struct SimdI8Mask<const LANES: usize>(crate::SimdI8<LANES>);
121 /// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
123 struct SimdI16Mask<const LANES: usize>(crate::SimdI16<LANES>);
127 /// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
129 struct SimdI32Mask<const LANES: usize>(crate::SimdI32<LANES>);
133 /// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
135 struct SimdI64Mask<const LANES: usize>(crate::SimdI64<LANES>);
139 /// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
141 struct SimdI128Mask<const LANES: usize>(crate::SimdI64<LANES>);
145 /// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
147 struct SimdIsizeMask<const LANES: usize>(crate::SimdI64<LANES>);
150 macro_rules! implement_mask_ext {
151 { $($vector:ident => $mask:ident,)* } => {
153 impl<const LANES: usize> crate::masks::MaskExt<$mask<LANES>> for crate::$vector<LANES> {
155 fn lanes_eq(&self, other: &Self) -> $mask<LANES> {
156 unsafe { crate::intrinsics::simd_eq(self, other) }
160 fn lanes_ne(&self, other: &Self) -> $mask<LANES> {
161 unsafe { crate::intrinsics::simd_ne(self, other) }
165 fn lanes_lt(&self, other: &Self) -> $mask<LANES> {
166 unsafe { crate::intrinsics::simd_lt(self, other) }
170 fn lanes_gt(&self, other: &Self) -> $mask<LANES> {
171 unsafe { crate::intrinsics::simd_gt(self, other) }
175 fn lanes_le(&self, other: &Self) -> $mask<LANES> {
176 unsafe { crate::intrinsics::simd_le(self, other) }
180 fn lanes_ge(&self, other: &Self) -> $mask<LANES> {
181 unsafe { crate::intrinsics::simd_ge(self, other) }
188 implement_mask_ext! {
189 SimdI8 => SimdI8Mask,
190 SimdI16 => SimdI16Mask,
191 SimdI32 => SimdI32Mask,
192 SimdI64 => SimdI64Mask,
193 SimdI128 => SimdI128Mask,
194 SimdIsize => SimdIsizeMask,
196 SimdU8 => SimdI8Mask,
197 SimdU16 => SimdI16Mask,
198 SimdU32 => SimdI32Mask,
199 SimdU64 => SimdI64Mask,
200 SimdU128 => SimdI128Mask,
201 SimdUsize => SimdIsizeMask,
203 SimdF32 => SimdI32Mask,
204 SimdF64 => SimdI64Mask,