]> git.lizzy.rs Git - rust.git/blob - crates/core_simd/src/masks/full_masks/mod.rs
Merge pull request #62 from rust-lang/feature/shuffle-self
[rust.git] / crates / core_simd / src / masks / full_masks / mod.rs
1 //! Masks that take up full SIMD vector registers.
2
3 /// The error type returned when converting an integer to a mask fails.
4 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
5 pub struct TryFromMaskError(());
6
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")
10     }
11 }
12
13 macro_rules! define_mask {
14     { $(#[$attr:meta])* struct $name:ident<const $lanes:ident: usize>($type:ty); } => {
15         $(#[$attr])*
16         #[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
17         #[repr(transparent)]
18         pub struct $name<const $lanes: usize>($type);
19
20         delegate_ops_to_inner! { $name }
21
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 {
25                 Self(<$type>::splat(
26                     if value {
27                         -1
28                     } else {
29                         0
30                     }
31                 ))
32             }
33
34             /// Tests the value of the specified lane.
35             ///
36             /// # Panics
37             /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
38             #[inline]
39             pub fn test(&self, lane: usize) -> bool {
40                 self.0[lane] == -1
41             }
42
43             /// Sets the value of the specified lane.
44             ///
45             /// # Panics
46             /// Panics if `lane` is greater than or equal to the number of lanes in the vector.
47             #[inline]
48             pub fn set(&mut self, lane: usize, value: bool) {
49                 self.0[lane] = if value {
50                     -1
51                 } else {
52                     0
53                 }
54             }
55         }
56
57         impl<const $lanes: usize> core::convert::From<bool> for $name<$lanes> {
58             fn from(value: bool) -> Self {
59                 Self::splat(value)
60             }
61         }
62
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) {
67                     Ok(Self(value))
68                 } else {
69                     Err(TryFromMaskError(()))
70                 }
71             }
72         }
73
74         impl<const $lanes: usize> core::convert::From<$name<$lanes>> for $type {
75             fn from(value: $name<$lanes>) -> Self {
76                 value.0
77             }
78         }
79
80         impl<const $lanes: usize> core::fmt::Debug for $name<$lanes> {
81             fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
82                 f.debug_list()
83                     .entries((0..LANES).map(|lane| self.test(lane)))
84                     .finish()
85             }
86         }
87
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)
91             }
92         }
93
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)
97             }
98         }
99
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)
103             }
104         }
105
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)
109             }
110         }
111     }
112 }
113
114 define_mask! {
115     /// A mask equivalent to [SimdI8](crate::SimdI8), where all bits in the lane must be either set
116     /// or unset.
117     struct SimdI8Mask<const LANES: usize>(crate::SimdI8<LANES>);
118 }
119
120 define_mask! {
121     /// A mask equivalent to [SimdI16](crate::SimdI16), where all bits in the lane must be either set
122     /// or unset.
123     struct SimdI16Mask<const LANES: usize>(crate::SimdI16<LANES>);
124 }
125
126 define_mask! {
127     /// A mask equivalent to [SimdI32](crate::SimdI32), where all bits in the lane must be either set
128     /// or unset.
129     struct SimdI32Mask<const LANES: usize>(crate::SimdI32<LANES>);
130 }
131
132 define_mask! {
133     /// A mask equivalent to [SimdI64](crate::SimdI64), where all bits in the lane must be either set
134     /// or unset.
135     struct SimdI64Mask<const LANES: usize>(crate::SimdI64<LANES>);
136 }
137
138 define_mask! {
139     /// A mask equivalent to [SimdI128](crate::SimdI128), where all bits in the lane must be either set
140     /// or unset.
141     struct SimdI128Mask<const LANES: usize>(crate::SimdI64<LANES>);
142 }
143
144 define_mask! {
145     /// A mask equivalent to [SimdIsize](crate::SimdIsize), where all bits in the lane must be either set
146     /// or unset.
147     struct SimdIsizeMask<const LANES: usize>(crate::SimdI64<LANES>);
148 }
149
150 macro_rules! implement_mask_ext {
151     { $($vector:ident => $mask:ident,)* } => {
152         $(
153             impl<const LANES: usize> crate::masks::MaskExt<$mask<LANES>> for crate::$vector<LANES> {
154                 #[inline]
155                 fn lanes_eq(&self, other: &Self) -> $mask<LANES> {
156                     unsafe { crate::intrinsics::simd_eq(self, other) }
157                 }
158
159                 #[inline]
160                 fn lanes_ne(&self, other: &Self) -> $mask<LANES> {
161                     unsafe { crate::intrinsics::simd_ne(self, other) }
162                 }
163
164                 #[inline]
165                 fn lanes_lt(&self, other: &Self) -> $mask<LANES> {
166                     unsafe { crate::intrinsics::simd_lt(self, other) }
167                 }
168
169                 #[inline]
170                 fn lanes_gt(&self, other: &Self) -> $mask<LANES> {
171                     unsafe { crate::intrinsics::simd_gt(self, other) }
172                 }
173
174                 #[inline]
175                 fn lanes_le(&self, other: &Self) -> $mask<LANES> {
176                     unsafe { crate::intrinsics::simd_le(self, other) }
177                 }
178
179                 #[inline]
180                 fn lanes_ge(&self, other: &Self) -> $mask<LANES> {
181                     unsafe { crate::intrinsics::simd_ge(self, other) }
182                 }
183             }
184         )*
185     }
186 }
187
188 implement_mask_ext! {
189     SimdI8 => SimdI8Mask,
190     SimdI16 => SimdI16Mask,
191     SimdI32 => SimdI32Mask,
192     SimdI64 => SimdI64Mask,
193     SimdI128 => SimdI128Mask,
194     SimdIsize => SimdIsizeMask,
195
196     SimdU8 => SimdI8Mask,
197     SimdU16 => SimdI16Mask,
198     SimdU32 => SimdI32Mask,
199     SimdU64 => SimdI64Mask,
200     SimdU128 => SimdI128Mask,
201     SimdUsize => SimdIsizeMask,
202
203     SimdF32 => SimdI32Mask,
204     SimdF64 => SimdI64Mask,
205 }