Skip to main content

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