1use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2};
4use core::fmt;
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8#[cfg(target_arch = "x86")]
9use core::arch::x86::*;
10#[cfg(target_arch = "x86_64")]
11use core::arch::x86_64::*;
12
13#[repr(C)]
14union UnionCast {
15 a: [f32; 4],
16 v: Mat2,
17}
18
19#[inline(always)]
21#[must_use]
22pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
23 Mat2::from_cols(x_axis, y_axis)
24}
25
26#[derive(Clone, Copy)]
32#[repr(transparent)]
33pub struct Mat2(pub(crate) __m128);
34
35impl Mat2 {
36 pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
38
39 pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
41
42 pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
44
45 #[allow(clippy::too_many_arguments)]
46 #[inline(always)]
47 #[must_use]
48 const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
49 unsafe {
50 UnionCast {
51 a: [m00, m01, m10, m11],
52 }
53 .v
54 }
55 }
56
57 #[inline(always)]
59 #[must_use]
60 pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
61 unsafe {
62 UnionCast {
63 a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y],
64 }
65 .v
66 }
67 }
68
69 #[inline]
73 #[must_use]
74 pub const fn from_cols_array(m: &[f32; 4]) -> Self {
75 Self::new(m[0], m[1], m[2], m[3])
76 }
77
78 #[inline]
81 #[must_use]
82 pub const fn to_cols_array(&self) -> [f32; 4] {
83 unsafe { *(self as *const Self as *const [f32; 4]) }
84 }
85
86 #[inline]
90 #[must_use]
91 pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
92 Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
93 }
94
95 #[inline]
98 #[must_use]
99 pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
100 unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
101 }
102
103 #[doc(alias = "scale")]
105 #[inline]
106 #[must_use]
107 pub const fn from_diagonal(diagonal: Vec2) -> Self {
108 Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
109 }
110
111 #[inline]
114 #[must_use]
115 pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
116 let (sin, cos) = math::sin_cos(angle);
117 Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
118 }
119
120 #[inline]
122 #[must_use]
123 pub fn from_angle(angle: f32) -> Self {
124 let (sin, cos) = math::sin_cos(angle);
125 Self::new(cos, sin, -sin, cos)
126 }
127
128 #[inline]
130 #[must_use]
131 pub fn from_mat3(m: Mat3) -> Self {
132 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
133 }
134
135 #[inline]
142 #[must_use]
143 pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
144 match (i, j) {
145 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
146 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
147 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
148 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
149 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
150 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
151 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
152 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
153 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
154 _ => panic!("index out of bounds"),
155 }
156 }
157
158 #[inline]
160 #[must_use]
161 pub fn from_mat3a(m: Mat3A) -> Self {
162 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
163 }
164
165 #[inline]
172 #[must_use]
173 pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
174 match (i, j) {
175 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
176 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
177 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
178 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
179 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
180 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
181 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
182 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
183 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
184 _ => panic!("index out of bounds"),
185 }
186 }
187
188 #[inline]
194 #[must_use]
195 pub const fn from_cols_slice(slice: &[f32]) -> Self {
196 Self::new(slice[0], slice[1], slice[2], slice[3])
197 }
198
199 #[inline]
205 pub fn write_cols_to_slice(self, slice: &mut [f32]) {
206 slice[0] = self.x_axis.x;
207 slice[1] = self.x_axis.y;
208 slice[2] = self.y_axis.x;
209 slice[3] = self.y_axis.y;
210 }
211
212 #[inline]
218 #[must_use]
219 pub fn col(&self, index: usize) -> Vec2 {
220 match index {
221 0 => self.x_axis,
222 1 => self.y_axis,
223 _ => panic!("index out of bounds"),
224 }
225 }
226
227 #[inline]
233 pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
234 match index {
235 0 => &mut self.x_axis,
236 1 => &mut self.y_axis,
237 _ => panic!("index out of bounds"),
238 }
239 }
240
241 #[inline]
247 #[must_use]
248 pub fn row(&self, index: usize) -> Vec2 {
249 match index {
250 0 => Vec2::new(self.x_axis.x, self.y_axis.x),
251 1 => Vec2::new(self.x_axis.y, self.y_axis.y),
252 _ => panic!("index out of bounds"),
253 }
254 }
255
256 #[inline]
259 #[must_use]
260 pub fn is_finite(&self) -> bool {
261 self.x_axis.is_finite() && self.y_axis.is_finite()
262 }
263
264 #[inline]
266 #[must_use]
267 pub fn is_nan(&self) -> bool {
268 self.x_axis.is_nan() || self.y_axis.is_nan()
269 }
270
271 #[inline]
273 #[must_use]
274 pub fn transpose(&self) -> Self {
275 Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
276 }
277
278 #[inline]
280 #[must_use]
281 pub fn determinant(&self) -> f32 {
282 unsafe {
283 let abcd = self.0;
284 let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
285 let prod = _mm_mul_ps(abcd, dcba);
286 let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
287 _mm_cvtss_f32(det)
288 }
289 }
290
291 #[inline]
299 #[must_use]
300 pub fn inverse(&self) -> Self {
301 unsafe {
302 const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
303 let abcd = self.0;
304 let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
305 let prod = _mm_mul_ps(abcd, dcba);
306 let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
307 let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00);
308 let tmp = _mm_div_ps(SIGN, det);
309 glam_assert!(Mat2(tmp).is_finite());
310 let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11);
311 Self(_mm_mul_ps(dbca, tmp))
312 }
313 }
314
315 #[inline]
317 #[must_use]
318 pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
319 unsafe {
320 use crate::Align16;
321 use core::mem::MaybeUninit;
322 let abcd = self.0;
323 let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
324 let axbxcydy = _mm_mul_ps(abcd, xxyy);
325 let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
326 let result = _mm_add_ps(axbxcydy, cydyaxbx);
327 let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
328 _mm_store_ps(out.as_mut_ptr().cast(), result);
329 out.assume_init().0
330 }
331 }
332
333 #[inline]
335 #[must_use]
336 pub fn mul_mat2(&self, rhs: &Self) -> Self {
337 unsafe {
338 let abcd = self.0;
339 let rhs = rhs.0;
340 let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
341 let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
342 let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
343 let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
344 let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
345 let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
346 let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
347 let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
348 Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
349 }
350 }
351
352 #[inline]
354 #[must_use]
355 pub fn add_mat2(&self, rhs: &Self) -> Self {
356 Self(unsafe { _mm_add_ps(self.0, rhs.0) })
357 }
358
359 #[inline]
361 #[must_use]
362 pub fn sub_mat2(&self, rhs: &Self) -> Self {
363 Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
364 }
365
366 #[inline]
368 #[must_use]
369 pub fn mul_scalar(&self, rhs: f32) -> Self {
370 Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
371 }
372
373 #[inline]
375 #[must_use]
376 pub fn div_scalar(&self, rhs: f32) -> Self {
377 Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) })
378 }
379
380 #[inline]
390 #[must_use]
391 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
392 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
393 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
394 }
395
396 #[inline]
398 #[must_use]
399 pub fn abs(&self) -> Self {
400 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
401 }
402
403 #[inline]
404 pub fn as_dmat2(&self) -> DMat2 {
405 DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
406 }
407}
408
409impl Default for Mat2 {
410 #[inline]
411 fn default() -> Self {
412 Self::IDENTITY
413 }
414}
415
416impl Add<Mat2> for Mat2 {
417 type Output = Self;
418 #[inline]
419 fn add(self, rhs: Self) -> Self::Output {
420 self.add_mat2(&rhs)
421 }
422}
423
424impl AddAssign<Mat2> for Mat2 {
425 #[inline]
426 fn add_assign(&mut self, rhs: Self) {
427 *self = self.add_mat2(&rhs);
428 }
429}
430
431impl Sub<Mat2> for Mat2 {
432 type Output = Self;
433 #[inline]
434 fn sub(self, rhs: Self) -> Self::Output {
435 self.sub_mat2(&rhs)
436 }
437}
438
439impl SubAssign<Mat2> for Mat2 {
440 #[inline]
441 fn sub_assign(&mut self, rhs: Self) {
442 *self = self.sub_mat2(&rhs);
443 }
444}
445
446impl Neg for Mat2 {
447 type Output = Self;
448 #[inline]
449 fn neg(self) -> Self::Output {
450 Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
451 }
452}
453
454impl Mul<Mat2> for Mat2 {
455 type Output = Self;
456 #[inline]
457 fn mul(self, rhs: Self) -> Self::Output {
458 self.mul_mat2(&rhs)
459 }
460}
461
462impl MulAssign<Mat2> for Mat2 {
463 #[inline]
464 fn mul_assign(&mut self, rhs: Self) {
465 *self = self.mul_mat2(&rhs);
466 }
467}
468
469impl Mul<Vec2> for Mat2 {
470 type Output = Vec2;
471 #[inline]
472 fn mul(self, rhs: Vec2) -> Self::Output {
473 self.mul_vec2(rhs)
474 }
475}
476
477impl Mul<Mat2> for f32 {
478 type Output = Mat2;
479 #[inline]
480 fn mul(self, rhs: Mat2) -> Self::Output {
481 rhs.mul_scalar(self)
482 }
483}
484
485impl Mul<f32> for Mat2 {
486 type Output = Self;
487 #[inline]
488 fn mul(self, rhs: f32) -> Self::Output {
489 self.mul_scalar(rhs)
490 }
491}
492
493impl MulAssign<f32> for Mat2 {
494 #[inline]
495 fn mul_assign(&mut self, rhs: f32) {
496 *self = self.mul_scalar(rhs);
497 }
498}
499
500impl Div<Mat2> for f32 {
501 type Output = Mat2;
502 #[inline]
503 fn div(self, rhs: Mat2) -> Self::Output {
504 rhs.div_scalar(self)
505 }
506}
507
508impl Div<f32> for Mat2 {
509 type Output = Self;
510 #[inline]
511 fn div(self, rhs: f32) -> Self::Output {
512 self.div_scalar(rhs)
513 }
514}
515
516impl DivAssign<f32> for Mat2 {
517 #[inline]
518 fn div_assign(&mut self, rhs: f32) {
519 *self = self.div_scalar(rhs);
520 }
521}
522
523impl Sum<Self> for Mat2 {
524 fn sum<I>(iter: I) -> Self
525 where
526 I: Iterator<Item = Self>,
527 {
528 iter.fold(Self::ZERO, Self::add)
529 }
530}
531
532impl<'a> Sum<&'a Self> for Mat2 {
533 fn sum<I>(iter: I) -> Self
534 where
535 I: Iterator<Item = &'a Self>,
536 {
537 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
538 }
539}
540
541impl Product for Mat2 {
542 fn product<I>(iter: I) -> Self
543 where
544 I: Iterator<Item = Self>,
545 {
546 iter.fold(Self::IDENTITY, Self::mul)
547 }
548}
549
550impl<'a> Product<&'a Self> for Mat2 {
551 fn product<I>(iter: I) -> Self
552 where
553 I: Iterator<Item = &'a Self>,
554 {
555 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
556 }
557}
558
559impl PartialEq for Mat2 {
560 #[inline]
561 fn eq(&self, rhs: &Self) -> bool {
562 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
563 }
564}
565
566#[cfg(not(target_arch = "spirv"))]
567impl AsRef<[f32; 4]> for Mat2 {
568 #[inline]
569 fn as_ref(&self) -> &[f32; 4] {
570 unsafe { &*(self as *const Self as *const [f32; 4]) }
571 }
572}
573
574#[cfg(not(target_arch = "spirv"))]
575impl AsMut<[f32; 4]> for Mat2 {
576 #[inline]
577 fn as_mut(&mut self) -> &mut [f32; 4] {
578 unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
579 }
580}
581
582impl core::ops::Deref for Mat2 {
583 type Target = crate::deref::Cols2<Vec2>;
584 #[inline]
585 fn deref(&self) -> &Self::Target {
586 unsafe { &*(self as *const Self as *const Self::Target) }
587 }
588}
589
590impl core::ops::DerefMut for Mat2 {
591 #[inline]
592 fn deref_mut(&mut self) -> &mut Self::Target {
593 unsafe { &mut *(self as *mut Self as *mut Self::Target) }
594 }
595}
596
597impl fmt::Debug for Mat2 {
598 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
599 fmt.debug_struct(stringify!(Mat2))
600 .field("x_axis", &self.x_axis)
601 .field("y_axis", &self.y_axis)
602 .finish()
603 }
604}
605
606impl fmt::Display for Mat2 {
607 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
608 if let Some(p) = f.precision() {
609 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
610 } else {
611 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
612 }
613 }
614}