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