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