Skip to main content

glam/f32/sse2/
mat2.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3#[cfg(feature = "f64")]
4use crate::DMat2;
5
6use crate::{f32::math, swizzles::*, Mat3, Mat3A, Vec2};
7use core::fmt;
8use core::iter::{Product, Sum};
9use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10
11#[cfg(target_arch = "x86")]
12use core::arch::x86::*;
13#[cfg(target_arch = "x86_64")]
14use core::arch::x86_64::*;
15
16#[cfg(feature = "zerocopy-08")]
17use zerocopy_derive_08::*;
18
19#[repr(C)]
20union UnionCast {
21    a: [f32; 4],
22    v: Mat2,
23}
24
25/// Creates a 2x2 matrix from two column vectors.
26#[inline(always)]
27#[must_use]
28pub const fn mat2(x_axis: Vec2, y_axis: Vec2) -> Mat2 {
29    Mat2::from_cols(x_axis, y_axis)
30}
31
32/// A 2x2 column major matrix.
33///
34/// SIMD vector types are used for storage on supported platforms.
35///
36/// This type is 16 byte aligned.
37#[derive(Clone, Copy)]
38#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
39#[cfg_attr(
40    feature = "zerocopy-08",
41    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
42)]
43#[repr(transparent)]
44pub struct Mat2(pub(crate) __m128);
45
46impl Mat2 {
47    /// A 2x2 matrix with all elements set to `0.0`.
48    pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO);
49
50    /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
51    pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y);
52
53    /// All NAN:s.
54    pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN);
55
56    #[allow(clippy::too_many_arguments)]
57    #[inline(always)]
58    #[must_use]
59    const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self {
60        unsafe {
61            UnionCast {
62                a: [m00, m01, m10, m11],
63            }
64            .v
65        }
66    }
67
68    /// Creates a 2x2 matrix from two column vectors.
69    ///
70    /// See also [`Self::from_rows`] when the data is in row major order.
71    #[inline(always)]
72    #[must_use]
73    pub const fn from_cols(x_axis: Vec2, y_axis: Vec2) -> Self {
74        unsafe {
75            UnionCast {
76                a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y],
77            }
78            .v
79        }
80    }
81
82    /// Creates a 2x2 matrix from two row vectors.
83    ///
84    /// Matrices are stored in column major order, so the given rows are permuted into
85    /// the matrix layout. Use [`Self::from_cols`] instead when the data is already in
86    /// column major order.
87    #[inline(always)]
88    #[must_use]
89    pub const fn from_rows(row0: Vec2, row1: Vec2) -> Self {
90        let [m00, m01] = row0.to_array();
91        let [m10, m11] = row1.to_array();
92        Self::new(m00, m10, m01, m11)
93    }
94
95    /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order.
96    ///
97    /// If the data is in row major order use [`Self::from_rows_array`] instead.
98    #[inline]
99    #[must_use]
100    pub const fn from_cols_array(m: &[f32; 4]) -> Self {
101        Self::new(m[0], m[1], m[2], m[3])
102    }
103
104    /// Creates a `[f32; 4]` array storing data in column major order.
105    ///
106    /// If you require the data in row major order use [`Self::to_rows_array`] instead.
107    #[inline]
108    #[must_use]
109    pub const fn to_cols_array(&self) -> [f32; 4] {
110        unsafe { *(self as *const Self as *const [f32; 4]) }
111    }
112
113    /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order.
114    ///
115    /// If the data is in row major order `transpose` the returned matrix.
116    #[inline]
117    #[must_use]
118    pub const fn from_cols_array_2d(m: &[[f32; 2]; 2]) -> Self {
119        Self::from_cols(Vec2::from_array(m[0]), Vec2::from_array(m[1]))
120    }
121
122    /// Creates a `[[f32; 2]; 2]` 2D array storing data in column major order.
123    ///
124    /// If you require row major order `transpose` the matrix first.
125    #[inline]
126    #[must_use]
127    pub const fn to_cols_array_2d(&self) -> [[f32; 2]; 2] {
128        unsafe { *(self as *const Self as *const [[f32; 2]; 2]) }
129    }
130
131    /// Creates a 2x2 matrix from a `[f32; 4]` array stored in row major order.
132    ///
133    /// Matrices are stored in column major order, so the array is permuted into the
134    /// matrix layout. Use [`Self::from_cols_array`] instead when the data is already in
135    /// column major order.
136    #[inline]
137    #[must_use]
138    pub const fn from_rows_array(m: &[f32; 4]) -> Self {
139        Self::new(m[0], m[2], m[1], m[3])
140    }
141
142    /// Creates a `[f32; 4]` array storing data in row major order.
143    ///
144    /// Matrices are stored in column major order, so the array is permuted out of the
145    /// column major storage. Use [`Self::to_cols_array`] instead when you want data in
146    /// column major order.
147    #[inline]
148    #[must_use]
149    pub const fn to_rows_array(&self) -> [f32; 4] {
150        let m = self.to_cols_array();
151        [m[0], m[2], m[1], m[3]]
152    }
153
154    /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
155    #[doc(alias = "scale")]
156    #[inline]
157    #[must_use]
158    pub const fn from_diagonal(diagonal: Vec2) -> Self {
159        Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
160    }
161
162    /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
163    /// `angle` (in radians).
164    #[inline]
165    #[must_use]
166    pub fn from_scale_angle(scale: Vec2, angle: f32) -> Self {
167        let (sin, cos) = math::sin_cos(angle);
168        Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
169    }
170
171    /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
172    #[inline]
173    #[must_use]
174    pub fn from_angle(angle: f32) -> Self {
175        let (sin, cos) = math::sin_cos(angle);
176        Self::new(cos, sin, -sin, cos)
177    }
178
179    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
180    #[inline]
181    #[must_use]
182    pub fn from_mat3(m: Mat3) -> Self {
183        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
184    }
185
186    /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
187    /// and `j`th row.
188    ///
189    /// # Panics
190    ///
191    /// Panics if `i` or `j` is greater than 2.
192    #[inline]
193    #[must_use]
194    pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
195        match (i, j) {
196            (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
197            (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
198            (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
199            (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
200            (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
201            (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
202            (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
203            (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
204            (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
205            _ => panic!("index out of bounds"),
206        }
207    }
208
209    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
210    #[inline]
211    #[must_use]
212    pub fn from_mat3a(m: Mat3A) -> Self {
213        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
214    }
215
216    /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
217    /// and `j`th row.
218    ///
219    /// # Panics
220    ///
221    /// Panics if `i` or `j` is greater than 2.
222    #[inline]
223    #[must_use]
224    pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
225        match (i, j) {
226            (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
227            (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
228            (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
229            (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
230            (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
231            (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
232            (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
233            (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
234            (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
235            _ => panic!("index out of bounds"),
236        }
237    }
238
239    /// Creates a 2x2 matrix from the first 4 values in `slice`.
240    ///
241    /// See also [`Self::from_rows_slice`] when the slice is in row major order.
242    ///
243    /// # Panics
244    ///
245    /// Panics if `slice` is less than 4 elements long.
246    #[inline]
247    #[must_use]
248    pub const fn from_cols_slice(slice: &[f32]) -> Self {
249        Self::new(slice[0], slice[1], slice[2], slice[3])
250    }
251
252    /// Writes the columns of `self` to the first 4 elements in `slice`.
253    ///
254    /// # Panics
255    ///
256    /// Panics if `slice` is less than 4 elements long.
257    #[inline]
258    pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
259        slice[0] = self.x_axis.x;
260        slice[1] = self.x_axis.y;
261        slice[2] = self.y_axis.x;
262        slice[3] = self.y_axis.y;
263    }
264
265    /// Creates a 2x2 matrix from the first 4 values in `slice`, stored in row
266    /// major order.
267    ///
268    /// Matrices are stored in column major order, so the slice is permuted into the
269    /// matrix layout. Use [`Self::from_cols_slice`] instead when the slice is already in
270    /// column major order.
271    ///
272    /// # Panics
273    ///
274    /// Panics if `slice` is less than 4 elements long.
275    #[inline]
276    #[must_use]
277    pub const fn from_rows_slice(slice: &[f32]) -> Self {
278        Self::new(slice[0], slice[2], slice[1], slice[3])
279    }
280
281    /// Returns the matrix column for the given `index`.
282    ///
283    /// # Panics
284    ///
285    /// Panics if `index` is greater than 1.
286    #[inline]
287    #[must_use]
288    pub fn col(&self, index: usize) -> Vec2 {
289        match index {
290            0 => self.x_axis,
291            1 => self.y_axis,
292            _ => panic!("index out of bounds"),
293        }
294    }
295
296    /// Returns a mutable reference to the matrix column for the given `index`.
297    ///
298    /// # Panics
299    ///
300    /// Panics if `index` is greater than 1.
301    #[inline]
302    pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
303        match index {
304            0 => &mut self.x_axis,
305            1 => &mut self.y_axis,
306            _ => panic!("index out of bounds"),
307        }
308    }
309
310    /// Returns the matrix row for the given `index`.
311    ///
312    /// See also [`Self::set_row`] when you need to change the row.
313    ///
314    /// # Panics
315    ///
316    /// Panics if `index` is greater than 1.
317    #[inline]
318    #[must_use]
319    pub fn row(&self, index: usize) -> Vec2 {
320        match index {
321            0 => Vec2::new(self.x_axis.x, self.y_axis.x),
322            1 => Vec2::new(self.x_axis.y, self.y_axis.y),
323            _ => panic!("index out of bounds"),
324        }
325    }
326
327    /// Sets the matrix row for the given `index`.
328    ///
329    /// Matrices are stored in column major order, so the row is spread across all
330    /// 2 columns and writing it touches every column. Use [`Self::col_mut`]
331    /// instead when you can work with columns. See also [`Self::row`].
332    ///
333    /// # Panics
334    ///
335    /// Panics if `index` is greater than 1.
336    #[inline]
337    pub fn set_row(&mut self, index: usize, row: Vec2) {
338        match index {
339            0 => {
340                self.x_axis.x = row.x;
341                self.y_axis.x = row.y;
342            }
343            1 => {
344                self.x_axis.y = row.x;
345                self.y_axis.y = row.y;
346            }
347            _ => panic!("index out of bounds"),
348        }
349    }
350
351    /// Returns `true` if, and only if, all elements are finite.
352    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
353    #[inline]
354    #[must_use]
355    pub fn is_finite(&self) -> bool {
356        self.x_axis.is_finite() && self.y_axis.is_finite()
357    }
358
359    /// Returns `true` if any elements are `NaN`.
360    #[inline]
361    #[must_use]
362    pub fn is_nan(&self) -> bool {
363        self.x_axis.is_nan() || self.y_axis.is_nan()
364    }
365
366    /// Returns the transpose of `self`.
367    #[inline]
368    #[must_use]
369    pub fn transpose(&self) -> Self {
370        Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
371    }
372
373    /// Returns the diagonal of `self`.
374    #[inline]
375    #[must_use]
376    pub fn diagonal(&self) -> Vec2 {
377        Vec2::new(self.x_axis.x, self.y_axis.y)
378    }
379
380    /// Returns the determinant of `self`.
381    #[inline]
382    #[must_use]
383    pub fn determinant(&self) -> f32 {
384        unsafe {
385            let abcd = self.0;
386            let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
387            let prod = _mm_mul_ps(abcd, dcba);
388            let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
389            _mm_cvtss_f32(det)
390        }
391    }
392
393    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
394    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
395    /// inverted matrix and true is returned.
396    ///
397    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
398    /// inverted matrix will be invalid. Will panic if the determinant of `self` is zero when
399    /// `glam_assert` is enabled.
400    ///
401    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
402    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
403    /// matrix is aligned.
404    #[inline(always)]
405    #[must_use]
406    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
407        unsafe {
408            use crate::Vec4;
409            const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
410            let abcd = self.0;
411            let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
412            let prod = _mm_mul_ps(abcd, dcba);
413            let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
414            let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00);
415            if CHECKED {
416                if Vec4(det) == Vec4::ZERO {
417                    return (Self::ZERO, false);
418                }
419            } else {
420                glam_assert!(Vec4(det).cmpne(Vec4::ZERO).all());
421            }
422            let tmp = _mm_div_ps(SIGN, det);
423            let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11);
424            (Self(_mm_mul_ps(dbca, tmp)), true)
425        }
426    }
427
428    /// Returns the inverse of `self`.
429    ///
430    /// If the matrix is not invertible the returned matrix will be invalid.
431    ///
432    /// # Panics
433    ///
434    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
435    #[inline]
436    #[must_use]
437    pub fn inverse(&self) -> Self {
438        self.inverse_checked::<false>().0
439    }
440
441    /// Returns the inverse of `self` or `None` if the matrix is not invertible.
442    #[inline]
443    #[must_use]
444    pub fn try_inverse(&self) -> Option<Self> {
445        let (m, is_valid) = self.inverse_checked::<true>();
446        if is_valid {
447            Some(m)
448        } else {
449            None
450        }
451    }
452
453    /// Returns the inverse of `self` or `Mat2::ZERO` if the matrix is not invertible.
454    #[inline]
455    #[must_use]
456    pub fn inverse_or_zero(&self) -> Self {
457        self.inverse_checked::<true>().0
458    }
459
460    /// Transforms a 2D vector.
461    #[inline]
462    #[must_use]
463    pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
464        unsafe {
465            use crate::Align16;
466            use core::mem::MaybeUninit;
467            let abcd = self.0;
468            let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
469            let axbxcydy = _mm_mul_ps(abcd, xxyy);
470            let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
471            let result = _mm_add_ps(axbxcydy, cydyaxbx);
472            let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
473            _mm_store_ps(out.as_mut_ptr().cast(), result);
474            out.assume_init().0
475        }
476    }
477
478    /// Transforms a 2D vector by the transpose of `self`.
479    #[inline]
480    #[must_use]
481    pub fn mul_transpose_vec2(&self, rhs: Vec2) -> Vec2 {
482        Vec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
483    }
484
485    /// Multiplies two 2x2 matrices.
486    #[inline]
487    #[must_use]
488    pub fn mul_mat2(&self, rhs: &Self) -> Self {
489        self.mul(rhs)
490    }
491
492    /// Adds two 2x2 matrices.
493    #[inline]
494    #[must_use]
495    pub fn add_mat2(&self, rhs: &Self) -> Self {
496        self.add(rhs)
497    }
498
499    /// Subtracts two 2x2 matrices.
500    #[inline]
501    #[must_use]
502    pub fn sub_mat2(&self, rhs: &Self) -> Self {
503        self.sub(rhs)
504    }
505
506    /// Multiplies a 2x2 matrix by a scalar.
507    #[inline]
508    #[must_use]
509    pub fn mul_scalar(&self, rhs: f32) -> Self {
510        Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
511    }
512
513    /// Multiply `self` by a scaling vector `scale`.
514    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
515    /// This operation is commutative.
516    #[inline]
517    #[must_use]
518    pub fn mul_diagonal_scale(&self, scale: Vec2) -> Self {
519        Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
520    }
521
522    /// Divides a 2x2 matrix by a scalar.
523    #[inline]
524    #[must_use]
525    pub fn div_scalar(&self, rhs: f32) -> Self {
526        Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) })
527    }
528
529    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
530    #[inline]
531    #[must_use]
532    pub fn recip(&self) -> Self {
533        Self::from_cols(self.x_axis.recip(), self.y_axis.recip())
534    }
535
536    /// Returns true if the absolute difference of all elements between `self` and `rhs`
537    /// is less than or equal to `max_abs_diff`.
538    ///
539    /// This can be used to compare if two matrices contain similar elements. It works best
540    /// when comparing with a known value. The `max_abs_diff` that should be used used
541    /// depends on the values being compared against.
542    ///
543    /// For more see
544    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
545    #[inline]
546    #[must_use]
547    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
548        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
549            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
550    }
551
552    /// Takes the absolute value of each element in `self`
553    #[inline]
554    #[must_use]
555    pub fn abs(&self) -> Self {
556        Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
557    }
558
559    #[cfg(feature = "f64")]
560    #[inline]
561    #[must_use]
562    pub fn as_dmat2(&self) -> DMat2 {
563        DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
564    }
565}
566
567impl Default for Mat2 {
568    #[inline]
569    fn default() -> Self {
570        Self::IDENTITY
571    }
572}
573
574impl Add for Mat2 {
575    type Output = Self;
576    #[inline]
577    fn add(self, rhs: Self) -> Self {
578        Self(unsafe { _mm_add_ps(self.0, rhs.0) })
579    }
580}
581
582impl Add<&Self> for Mat2 {
583    type Output = Self;
584    #[inline]
585    fn add(self, rhs: &Self) -> Self {
586        self.add(*rhs)
587    }
588}
589
590impl Add<&Mat2> for &Mat2 {
591    type Output = Mat2;
592    #[inline]
593    fn add(self, rhs: &Mat2) -> Mat2 {
594        (*self).add(*rhs)
595    }
596}
597
598impl Add<Mat2> for &Mat2 {
599    type Output = Mat2;
600    #[inline]
601    fn add(self, rhs: Mat2) -> Mat2 {
602        (*self).add(rhs)
603    }
604}
605
606impl AddAssign for Mat2 {
607    #[inline]
608    fn add_assign(&mut self, rhs: Self) {
609        *self = self.add(rhs);
610    }
611}
612
613impl AddAssign<&Self> for Mat2 {
614    #[inline]
615    fn add_assign(&mut self, rhs: &Self) {
616        self.add_assign(*rhs);
617    }
618}
619
620impl Sub for Mat2 {
621    type Output = Self;
622    #[inline]
623    fn sub(self, rhs: Self) -> Self {
624        Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
625    }
626}
627
628impl Sub<&Self> for Mat2 {
629    type Output = Self;
630    #[inline]
631    fn sub(self, rhs: &Self) -> Self {
632        self.sub(*rhs)
633    }
634}
635
636impl Sub<&Mat2> for &Mat2 {
637    type Output = Mat2;
638    #[inline]
639    fn sub(self, rhs: &Mat2) -> Mat2 {
640        (*self).sub(*rhs)
641    }
642}
643
644impl Sub<Mat2> for &Mat2 {
645    type Output = Mat2;
646    #[inline]
647    fn sub(self, rhs: Mat2) -> Mat2 {
648        (*self).sub(rhs)
649    }
650}
651
652impl SubAssign for Mat2 {
653    #[inline]
654    fn sub_assign(&mut self, rhs: Self) {
655        *self = self.sub(rhs);
656    }
657}
658
659impl SubAssign<&Self> for Mat2 {
660    #[inline]
661    fn sub_assign(&mut self, rhs: &Self) {
662        self.sub_assign(*rhs);
663    }
664}
665
666impl Neg for Mat2 {
667    type Output = Self;
668    #[inline]
669    fn neg(self) -> Self::Output {
670        Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
671    }
672}
673
674impl Neg for &Mat2 {
675    type Output = Mat2;
676    #[inline]
677    fn neg(self) -> Mat2 {
678        (*self).neg()
679    }
680}
681
682impl Mul for Mat2 {
683    type Output = Self;
684    #[inline]
685    fn mul(self, rhs: Self) -> Self {
686        unsafe {
687            let abcd = self.0;
688            let rhs = rhs.0;
689            let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
690            let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
691            let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
692            let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
693            let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
694            let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
695            let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
696            let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
697            Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
698        }
699    }
700}
701
702impl Mul<&Self> for Mat2 {
703    type Output = Self;
704    #[inline]
705    fn mul(self, rhs: &Self) -> Self {
706        self.mul(*rhs)
707    }
708}
709
710impl Mul<&Mat2> for &Mat2 {
711    type Output = Mat2;
712    #[inline]
713    fn mul(self, rhs: &Mat2) -> Mat2 {
714        (*self).mul(*rhs)
715    }
716}
717
718impl Mul<Mat2> for &Mat2 {
719    type Output = Mat2;
720    #[inline]
721    fn mul(self, rhs: Mat2) -> Mat2 {
722        (*self).mul(rhs)
723    }
724}
725
726impl MulAssign for Mat2 {
727    #[inline]
728    fn mul_assign(&mut self, rhs: Self) {
729        *self = self.mul(rhs);
730    }
731}
732
733impl MulAssign<&Self> for Mat2 {
734    #[inline]
735    fn mul_assign(&mut self, rhs: &Self) {
736        self.mul_assign(*rhs);
737    }
738}
739
740impl Mul<Vec2> for Mat2 {
741    type Output = Vec2;
742    #[inline]
743    fn mul(self, rhs: Vec2) -> Self::Output {
744        self.mul_vec2(rhs)
745    }
746}
747
748impl Mul<&Vec2> for Mat2 {
749    type Output = Vec2;
750    #[inline]
751    fn mul(self, rhs: &Vec2) -> Vec2 {
752        self.mul(*rhs)
753    }
754}
755
756impl Mul<&Vec2> for &Mat2 {
757    type Output = Vec2;
758    #[inline]
759    fn mul(self, rhs: &Vec2) -> Vec2 {
760        (*self).mul(*rhs)
761    }
762}
763
764impl Mul<Vec2> for &Mat2 {
765    type Output = Vec2;
766    #[inline]
767    fn mul(self, rhs: Vec2) -> Vec2 {
768        (*self).mul(rhs)
769    }
770}
771
772impl Mul<Mat2> for f32 {
773    type Output = Mat2;
774    #[inline]
775    fn mul(self, rhs: Mat2) -> Self::Output {
776        rhs.mul_scalar(self)
777    }
778}
779
780impl Mul<&Mat2> for f32 {
781    type Output = Mat2;
782    #[inline]
783    fn mul(self, rhs: &Mat2) -> Mat2 {
784        self.mul(*rhs)
785    }
786}
787
788impl Mul<&Mat2> for &f32 {
789    type Output = Mat2;
790    #[inline]
791    fn mul(self, rhs: &Mat2) -> Mat2 {
792        (*self).mul(*rhs)
793    }
794}
795
796impl Mul<Mat2> for &f32 {
797    type Output = Mat2;
798    #[inline]
799    fn mul(self, rhs: Mat2) -> Mat2 {
800        (*self).mul(rhs)
801    }
802}
803
804impl Mul<f32> for Mat2 {
805    type Output = Self;
806    #[inline]
807    fn mul(self, rhs: f32) -> Self {
808        self.mul_scalar(rhs)
809    }
810}
811
812impl Mul<&f32> for Mat2 {
813    type Output = Self;
814    #[inline]
815    fn mul(self, rhs: &f32) -> Self {
816        self.mul(*rhs)
817    }
818}
819
820impl Mul<&f32> for &Mat2 {
821    type Output = Mat2;
822    #[inline]
823    fn mul(self, rhs: &f32) -> Mat2 {
824        (*self).mul(*rhs)
825    }
826}
827
828impl Mul<f32> for &Mat2 {
829    type Output = Mat2;
830    #[inline]
831    fn mul(self, rhs: f32) -> Mat2 {
832        (*self).mul(rhs)
833    }
834}
835
836impl MulAssign<f32> for Mat2 {
837    #[inline]
838    fn mul_assign(&mut self, rhs: f32) {
839        *self = self.mul(rhs);
840    }
841}
842
843impl MulAssign<&f32> for Mat2 {
844    #[inline]
845    fn mul_assign(&mut self, rhs: &f32) {
846        self.mul_assign(*rhs);
847    }
848}
849
850impl Div<Mat2> for f32 {
851    type Output = Mat2;
852    #[inline]
853    fn div(self, rhs: Mat2) -> Self::Output {
854        Mat2(unsafe { _mm_div_ps(_mm_set_ps1(self), rhs.0) })
855    }
856}
857
858impl Div<&Mat2> for f32 {
859    type Output = Mat2;
860    #[inline]
861    fn div(self, rhs: &Mat2) -> Mat2 {
862        self.div(*rhs)
863    }
864}
865
866impl Div<&Mat2> for &f32 {
867    type Output = Mat2;
868    #[inline]
869    fn div(self, rhs: &Mat2) -> Mat2 {
870        (*self).div(*rhs)
871    }
872}
873
874impl Div<Mat2> for &f32 {
875    type Output = Mat2;
876    #[inline]
877    fn div(self, rhs: Mat2) -> Mat2 {
878        (*self).div(rhs)
879    }
880}
881
882impl Div<f32> for Mat2 {
883    type Output = Self;
884    #[inline]
885    fn div(self, rhs: f32) -> Self {
886        self.div_scalar(rhs)
887    }
888}
889
890impl Div<&f32> for Mat2 {
891    type Output = Self;
892    #[inline]
893    fn div(self, rhs: &f32) -> Self {
894        self.div(*rhs)
895    }
896}
897
898impl Div<&f32> for &Mat2 {
899    type Output = Mat2;
900    #[inline]
901    fn div(self, rhs: &f32) -> Mat2 {
902        (*self).div(*rhs)
903    }
904}
905
906impl Div<f32> for &Mat2 {
907    type Output = Mat2;
908    #[inline]
909    fn div(self, rhs: f32) -> Mat2 {
910        (*self).div(rhs)
911    }
912}
913
914impl DivAssign<f32> for Mat2 {
915    #[inline]
916    fn div_assign(&mut self, rhs: f32) {
917        *self = self.div(rhs);
918    }
919}
920
921impl DivAssign<&f32> for Mat2 {
922    #[inline]
923    fn div_assign(&mut self, rhs: &f32) {
924        self.div_assign(*rhs);
925    }
926}
927
928impl Sum<Self> for Mat2 {
929    fn sum<I>(iter: I) -> Self
930    where
931        I: Iterator<Item = Self>,
932    {
933        iter.fold(Self::ZERO, Self::add)
934    }
935}
936
937impl<'a> Sum<&'a Self> for Mat2 {
938    fn sum<I>(iter: I) -> Self
939    where
940        I: Iterator<Item = &'a Self>,
941    {
942        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
943    }
944}
945
946impl Product for Mat2 {
947    fn product<I>(iter: I) -> Self
948    where
949        I: Iterator<Item = Self>,
950    {
951        iter.fold(Self::IDENTITY, Self::mul)
952    }
953}
954
955impl<'a> Product<&'a Self> for Mat2 {
956    fn product<I>(iter: I) -> Self
957    where
958        I: Iterator<Item = &'a Self>,
959    {
960        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
961    }
962}
963
964impl PartialEq for Mat2 {
965    #[inline]
966    fn eq(&self, rhs: &Self) -> bool {
967        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
968    }
969}
970
971impl AsRef<[f32; 4]> for Mat2 {
972    #[inline]
973    fn as_ref(&self) -> &[f32; 4] {
974        unsafe { &*(self as *const Self as *const [f32; 4]) }
975    }
976}
977
978impl AsMut<[f32; 4]> for Mat2 {
979    #[inline]
980    fn as_mut(&mut self) -> &mut [f32; 4] {
981        unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
982    }
983}
984
985impl core::ops::Deref for Mat2 {
986    type Target = crate::deref::Cols2<Vec2>;
987    #[inline]
988    fn deref(&self) -> &Self::Target {
989        unsafe { &*(self as *const Self as *const Self::Target) }
990    }
991}
992
993impl core::ops::DerefMut for Mat2 {
994    #[inline]
995    fn deref_mut(&mut self) -> &mut Self::Target {
996        unsafe { &mut *(self as *mut Self as *mut Self::Target) }
997    }
998}
999
1000impl fmt::Debug for Mat2 {
1001    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1002        fmt.debug_struct(stringify!(Mat2))
1003            .field("x_axis", &self.x_axis)
1004            .field("y_axis", &self.y_axis)
1005            .finish()
1006    }
1007}
1008
1009impl fmt::Display for Mat2 {
1010    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1011        if let Some(p) = f.precision() {
1012            write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
1013        } else {
1014            write!(f, "[{}, {}]", self.x_axis, self.y_axis)
1015        }
1016    }
1017}