hermes_simd_core/view/
mask_reg.rs1use super::vector_reg::{assert_runtime_supported, Vector};
4use crate::arch::SimdArch;
5use crate::kernel::SimdKernel;
6use crate::mask::BitMask;
7use crate::scalar::Scalar;
8use core::marker::PhantomData;
9
10#[repr(transparent)]
12pub struct Mask<T, Arch>
13where
14 Arch: SimdArch + SimdKernel<T>,
15 T: Scalar,
16{
17 pub raw: Arch::Mask,
19 _marker: PhantomData<T>,
20}
21
22impl<T, Arch> Clone for Mask<T, Arch>
23where
24 Arch: SimdArch + SimdKernel<T>,
25 T: Scalar,
26{
27 #[inline(always)]
28 fn clone(&self) -> Self {
29 *self
30 }
31}
32
33impl<T, Arch> Copy for Mask<T, Arch>
34where
35 Arch: SimdArch + SimdKernel<T>,
36 T: Scalar,
37{
38}
39
40impl<T, Arch> core::fmt::Debug for Mask<T, Arch>
41where
42 Arch: SimdArch + SimdKernel<T>,
43 T: Scalar,
44{
45 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46 assert_runtime_supported::<T, Arch>();
47 let bm = unsafe { self.to_bitmask() };
48 f.debug_tuple("Mask").field(&bm.to_bools()).finish()
49 }
50}
51
52impl<T, Arch> PartialEq for Mask<T, Arch>
53where
54 Arch: SimdArch + SimdKernel<T>,
55 T: Scalar,
56{
57 #[inline]
58 fn eq(&self, other: &Self) -> bool {
59 assert_runtime_supported::<T, Arch>();
60 unsafe { self.to_bitmask() == other.to_bitmask() }
61 }
62}
63
64impl<T, Arch> Eq for Mask<T, Arch>
65where
66 Arch: SimdArch + SimdKernel<T>,
67 T: Scalar,
68{
69}
70
71impl<T, Arch> Mask<T, Arch>
72where
73 Arch: SimdArch + SimdKernel<T>,
74 T: Scalar,
75{
76 #[inline(always)]
78 pub const fn new(raw: Arch::Mask) -> Self {
79 Self {
80 raw,
81 _marker: PhantomData,
82 }
83 }
84
85 #[inline(always)]
90 pub unsafe fn from_bitmask(bm: BitMask<64>) -> Self {
91 Self::new(Arch::mask_from_bitmask(bm.0))
92 }
93
94 #[inline(always)]
99 pub unsafe fn to_bitmask(self) -> BitMask<64> {
100 BitMask(Arch::mask_to_bitmask(self.raw))
101 }
102
103 #[inline(always)]
105 pub fn any(self) -> bool {
106 assert_runtime_supported::<T, Arch>();
107 unsafe { !self.to_bitmask().is_none_active() }
108 }
109
110 #[inline(always)]
112 pub fn all(self) -> bool {
113 assert_runtime_supported::<T, Arch>();
114 let lanes = <Arch as SimdKernel<T>>::LANE_COUNT;
115 let expected = if lanes >= 64 {
116 u64::MAX
117 } else {
118 (1u64 << lanes) - 1
119 };
120 unsafe { (self.to_bitmask().0 & expected) == expected }
121 }
122
123 #[inline(always)]
125 pub fn none(self) -> bool {
126 assert_runtime_supported::<T, Arch>();
127 unsafe { self.to_bitmask().is_none_active() }
128 }
129
130 #[inline(always)]
132 pub fn select(self, true_val: Vector<T, Arch>, false_val: Vector<T, Arch>) -> Vector<T, Arch> {
133 assert_runtime_supported::<T, Arch>();
134 let zero = Vector::<T, Arch>::zero();
135 Vector::new(unsafe { Arch::masked_add(true_val.raw, zero.raw, self.raw, false_val.raw) })
136 }
137}
138
139impl<T, Arch> core::ops::BitAnd for Mask<T, Arch>
141where
142 Arch: SimdArch + SimdKernel<T>,
143 T: Scalar,
144{
145 type Output = Self;
146 #[inline(always)]
147 fn bitand(self, rhs: Self) -> Self::Output {
148 assert_runtime_supported::<T, Arch>();
149 unsafe {
150 let bm_self = self.to_bitmask();
151 let bm_rhs = rhs.to_bitmask();
152 Self::from_bitmask(bm_self & bm_rhs)
153 }
154 }
155}
156
157impl<T, Arch> core::ops::BitOr for Mask<T, Arch>
158where
159 Arch: SimdArch + SimdKernel<T>,
160 T: Scalar,
161{
162 type Output = Self;
163 #[inline(always)]
164 fn bitor(self, rhs: Self) -> Self::Output {
165 assert_runtime_supported::<T, Arch>();
166 unsafe {
167 let bm_self = self.to_bitmask();
168 let bm_rhs = rhs.to_bitmask();
169 Self::from_bitmask(bm_self | bm_rhs)
170 }
171 }
172}
173
174impl<T, Arch> core::ops::BitXor for Mask<T, Arch>
175where
176 Arch: SimdArch + SimdKernel<T>,
177 T: Scalar,
178{
179 type Output = Self;
180 #[inline(always)]
181 fn bitxor(self, rhs: Self) -> Self::Output {
182 assert_runtime_supported::<T, Arch>();
183 unsafe {
184 let bm_self = self.to_bitmask();
185 let bm_rhs = rhs.to_bitmask();
186 Self::from_bitmask(BitMask(bm_self.0 ^ bm_rhs.0))
187 }
188 }
189}
190
191impl<T, Arch> core::ops::Not for Mask<T, Arch>
192where
193 Arch: SimdArch + SimdKernel<T>,
194 T: Scalar,
195{
196 type Output = Self;
197 #[inline(always)]
198 fn not(self) -> Self::Output {
199 assert_runtime_supported::<T, Arch>();
200 unsafe {
201 let bm = self.to_bitmask();
202 let lanes = <Arch as SimdKernel<T>>::LANE_COUNT;
203 let active_mask = if lanes >= 64 {
204 u64::MAX
205 } else {
206 (1u64 << lanes) - 1
207 };
208 Self::from_bitmask(BitMask((!bm.0) & active_mask))
209 }
210 }
211}