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::{Mat3, Mat3A, Vec2, f32::math, swizzles::*};
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 { Some(m) } else { None }
463    }
464
465    /// Returns the inverse of `self` or `Mat2::ZERO` if the matrix is not
466    /// invertible, or if the inverse is not finite.
467    #[inline]
468    #[must_use]
469    pub fn inverse_or_zero(&self) -> Self {
470        self.inverse_checked::<true>().0
471    }
472
473    /// Transforms a 2D vector.
474    #[inline]
475    #[must_use]
476    pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 {
477        unsafe {
478            use crate::Align16;
479            use core::mem::MaybeUninit;
480            let abcd = self.0;
481            let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x);
482            let axbxcydy = _mm_mul_ps(abcd, xxyy);
483            let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10);
484            let result = _mm_add_ps(axbxcydy, cydyaxbx);
485            let mut out: MaybeUninit<Align16<Vec2>> = MaybeUninit::uninit();
486            _mm_store_ps(out.as_mut_ptr().cast(), result);
487            out.assume_init().0
488        }
489    }
490
491    /// Transforms a 2D vector by the transpose of `self`.
492    #[inline]
493    #[must_use]
494    pub fn mul_transpose_vec2(&self, rhs: Vec2) -> Vec2 {
495        Vec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
496    }
497
498    /// Multiplies two 2x2 matrices.
499    #[inline]
500    #[must_use]
501    pub fn mul_mat2(&self, rhs: &Self) -> Self {
502        self.mul(rhs)
503    }
504
505    /// Adds two 2x2 matrices.
506    #[inline]
507    #[must_use]
508    pub fn add_mat2(&self, rhs: &Self) -> Self {
509        self.add(rhs)
510    }
511
512    /// Subtracts two 2x2 matrices.
513    #[inline]
514    #[must_use]
515    pub fn sub_mat2(&self, rhs: &Self) -> Self {
516        self.sub(rhs)
517    }
518
519    /// Multiplies a 2x2 matrix by a scalar.
520    #[inline]
521    #[must_use]
522    pub fn mul_scalar(&self, rhs: f32) -> Self {
523        Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) })
524    }
525
526    /// Multiply `self` by a scaling vector `scale`.
527    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
528    /// This operation is commutative.
529    #[inline]
530    #[must_use]
531    pub fn mul_diagonal_scale(&self, scale: Vec2) -> Self {
532        Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
533    }
534
535    /// Divides a 2x2 matrix by a scalar.
536    #[inline]
537    #[must_use]
538    pub fn div_scalar(&self, rhs: f32) -> Self {
539        Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) })
540    }
541
542    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
543    #[inline]
544    #[must_use]
545    pub fn recip(&self) -> Self {
546        Self::from_cols(self.x_axis.recip(), self.y_axis.recip())
547    }
548
549    /// Returns true if the absolute difference of all elements between `self` and `rhs`
550    /// is less than or equal to `max_abs_diff`.
551    ///
552    /// This can be used to compare if two matrices contain similar elements. It works best
553    /// when comparing with a known value. The `max_abs_diff` that should be used used
554    /// depends on the values being compared against.
555    ///
556    /// For more see
557    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
558    #[inline]
559    #[must_use]
560    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
561        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
562            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
563    }
564
565    /// Takes the absolute value of each element in `self`
566    #[inline]
567    #[must_use]
568    pub fn abs(&self) -> Self {
569        Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
570    }
571
572    #[cfg(feature = "f64")]
573    #[inline]
574    #[must_use]
575    pub fn as_dmat2(&self) -> DMat2 {
576        DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2())
577    }
578}
579
580impl Default for Mat2 {
581    #[inline]
582    fn default() -> Self {
583        Self::IDENTITY
584    }
585}
586
587impl Add for Mat2 {
588    type Output = Self;
589    #[inline]
590    fn add(self, rhs: Self) -> Self {
591        Self(unsafe { _mm_add_ps(self.0, rhs.0) })
592    }
593}
594
595impl Add<&Self> for Mat2 {
596    type Output = Self;
597    #[inline]
598    fn add(self, rhs: &Self) -> Self {
599        self.add(*rhs)
600    }
601}
602
603impl Add<&Mat2> for &Mat2 {
604    type Output = Mat2;
605    #[inline]
606    fn add(self, rhs: &Mat2) -> Mat2 {
607        (*self).add(*rhs)
608    }
609}
610
611impl Add<Mat2> for &Mat2 {
612    type Output = Mat2;
613    #[inline]
614    fn add(self, rhs: Mat2) -> Mat2 {
615        (*self).add(rhs)
616    }
617}
618
619impl AddAssign for Mat2 {
620    #[inline]
621    fn add_assign(&mut self, rhs: Self) {
622        *self = self.add(rhs);
623    }
624}
625
626impl AddAssign<&Self> for Mat2 {
627    #[inline]
628    fn add_assign(&mut self, rhs: &Self) {
629        self.add_assign(*rhs);
630    }
631}
632
633impl Sub for Mat2 {
634    type Output = Self;
635    #[inline]
636    fn sub(self, rhs: Self) -> Self {
637        Self(unsafe { _mm_sub_ps(self.0, rhs.0) })
638    }
639}
640
641impl Sub<&Self> for Mat2 {
642    type Output = Self;
643    #[inline]
644    fn sub(self, rhs: &Self) -> Self {
645        self.sub(*rhs)
646    }
647}
648
649impl Sub<&Mat2> for &Mat2 {
650    type Output = Mat2;
651    #[inline]
652    fn sub(self, rhs: &Mat2) -> Mat2 {
653        (*self).sub(*rhs)
654    }
655}
656
657impl Sub<Mat2> for &Mat2 {
658    type Output = Mat2;
659    #[inline]
660    fn sub(self, rhs: Mat2) -> Mat2 {
661        (*self).sub(rhs)
662    }
663}
664
665impl SubAssign for Mat2 {
666    #[inline]
667    fn sub_assign(&mut self, rhs: Self) {
668        *self = self.sub(rhs);
669    }
670}
671
672impl SubAssign<&Self> for Mat2 {
673    #[inline]
674    fn sub_assign(&mut self, rhs: &Self) {
675        self.sub_assign(*rhs);
676    }
677}
678
679impl Neg for Mat2 {
680    type Output = Self;
681    #[inline]
682    fn neg(self) -> Self::Output {
683        Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) })
684    }
685}
686
687impl Neg for &Mat2 {
688    type Output = Mat2;
689    #[inline]
690    fn neg(self) -> Mat2 {
691        (*self).neg()
692    }
693}
694
695impl Mul for Mat2 {
696    type Output = Self;
697    #[inline]
698    fn mul(self, rhs: Self) -> Self {
699        unsafe {
700            let abcd = self.0;
701            let rhs = rhs.0;
702            let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00);
703            let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10);
704            let axbxcydy0 = _mm_mul_ps(abcd, xxyy0);
705            let axbxcydy1 = _mm_mul_ps(abcd, xxyy1);
706            let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10);
707            let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10);
708            let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0);
709            let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1);
710            Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00))
711        }
712    }
713}
714
715impl Mul<&Self> for Mat2 {
716    type Output = Self;
717    #[inline]
718    fn mul(self, rhs: &Self) -> Self {
719        self.mul(*rhs)
720    }
721}
722
723impl Mul<&Mat2> for &Mat2 {
724    type Output = Mat2;
725    #[inline]
726    fn mul(self, rhs: &Mat2) -> Mat2 {
727        (*self).mul(*rhs)
728    }
729}
730
731impl Mul<Mat2> for &Mat2 {
732    type Output = Mat2;
733    #[inline]
734    fn mul(self, rhs: Mat2) -> Mat2 {
735        (*self).mul(rhs)
736    }
737}
738
739impl MulAssign for Mat2 {
740    #[inline]
741    fn mul_assign(&mut self, rhs: Self) {
742        *self = self.mul(rhs);
743    }
744}
745
746impl MulAssign<&Self> for Mat2 {
747    #[inline]
748    fn mul_assign(&mut self, rhs: &Self) {
749        self.mul_assign(*rhs);
750    }
751}
752
753impl Mul<Vec2> for Mat2 {
754    type Output = Vec2;
755    #[inline]
756    fn mul(self, rhs: Vec2) -> Self::Output {
757        self.mul_vec2(rhs)
758    }
759}
760
761impl Mul<&Vec2> for Mat2 {
762    type Output = Vec2;
763    #[inline]
764    fn mul(self, rhs: &Vec2) -> Vec2 {
765        self.mul(*rhs)
766    }
767}
768
769impl Mul<&Vec2> for &Mat2 {
770    type Output = Vec2;
771    #[inline]
772    fn mul(self, rhs: &Vec2) -> Vec2 {
773        (*self).mul(*rhs)
774    }
775}
776
777impl Mul<Vec2> for &Mat2 {
778    type Output = Vec2;
779    #[inline]
780    fn mul(self, rhs: Vec2) -> Vec2 {
781        (*self).mul(rhs)
782    }
783}
784
785impl Mul<Mat2> for f32 {
786    type Output = Mat2;
787    #[inline]
788    fn mul(self, rhs: Mat2) -> Self::Output {
789        rhs.mul_scalar(self)
790    }
791}
792
793impl Mul<&Mat2> for f32 {
794    type Output = Mat2;
795    #[inline]
796    fn mul(self, rhs: &Mat2) -> Mat2 {
797        self.mul(*rhs)
798    }
799}
800
801impl Mul<&Mat2> for &f32 {
802    type Output = Mat2;
803    #[inline]
804    fn mul(self, rhs: &Mat2) -> Mat2 {
805        (*self).mul(*rhs)
806    }
807}
808
809impl Mul<Mat2> for &f32 {
810    type Output = Mat2;
811    #[inline]
812    fn mul(self, rhs: Mat2) -> Mat2 {
813        (*self).mul(rhs)
814    }
815}
816
817impl Mul<f32> for Mat2 {
818    type Output = Self;
819    #[inline]
820    fn mul(self, rhs: f32) -> Self {
821        self.mul_scalar(rhs)
822    }
823}
824
825impl Mul<&f32> for Mat2 {
826    type Output = Self;
827    #[inline]
828    fn mul(self, rhs: &f32) -> Self {
829        self.mul(*rhs)
830    }
831}
832
833impl Mul<&f32> for &Mat2 {
834    type Output = Mat2;
835    #[inline]
836    fn mul(self, rhs: &f32) -> Mat2 {
837        (*self).mul(*rhs)
838    }
839}
840
841impl Mul<f32> for &Mat2 {
842    type Output = Mat2;
843    #[inline]
844    fn mul(self, rhs: f32) -> Mat2 {
845        (*self).mul(rhs)
846    }
847}
848
849impl MulAssign<f32> for Mat2 {
850    #[inline]
851    fn mul_assign(&mut self, rhs: f32) {
852        *self = self.mul(rhs);
853    }
854}
855
856impl MulAssign<&f32> for Mat2 {
857    #[inline]
858    fn mul_assign(&mut self, rhs: &f32) {
859        self.mul_assign(*rhs);
860    }
861}
862
863impl Div<Mat2> for f32 {
864    type Output = Mat2;
865    #[inline]
866    fn div(self, rhs: Mat2) -> Self::Output {
867        Mat2(unsafe { _mm_div_ps(_mm_set_ps1(self), rhs.0) })
868    }
869}
870
871impl Div<&Mat2> for f32 {
872    type Output = Mat2;
873    #[inline]
874    fn div(self, rhs: &Mat2) -> Mat2 {
875        self.div(*rhs)
876    }
877}
878
879impl Div<&Mat2> for &f32 {
880    type Output = Mat2;
881    #[inline]
882    fn div(self, rhs: &Mat2) -> Mat2 {
883        (*self).div(*rhs)
884    }
885}
886
887impl Div<Mat2> for &f32 {
888    type Output = Mat2;
889    #[inline]
890    fn div(self, rhs: Mat2) -> Mat2 {
891        (*self).div(rhs)
892    }
893}
894
895impl Div<f32> for Mat2 {
896    type Output = Self;
897    #[inline]
898    fn div(self, rhs: f32) -> Self {
899        self.div_scalar(rhs)
900    }
901}
902
903impl Div<&f32> for Mat2 {
904    type Output = Self;
905    #[inline]
906    fn div(self, rhs: &f32) -> Self {
907        self.div(*rhs)
908    }
909}
910
911impl Div<&f32> for &Mat2 {
912    type Output = Mat2;
913    #[inline]
914    fn div(self, rhs: &f32) -> Mat2 {
915        (*self).div(*rhs)
916    }
917}
918
919impl Div<f32> for &Mat2 {
920    type Output = Mat2;
921    #[inline]
922    fn div(self, rhs: f32) -> Mat2 {
923        (*self).div(rhs)
924    }
925}
926
927impl DivAssign<f32> for Mat2 {
928    #[inline]
929    fn div_assign(&mut self, rhs: f32) {
930        *self = self.div(rhs);
931    }
932}
933
934impl DivAssign<&f32> for Mat2 {
935    #[inline]
936    fn div_assign(&mut self, rhs: &f32) {
937        self.div_assign(*rhs);
938    }
939}
940
941impl Sum<Self> for Mat2 {
942    fn sum<I>(iter: I) -> Self
943    where
944        I: Iterator<Item = Self>,
945    {
946        iter.fold(Self::ZERO, Self::add)
947    }
948}
949
950impl<'a> Sum<&'a Self> for Mat2 {
951    fn sum<I>(iter: I) -> Self
952    where
953        I: Iterator<Item = &'a Self>,
954    {
955        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
956    }
957}
958
959impl Product for Mat2 {
960    fn product<I>(iter: I) -> Self
961    where
962        I: Iterator<Item = Self>,
963    {
964        iter.fold(Self::IDENTITY, Self::mul)
965    }
966}
967
968impl<'a> Product<&'a Self> for Mat2 {
969    fn product<I>(iter: I) -> Self
970    where
971        I: Iterator<Item = &'a Self>,
972    {
973        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
974    }
975}
976
977impl PartialEq for Mat2 {
978    #[inline]
979    fn eq(&self, rhs: &Self) -> bool {
980        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
981    }
982}
983
984impl AsRef<[f32; 4]> for Mat2 {
985    #[inline]
986    fn as_ref(&self) -> &[f32; 4] {
987        unsafe { &*(self as *const Self as *const [f32; 4]) }
988    }
989}
990
991impl AsMut<[f32; 4]> for Mat2 {
992    #[inline]
993    fn as_mut(&mut self) -> &mut [f32; 4] {
994        unsafe { &mut *(self as *mut Self as *mut [f32; 4]) }
995    }
996}
997
998impl core::ops::Deref for Mat2 {
999    type Target = crate::deref::Cols2<Vec2>;
1000    #[inline]
1001    fn deref(&self) -> &Self::Target {
1002        unsafe { &*(self as *const Self as *const Self::Target) }
1003    }
1004}
1005
1006impl core::ops::DerefMut for Mat2 {
1007    #[inline]
1008    fn deref_mut(&mut self) -> &mut Self::Target {
1009        unsafe { &mut *(self as *mut Self as *mut Self::Target) }
1010    }
1011}
1012
1013impl fmt::Debug for Mat2 {
1014    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1015        fmt.debug_struct(stringify!(Mat2))
1016            .field("x_axis", &self.x_axis)
1017            .field("y_axis", &self.y_axis)
1018            .finish()
1019    }
1020}
1021
1022impl fmt::Display for Mat2 {
1023    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1024        if let Some(p) = f.precision() {
1025            write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
1026        } else {
1027            write!(f, "[{}, {}]", self.x_axis, self.y_axis)
1028        }
1029    }
1030}