1use core::fmt;
4use core::ops::*;
5
6use core::arch::aarch64::*;
7
8#[repr(C)]
9union UnionCast {
10 a: [u32; 4],
11 v: BVec4A,
12}
13
14#[inline(always)]
16#[must_use]
17pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A {
18 BVec4A::new(x, y, z, w)
19}
20
21#[derive(Clone, Copy)]
25#[repr(transparent)]
26pub struct BVec4A(pub(crate) uint32x4_t);
27
28const MASK: [u32; 2] = [0, 0xff_ff_ff_ff];
29
30impl BVec4A {
31 pub const FALSE: Self = Self::splat(false);
33
34 pub const TRUE: Self = Self::splat(true);
36
37 #[inline(always)]
39 #[must_use]
40 pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self {
41 unsafe {
42 UnionCast {
43 a: [
44 MASK[x as usize],
45 MASK[y as usize],
46 MASK[z as usize],
47 MASK[w as usize],
48 ],
49 }
50 .v
51 }
52 }
53
54 #[inline]
56 #[must_use]
57 pub const fn splat(v: bool) -> Self {
58 Self::new(v, v, v, v)
59 }
60
61 #[inline]
63 #[must_use]
64 pub const fn from_array(a: [bool; 4]) -> Self {
65 Self::new(a[0], a[1], a[2], a[3])
66 }
67
68 #[inline]
73 #[must_use]
74 pub fn bitmask(self) -> u32 {
75 unsafe {
76 let mma = vandq_u32(self.0, vld1q_u32([1, 2, 4, 8].as_ptr())); let mmb = vextq_u32(mma, mma, 2); let mmc = vorrq_u32(mma, mmb); let mmd = vextq_u32(mmc, mmc, 3); let mme = vorrq_u32(mmc, mmd); vgetq_lane_u32(mme, 0)
82 }
83 }
84
85 #[inline]
87 #[must_use]
88 pub fn any(self) -> bool {
89 self.bitmask() != 0
90 }
91
92 #[inline]
94 #[must_use]
95 pub fn all(self) -> bool {
96 self.bitmask() == 0xf
97 }
98
99 #[inline]
103 #[must_use]
104 pub fn test(&self, index: usize) -> bool {
105 match index {
106 0 => (self.bitmask() & (1 << 0)) != 0,
107 1 => (self.bitmask() & (1 << 1)) != 0,
108 2 => (self.bitmask() & (1 << 2)) != 0,
109 3 => (self.bitmask() & (1 << 3)) != 0,
110 _ => panic!("index out of bounds"),
111 }
112 }
113
114 #[inline]
118 pub fn set(&mut self, index: usize, value: bool) {
119 self.0 = match index {
120 0 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 0) },
121 1 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 1) },
122 2 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 2) },
123 3 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 3) },
124 _ => panic!("index out of bounds"),
125 }
126 }
127
128 #[inline]
129 #[must_use]
130 fn into_bool_array(self) -> [bool; 4] {
131 let bitmask = self.bitmask();
132 [
133 (bitmask & 1) != 0,
134 (bitmask & 2) != 0,
135 (bitmask & 4) != 0,
136 (bitmask & 8) != 0,
137 ]
138 }
139
140 #[inline]
141 #[must_use]
142 fn into_u32_array(self) -> [u32; 4] {
143 let bitmask = self.bitmask();
144 [
145 MASK[(bitmask & 1) as usize],
146 MASK[((bitmask >> 1) & 1) as usize],
147 MASK[((bitmask >> 2) & 1) as usize],
148 MASK[((bitmask >> 3) & 1) as usize],
149 ]
150 }
151}
152
153impl Default for BVec4A {
154 #[inline]
155 fn default() -> Self {
156 Self::FALSE
157 }
158}
159
160impl PartialEq for BVec4A {
161 #[inline]
162 fn eq(&self, rhs: &Self) -> bool {
163 self.bitmask().eq(&rhs.bitmask())
164 }
165}
166
167impl Eq for BVec4A {}
168
169impl core::hash::Hash for BVec4A {
170 #[inline]
171 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
172 self.bitmask().hash(state);
173 }
174}
175
176impl BitAnd for BVec4A {
177 type Output = Self;
178 #[inline]
179 fn bitand(self, rhs: Self) -> Self {
180 Self(unsafe { vandq_u32(self.0, rhs.0) })
181 }
182}
183
184impl BitAndAssign for BVec4A {
185 #[inline]
186 fn bitand_assign(&mut self, rhs: Self) {
187 *self = self.bitand(rhs);
188 }
189}
190
191impl BitOr for BVec4A {
192 type Output = Self;
193 #[inline]
194 fn bitor(self, rhs: Self) -> Self {
195 Self(unsafe { vorrq_u32(self.0, rhs.0) })
196 }
197}
198
199impl BitOrAssign for BVec4A {
200 #[inline]
201 fn bitor_assign(&mut self, rhs: Self) {
202 *self = self.bitor(rhs);
203 }
204}
205
206impl BitXor for BVec4A {
207 type Output = Self;
208 #[inline]
209 fn bitxor(self, rhs: Self) -> Self {
210 Self(unsafe { veorq_u32(self.0, rhs.0) })
211 }
212}
213
214impl BitXorAssign for BVec4A {
215 #[inline]
216 fn bitxor_assign(&mut self, rhs: Self) {
217 *self = self.bitxor(rhs);
218 }
219}
220
221impl Not for BVec4A {
222 type Output = Self;
223 #[inline]
224 fn not(self) -> Self {
225 Self(unsafe { vmvnq_u32(self.0) })
226 }
227}
228
229impl From<BVec4A> for uint32x4_t {
230 #[inline]
231 fn from(t: BVec4A) -> Self {
232 t.0
233 }
234}
235
236impl fmt::Debug for BVec4A {
237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238 let arr = self.into_u32_array();
239 write!(
240 f,
241 "{}({:#x}, {:#x}, {:#x}, {:#x})",
242 stringify!(BVec4A),
243 arr[0],
244 arr[1],
245 arr[2],
246 arr[3]
247 )
248 }
249}
250
251impl fmt::Display for BVec4A {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 let arr = self.into_bool_array();
254 write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3])
255 }
256}
257
258impl From<[bool; 4]> for BVec4A {
259 #[inline]
260 fn from(a: [bool; 4]) -> Self {
261 Self::from_array(a)
262 }
263}
264
265impl From<BVec4A> for [bool; 4] {
266 #[inline]
267 fn from(mask: BVec4A) -> Self {
268 mask.into_bool_array()
269 }
270}
271
272impl From<BVec4A> for [u32; 4] {
273 #[inline]
274 fn from(mask: BVec4A) -> Self {
275 mask.into_u32_array()
276 }
277}