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