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