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    #[track_caller]
195    pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self {
196        match (i, j) {
197            (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
198            (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
199            (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
200            (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
201            (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
202            (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
203            (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
204            (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
205            (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
206            _ => panic!("index out of bounds"),
207        }
208    }
209
210    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
211    #[inline]
212    #[must_use]
213    pub fn from_mat3a(m: Mat3A) -> Self {
214        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
215    }
216
217    /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
218    /// and `j`th row.
219    ///
220    /// # Panics
221    ///
222    /// Panics if `i` or `j` is greater than 2.
223    #[inline]
224    #[must_use]
225    #[track_caller]
226    pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self {
227        match (i, j) {
228            (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
229            (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
230            (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
231            (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
232            (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
233            (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
234            (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
235            (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
236            (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
237            _ => panic!("index out of bounds"),
238        }
239    }
240
241    /// Creates a 2x2 matrix from the first 4 values in `slice`.
242    ///
243    /// See also [`Self::from_rows_slice`] when the slice is in row major order.
244    ///
245    /// # Panics
246    ///
247    /// Panics if `slice` is less than 4 elements long.
248    #[inline]
249    #[must_use]
250    #[track_caller]
251    pub const fn from_cols_slice(slice: &[f32]) -> Self {
252        Self::new(slice[0], slice[1], slice[2], slice[3])
253    }
254
255    /// Writes the columns of `self` to the first 4 elements in `slice`.
256    ///
257    /// # Panics
258    ///
259    /// Panics if `slice` is less than 4 elements long.
260    #[inline]
261    #[track_caller]
262    pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
263        slice[0] = self.x_axis.x;
264        slice[1] = self.x_axis.y;
265        slice[2] = self.y_axis.x;
266        slice[3] = self.y_axis.y;
267    }
268
269    /// Creates a 2x2 matrix from the first 4 values in `slice`, stored in row
270    /// major order.
271    ///
272    /// Matrices are stored in column major order, so the slice is permuted into the
273    /// matrix layout. Use [`Self::from_cols_slice`] instead when the slice is already in
274    /// column major order.
275    ///
276    /// # Panics
277    ///
278    /// Panics if `slice` is less than 4 elements long.
279    #[inline]
280    #[must_use]
281    #[track_caller]
282    pub const fn from_rows_slice(slice: &[f32]) -> Self {
283        Self::new(slice[0], slice[2], slice[1], slice[3])
284    }
285
286    /// Returns the matrix column for the given `index`.
287    ///
288    /// # Panics
289    ///
290    /// Panics if `index` is greater than 1.
291    #[inline]
292    #[must_use]
293    #[track_caller]
294    pub fn col(&self, index: usize) -> Vec2 {
295        match index {
296            0 => self.x_axis,
297            1 => self.y_axis,
298            _ => panic!("index out of bounds"),
299        }
300    }
301
302    /// Returns a mutable reference to the matrix column for the given `index`.
303    ///
304    /// # Panics
305    ///
306    /// Panics if `index` is greater than 1.
307    #[inline]
308    #[track_caller]
309    pub fn col_mut(&mut self, index: usize) -> &mut Vec2 {
310        match index {
311            0 => &mut self.x_axis,
312            1 => &mut self.y_axis,
313            _ => panic!("index out of bounds"),
314        }
315    }
316
317    /// Returns the matrix row for the given `index`.
318    ///
319    /// See also [`Self::set_row`] when you need to change the row.
320    ///
321    /// # Panics
322    ///
323    /// Panics if `index` is greater than 1.
324    #[inline]
325    #[must_use]
326    #[track_caller]
327    pub fn row(&self, index: usize) -> Vec2 {
328        match index {
329            0 => Vec2::new(self.x_axis.x, self.y_axis.x),
330            1 => Vec2::new(self.x_axis.y, self.y_axis.y),
331            _ => panic!("index out of bounds"),
332        }
333    }
334
335    /// Sets the matrix row for the given `index`.
336    ///
337    /// Matrices are stored in column major order, so the row is spread across all
338    /// 2 columns and writing it touches every column. Use [`Self::col_mut`]
339    /// instead when you can work with columns. See also [`Self::row`].
340    ///
341    /// # Panics
342    ///
343    /// Panics if `index` is greater than 1.
344    #[inline]
345    #[track_caller]
346    pub fn set_row(&mut self, index: usize, row: Vec2) {
347        match index {
348            0 => {
349                self.x_axis.x = row.x;
350                self.y_axis.x = row.y;
351            }
352            1 => {
353                self.x_axis.y = row.x;
354                self.y_axis.y = row.y;
355            }
356            _ => panic!("index out of bounds"),
357        }
358    }
359
360    /// Returns `true` if, and only if, all elements are finite.
361    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
362    #[inline]
363    #[must_use]
364    pub fn is_finite(&self) -> bool {
365        self.x_axis.is_finite() && self.y_axis.is_finite()
366    }
367
368    /// Returns `true` if any elements are `NaN`.
369    #[inline]
370    #[must_use]
371    pub fn is_nan(&self) -> bool {
372        self.x_axis.is_nan() || self.y_axis.is_nan()
373    }
374
375    /// Returns the transpose of `self`.
376    #[inline]
377    #[must_use]
378    pub fn transpose(&self) -> Self {
379        Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) })
380    }
381
382    /// Returns the diagonal of `self`.
383    #[inline]
384    #[must_use]
385    pub fn diagonal(&self) -> Vec2 {
386        Vec2::new(self.x_axis.x, self.y_axis.y)
387    }
388
389    /// Returns the determinant of `self`.
390    #[inline]
391    #[must_use]
392    pub fn determinant(&self) -> f32 {
393        unsafe {
394            let abcd = self.0;
395            let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
396            let prod = _mm_mul_ps(abcd, dcba);
397            let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
398            _mm_cvtss_f32(det)
399        }
400    }
401
402    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
403    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
404    /// inverted matrix and true is returned.
405    ///
406    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
407    /// inverted matrix will be invalid. Will panic if the resulting inverted matrix is not finite
408    /// when `glam_assert` is enabled.
409    ///
410    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
411    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
412    /// matrix is aligned.
413    #[inline(always)]
414    #[must_use]
415    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
416    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
417        unsafe {
418            const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]);
419            let abcd = self.0;
420            let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11);
421            let prod = _mm_mul_ps(abcd, dcba);
422            let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01));
423            let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00);
424            let tmp = _mm_div_ps(SIGN, det);
425            let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11);
426            let m = Self(_mm_mul_ps(dbca, tmp));
427            if CHECKED {
428                if !m.is_finite() {
429                    return (Self::ZERO, false);
430                }
431            } else {
432                glam_assert!(m.is_finite());
433            }
434            (m, true)
435        }
436    }
437
438    /// Returns the inverse of `self`.
439    ///
440    /// If the matrix is not invertible the returned matrix will be invalid. The
441    /// returned matrix will also be invalid if the inverse is not finite, which can
442    /// happen when `self` contains very large or very small values. Use
443    /// [`Self::try_inverse`] or [`Self::inverse_or_zero`] to detect these cases.
444    ///
445    /// # Panics
446    ///
447    /// Will panic if the resulting inverted matrix is not finite when `glam_assert`
448    /// is enabled.
449    #[inline]
450    #[must_use]
451    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
452    pub fn inverse(&self) -> Self {
453        self.inverse_checked::<false>().0
454    }
455
456    /// Returns the inverse of `self` or `None` if the matrix is not invertible, or if
457    /// the inverse is not finite.
458    #[inline]
459    #[must_use]
460    pub fn try_inverse(&self) -> Option<Self> {
461        let (m, is_valid) = self.inverse_checked::<true>();
462        if is_valid {
463            Some(m)
464        } else {
465            None
466        }
467    }
468
469    /// Returns the inverse of `self` or `Mat2::ZERO` if the matrix is not
470    /// invertible, or if the inverse is not finite.
471    #[inline]
472    #[must_use]
473    pub fn inverse_or_zero(&self) -> Self {
474        self.inverse_checked::<true>().0
475    }
476
477    /// Transforms a 2D vector.
478    #[inline]
479    #[must_use]
480    pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
481        unsafe {
482            use crate::Align16;
483            use core::mem::MaybeUninit;
484            let abcd = self.0;
485            let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
486            let axbxcydy = _mm_mul_ps(abcd, xxyy);
487            let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
488            let result = _mm_add_ps(axbxcydy, cydyaxbx);
489            let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
490            _mm_store_ps(out.as_mut_ptr().cast(), result);
491            out.assume_init().0
492        }
493    }
494
495    /// Transforms a 2D vector by the transpose of `self`.
496    #[inline]
497    #[must_use]
498    pub fn mul_transpose_vec2(&self, rhs: Vec2) -> Vec2 {
499        Vec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
500    }
501
502    /// Multiplies two 2x2 matrices.
503    #[inline]
504    #[must_use]
505    pub fn mul_mat2(&self, rhs: &Self) -> Self {
506        self.mul(rhs)
507    }
508
509    /// Adds two 2x2 matrices.
510    #[inline]
511    #[must_use]
512    pub fn add_mat2(&self, rhs: &Self) -> Self {
513        self.add(rhs)
514    }
515
516    /// Subtracts two 2x2 matrices.
517    #[inline]
518    #[must_use]
519    pub fn sub_mat2(&self, rhs: &Self) -> Self {
520        self.sub(rhs)
521    }
522
523    /// Multiplies a 2x2 matrix by a scalar.
524    #[inline]
525    #[must_use]
526    pub fn mul_scalar(&self, rhs: f32) -> Self {
527        Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
528    }
529
530    /// Multiply `self` by a scaling vector `scale`.
531    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
532    /// This operation is commutative.
533    #[inline]
534    #[must_use]
535    pub fn mul_diagonal_scale(&self, scale: Vec2) -> Self {
536        Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
537    }
538
539    /// Divides a 2x2 matrix by a scalar.
540    #[inline]
541    #[must_use]
542    pub fn div_scalar(&self, rhs: f32) -> Self {
543        Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) })
544    }
545
546    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
547    #[inline]
548    #[must_use]
549    pub fn recip(&self) -> Self {
550        Self::from_cols(self.x_axis.recip(), self.y_axis.recip())
551    }
552
553    /// Returns true if the absolute difference of all elements between `self` and `rhs`
554    /// is less than or equal to `max_abs_diff`.
555    ///
556    /// This can be used to compare if two matrices contain similar elements. It works best
557    /// when comparing with a known value. The `max_abs_diff` that should be used used
558    /// depends on the values being compared against.
559    ///
560    /// For more see
561    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
562    #[inline]
563    #[must_use]
564    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
565        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
566            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
567    }
568
569    /// Takes the absolute value of each element in `self`
570    #[inline]
571    #[must_use]
572    pub fn abs(&self) -> Self {
573        Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
574    }
575
576    #[cfg(feature = "f64")]
577    #[inline]
578    #[must_use]
579    pub fn as_dmat2(&self) -> DMat2 {
580        DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
581    }
582}
583
584impl Default for Mat2 {
585    #[inline]
586    fn default() -> Self {
587        Self::IDENTITY
588    }
589}
590
591impl Add for Mat2 {
592    type Output = Self;
593    #[inline]
594    fn add(self, rhs: Self) -> Self {
595        Self(unsafe { _mm_add_ps(self.0, rhs.0) })
596    }
597}
598
599impl Add<&Self> for Mat2 {
600    type Output = Self;
601    #[inline]
602    fn add(self, rhs: &Self) -> Self {
603        self.add(*rhs)
604    }
605}
606
607impl Add<&Mat2> for &Mat2 {
608    type Output = Mat2;
609    #[inline]
610    fn add(self, rhs: &Mat2) -> Mat2 {
611        (*self).add(*rhs)
612    }
613}
614
615impl Add<Mat2> for &Mat2 {
616    type Output = Mat2;
617    #[inline]
618    fn add(self, rhs: Mat2) -> Mat2 {
619        (*self).add(rhs)
620    }
621}
622
623impl AddAssign for Mat2 {
624    #[inline]
625    fn add_assign(&mut self, rhs: Self) {
626        *self = self.add(rhs);
627    }
628}
629
630impl AddAssign<&Self> for Mat2 {
631    #[inline]
632    fn add_assign(&mut self, rhs: &Self) {
633        self.add_assign(*rhs);
634    }
635}
636
637impl Sub for Mat2 {
638    type Output = Self;
639    #[inline]
640    fn sub(self, rhs: Self) -> Self {
641        Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
642    }
643}
644
645impl Sub<&Self> for Mat2 {
646    type Output = Self;
647    #[inline]
648    fn sub(self, rhs: &Self) -> Self {
649        self.sub(*rhs)
650    }
651}
652
653impl Sub<&Mat2> for &Mat2 {
654    type Output = Mat2;
655    #[inline]
656    fn sub(self, rhs: &Mat2) -> Mat2 {
657        (*self).sub(*rhs)
658    }
659}
660
661impl Sub<Mat2> for &Mat2 {
662    type Output = Mat2;
663    #[inline]
664    fn sub(self, rhs: Mat2) -> Mat2 {
665        (*self).sub(rhs)
666    }
667}
668
669impl SubAssign for Mat2 {
670    #[inline]
671    fn sub_assign(&mut self, rhs: Self) {
672        *self = self.sub(rhs);
673    }
674}
675
676impl SubAssign<&Self> for Mat2 {
677    #[inline]
678    fn sub_assign(&mut self, rhs: &Self) {
679        self.sub_assign(*rhs);
680    }
681}
682
683impl Neg for Mat2 {
684    type Output = Self;
685    #[inline]
686    fn neg(self) -> Self::Output {
687        Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
688    }
689}
690
691impl Neg for &Mat2 {
692    type Output = Mat2;
693    #[inline]
694    fn neg(self) -> Mat2 {
695        (*self).neg()
696    }
697}
698
699impl Mul for Mat2 {
700    type Output = Self;
701    #[inline]
702    fn mul(self, rhs: Self) -> Self {
703        unsafe {
704            let abcd = self.0;
705            let rhs = rhs.0;
706            let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
707            let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
708            let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
709            let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
710            let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
711            let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
712            let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
713            let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
714            Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
715        }
716    }
717}
718
719impl Mul<&Self> for Mat2 {
720    type Output = Self;
721    #[inline]
722    fn mul(self, rhs: &Self) -> Self {
723        self.mul(*rhs)
724    }
725}
726
727impl Mul<&Mat2> for &Mat2 {
728    type Output = Mat2;
729    #[inline]
730    fn mul(self, rhs: &Mat2) -> Mat2 {
731        (*self).mul(*rhs)
732    }
733}
734
735impl Mul<Mat2> for &Mat2 {
736    type Output = Mat2;
737    #[inline]
738    fn mul(self, rhs: Mat2) -> Mat2 {
739        (*self).mul(rhs)
740    }
741}
742
743impl MulAssign for Mat2 {
744    #[inline]
745    fn mul_assign(&mut self, rhs: Self) {
746        *self = self.mul(rhs);
747    }
748}
749
750impl MulAssign<&Self> for Mat2 {
751    #[inline]
752    fn mul_assign(&mut self, rhs: &Self) {
753        self.mul_assign(*rhs);
754    }
755}
756
757impl Mul<Vec2> for Mat2 {
758    type Output = Vec2;
759    #[inline]
760    fn mul(self, rhs: Vec2) -> Self::Output {
761        self.mul_vec2(rhs)
762    }
763}
764
765impl Mul<&Vec2> for Mat2 {
766    type Output = Vec2;
767    #[inline]
768    fn mul(self, rhs: &Vec2) -> Vec2 {
769        self.mul(*rhs)
770    }
771}
772
773impl Mul<&Vec2> for &Mat2 {
774    type Output = Vec2;
775    #[inline]
776    fn mul(self, rhs: &Vec2) -> Vec2 {
777        (*self).mul(*rhs)
778    }
779}
780
781impl Mul<Vec2> for &Mat2 {
782    type Output = Vec2;
783    #[inline]
784    fn mul(self, rhs: Vec2) -> Vec2 {
785        (*self).mul(rhs)
786    }
787}
788
789impl Mul<Mat2> for f32 {
790    type Output = Mat2;
791    #[inline]
792    fn mul(self, rhs: Mat2) -> Self::Output {
793        rhs.mul_scalar(self)
794    }
795}
796
797impl Mul<&Mat2> for f32 {
798    type Output = Mat2;
799    #[inline]
800    fn mul(self, rhs: &Mat2) -> Mat2 {
801        self.mul(*rhs)
802    }
803}
804
805impl Mul<&Mat2> for &f32 {
806    type Output = Mat2;
807    #[inline]
808    fn mul(self, rhs: &Mat2) -> Mat2 {
809        (*self).mul(*rhs)
810    }
811}
812
813impl Mul<Mat2> for &f32 {
814    type Output = Mat2;
815    #[inline]
816    fn mul(self, rhs: Mat2) -> Mat2 {
817        (*self).mul(rhs)
818    }
819}
820
821impl Mul<f32> for Mat2 {
822    type Output = Self;
823    #[inline]
824    fn mul(self, rhs: f32) -> Self {
825        self.mul_scalar(rhs)
826    }
827}
828
829impl Mul<&f32> for Mat2 {
830    type Output = Self;
831    #[inline]
832    fn mul(self, rhs: &f32) -> Self {
833        self.mul(*rhs)
834    }
835}
836
837impl Mul<&f32> for &Mat2 {
838    type Output = Mat2;
839    #[inline]
840    fn mul(self, rhs: &f32) -> Mat2 {
841        (*self).mul(*rhs)
842    }
843}
844
845impl Mul<f32> for &Mat2 {
846    type Output = Mat2;
847    #[inline]
848    fn mul(self, rhs: f32) -> Mat2 {
849        (*self).mul(rhs)
850    }
851}
852
853impl MulAssign<f32> for Mat2 {
854    #[inline]
855    fn mul_assign(&mut self, rhs: f32) {
856        *self = self.mul(rhs);
857    }
858}
859
860impl MulAssign<&f32> for Mat2 {
861    #[inline]
862    fn mul_assign(&mut self, rhs: &f32) {
863        self.mul_assign(*rhs);
864    }
865}
866
867impl Div<Mat2> for f32 {
868    type Output = Mat2;
869    #[inline]
870    fn div(self, rhs: Mat2) -> Self::Output {
871        Mat2(unsafe { _mm_div_ps(_mm_set_ps1(self), rhs.0) })
872    }
873}
874
875impl Div<&Mat2> for f32 {
876    type Output = Mat2;
877    #[inline]
878    fn div(self, rhs: &Mat2) -> Mat2 {
879        self.div(*rhs)
880    }
881}
882
883impl Div<&Mat2> for &f32 {
884    type Output = Mat2;
885    #[inline]
886    fn div(self, rhs: &Mat2) -> Mat2 {
887        (*self).div(*rhs)
888    }
889}
890
891impl Div<Mat2> for &f32 {
892    type Output = Mat2;
893    #[inline]
894    fn div(self, rhs: Mat2) -> Mat2 {
895        (*self).div(rhs)
896    }
897}
898
899impl Div<f32> for Mat2 {
900    type Output = Self;
901    #[inline]
902    fn div(self, rhs: f32) -> Self {
903        self.div_scalar(rhs)
904    }
905}
906
907impl Div<&f32> for Mat2 {
908    type Output = Self;
909    #[inline]
910    fn div(self, rhs: &f32) -> Self {
911        self.div(*rhs)
912    }
913}
914
915impl Div<&f32> for &Mat2 {
916    type Output = Mat2;
917    #[inline]
918    fn div(self, rhs: &f32) -> Mat2 {
919        (*self).div(*rhs)
920    }
921}
922
923impl Div<f32> for &Mat2 {
924    type Output = Mat2;
925    #[inline]
926    fn div(self, rhs: f32) -> Mat2 {
927        (*self).div(rhs)
928    }
929}
930
931impl DivAssign<f32> for Mat2 {
932    #[inline]
933    fn div_assign(&mut self, rhs: f32) {
934        *self = self.div(rhs);
935    }
936}
937
938impl DivAssign<&f32> for Mat2 {
939    #[inline]
940    fn div_assign(&mut self, rhs: &f32) {
941        self.div_assign(*rhs);
942    }
943}
944
945impl Sum<Self> for Mat2 {
946    fn sum<I>(iter: I) -> Self
947    where
948        I: Iterator<Item = Self>,
949    {
950        iter.fold(Self::ZERO, Self::add)
951    }
952}
953
954impl<'a> Sum<&'a Self> for Mat2 {
955    fn sum<I>(iter: I) -> Self
956    where
957        I: Iterator<Item = &'a Self>,
958    {
959        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
960    }
961}
962
963impl Product for Mat2 {
964    fn product<I>(iter: I) -> Self
965    where
966        I: Iterator<Item = Self>,
967    {
968        iter.fold(Self::IDENTITY, Self::mul)
969    }
970}
971
972impl<'a> Product<&'a Self> for Mat2 {
973    fn product<I>(iter: I) -> Self
974    where
975        I: Iterator<Item = &'a Self>,
976    {
977        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
978    }
979}
980
981impl PartialEq for Mat2 {
982    #[inline]
983    fn eq(&self, rhs: &Self) -> bool {
984        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
985    }
986}
987
988impl AsRef<[f32; 4]> for Mat2 {
989    #[inline]
990    fn as_ref(&self) -> &[f32; 4] {
991        unsafe { &*(self as *const Self as *const [f32; 4]) }
992    }
993}
994
995impl AsMut<[f32; 4]> for Mat2 {
996    #[inline]
997    fn as_mut(&mut self) -> &mut [f32; 4] {
998        unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
999    }
1000}
1001
1002impl core::ops::Deref for Mat2 {
1003    type Target = crate::deref::Cols2<Vec2>;
1004    #[inline]
1005    fn deref(&self) -> &Self::Target {
1006        unsafe { &*(self as *const Self as *const Self::Target) }
1007    }
1008}
1009
1010impl core::ops::DerefMut for Mat2 {
1011    #[inline]
1012    fn deref_mut(&mut self) -> &mut Self::Target {
1013        unsafe { &mut *(self as *mut Self as *mut Self::Target) }
1014    }
1015}
1016
1017impl fmt::Debug for Mat2 {
1018    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1019        fmt.debug_struct(stringify!(Mat2))
1020            .field("x_axis", &self.x_axis)
1021            .field("y_axis", &self.y_axis)
1022            .finish()
1023    }
1024}
1025
1026impl fmt::Display for Mat2 {
1027    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1028        if let Some(p) = f.precision() {
1029            write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
1030        } else {
1031            write!(f, "[{}, {}]", self.x_axis, self.y_axis)
1032        }
1033    }
1034}