glam/f32/neon/
mat2.rs

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