glam_matrix_extras/symmetric/
symmetric_mat2.rs

1use core::iter::Sum;
2use core::ops::*;
3#[cfg(feature = "f64")]
4use glam::{DMat2, DVec2};
5use glam::{Mat2, Vec2};
6
7#[cfg(feature = "bevy_reflect")]
8use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize, std_traits::ReflectDefault};
9
10#[cfg(feature = "f64")]
11use crate::{DMat23, DMat32};
12#[cfg(feature = "f32")]
13use crate::{Mat23, Mat32};
14use crate::{MatConversionError, SquareMatExt, ops::FloatAbs};
15
16/// An extension trait for 2x2 matrices.
17pub trait Mat2Ext {
18    /// The type of the symmetric 2x2 matrix.
19    type SymmetricMat2;
20
21    /// Multiplies `self` by a symmetric 2x2 matrix.
22    fn mul_symmetric_mat2(&self, rhs: &Self::SymmetricMat2) -> Self;
23
24    /// Adds a symmetric 2x2 matrix to `self`.
25    fn add_symmetric_mat2(&self, rhs: &Self::SymmetricMat2) -> Self;
26
27    /// Subtracts a symmetric 2x2 matrix from `self`.
28    fn sub_symmetric_mat2(&self, rhs: &Self::SymmetricMat2) -> Self;
29}
30
31#[cfg(feature = "f32")]
32impl Mat2Ext for Mat2 {
33    type SymmetricMat2 = SymmetricMat2;
34
35    #[inline]
36    fn mul_symmetric_mat2(&self, rhs: &SymmetricMat2) -> Mat2 {
37        self.mul(rhs)
38    }
39
40    #[inline]
41    fn add_symmetric_mat2(&self, rhs: &SymmetricMat2) -> Mat2 {
42        self.add(rhs)
43    }
44
45    #[inline]
46    fn sub_symmetric_mat2(&self, rhs: &SymmetricMat2) -> Mat2 {
47        self.sub(rhs)
48    }
49}
50
51#[cfg(feature = "f64")]
52impl Mat2Ext for DMat2 {
53    type SymmetricMat2 = SymmetricDMat2;
54
55    #[inline]
56    fn mul_symmetric_mat2(&self, rhs: &SymmetricDMat2) -> DMat2 {
57        self.mul(rhs)
58    }
59
60    #[inline]
61    fn add_symmetric_mat2(&self, rhs: &SymmetricDMat2) -> DMat2 {
62        self.add(rhs)
63    }
64
65    #[inline]
66    fn sub_symmetric_mat2(&self, rhs: &SymmetricDMat2) -> DMat2 {
67        self.sub(rhs)
68    }
69}
70
71macro_rules! symmetric_mat2s {
72    ($($n:ident => $nonsymmetricn:ident, $m23t:ident, $m32t:ident, $vt:ident, $t:ident),+) => {
73        $(
74        /// The bottom left triangle (including the diagonal) of a symmetric 2x2 column-major matrix.
75        ///
76        /// This is useful for storing a symmetric 2x2 matrix in a more compact form and performing some
77        /// matrix operations more efficiently.
78        ///
79        /// Some defining properties of symmetric matrices include:
80        ///
81        /// - The matrix is equal to its transpose.
82        /// - The matrix has real eigenvalues.
83        /// - The eigenvectors corresponding to the eigenvalues are orthogonal.
84        /// - The matrix is always diagonalizable.
85        ///
86        /// The sum and difference of two symmetric matrices is always symmetric.
87        /// However, the product of two symmetric matrices is *only* symmetric
88        /// if the matrices are commutable, meaning that `AB = BA`.
89        #[derive(Clone, Copy, PartialEq)]
90        #[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
91        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
92        #[cfg_attr(
93            all(feature = "bevy_reflect", feature = "serde"),
94            reflect(Debug, Default, PartialEq, Serialize, Deserialize)
95        )]
96        pub struct $n {
97            /// The first element of the first column.
98            pub m00: $t,
99            /// The second element of the first column.
100            pub m01: $t,
101            /// The second element of the second column.
102            pub m11: $t,
103        }
104
105        impl $n {
106            /// A symmetric 2x2 matrix with all elements set to `0.0`.
107            pub const ZERO: Self = Self::new(0.0, 0.0, 0.0);
108
109            /// A symmetric 2x2 identity matrix, where all diagonal elements are `1.0`,
110            /// and all off-diagonal elements are `0.0`.
111            pub const IDENTITY: Self = Self::new(1.0, 0.0, 1.0);
112
113            /// All NaNs.
114            pub const NAN: Self = Self::new($t::NAN, $t::NAN, $t::NAN);
115
116            /// Creates a new symmetric 2x2 matrix from its bottom left triangle, including diagonal elements.
117            ///
118            /// The elements are in column-major order `mCR`, where `C` is the column index
119            /// and `R` is the row index.
120            #[inline(always)]
121            #[must_use]
122            pub const fn new(
123                m00: $t,
124                m01: $t,
125                m11: $t,
126            ) -> Self {
127                Self { m00, m01, m11 }
128            }
129
130            /// Creates a symmetric 2x2 matrix from three column vectors.
131            ///
132            /// Only the lower left triangle of the matrix is used. No check is performed to ensure
133            /// that the given columns truly produce a symmetric matrix.
134            #[inline(always)]
135            #[must_use]
136            pub const fn from_cols_unchecked(x_axis: $vt, y_axis: $vt) -> Self {
137                Self {
138                    m00: x_axis.x,
139                    m01: x_axis.y,
140                    m11: y_axis.y,
141                }
142            }
143
144            /// Creates a symmetric 2x2 matrix from an array stored in column major order.
145            ///
146            /// Only the lower left triangle of the matrix is used. No check is performed to ensure
147            /// that the given columns truly produce a symmetric matrix.
148            #[inline]
149            #[must_use]
150            pub const fn from_cols_array_unchecked(m: &[$t; 4]) -> Self {
151                Self::new(m[0], m[1], m[3])
152            }
153
154            /// Creates an array storing data in column major order.
155            #[inline]
156            #[must_use]
157            pub const fn to_cols_array(&self) -> [$t; 4] {
158                [self.m00, self.m01, self.m01, self.m11]
159            }
160
161            /// Creates a symmetric 2x2 matrix from a 2D array stored in column major order.
162            ///
163            /// Only the lower left triangle of the matrix is used. No check is performed to ensure
164            /// that the given columns truly produce a symmetric matrix.
165            #[inline]
166            #[must_use]
167            pub const fn from_cols_array_2d_unchecked(m: &[[$t; 2]; 2]) -> Self {
168                Self::from_cols_unchecked(
169                    $vt::from_array(m[0]),
170                    $vt::from_array(m[1]),
171                )
172            }
173
174            /// Creates a 2D array storing data in column major order.
175            #[inline]
176            #[must_use]
177            pub const fn to_cols_array_2d(&self) -> [[$t; 2]; 2] {
178                [[self.m00, self.m01], [self.m01, self.m11]]
179            }
180
181            /// Creates a 2x2 matrix from the first 4 values in `slice`.
182            ///
183            /// Only the lower left triangle of the matrix is used. No check is performed to ensure
184            /// that the given columns truly produce a symmetric matrix.
185            ///
186            /// # Panics
187            ///
188            /// Panics if `slice` is less than 4 elements long.
189            #[inline]
190            #[must_use]
191            pub const fn from_cols_slice(slice: &[$t]) -> Self {
192                Self::new(slice[0], slice[1], slice[3])
193            }
194
195            /// Creates a symmetric 2x2 matrix with its diagonal set to `diagonal` and all other entries set to `0.0`.
196            #[inline]
197            #[must_use]
198            #[doc(alias = "scale")]
199            pub const fn from_diagonal(diagonal: $vt) -> Self {
200                Self::new(diagonal.x, 0.0, diagonal.y)
201            }
202
203            /// Tries to create a symmetric 2x2 matrix from a 2x2 matrix.
204            ///
205            /// # Errors
206            ///
207            /// Returns a [`MatConversionError`] if the given matrix is not symmetric.
208            #[inline]
209            pub fn try_from_mat2(mat: $nonsymmetricn) -> Result<Self, MatConversionError> {
210                if mat.is_symmetric() {
211                    Ok(Self::from_mat2_unchecked(mat))
212                } else {
213                    Err(MatConversionError::Asymmetric)
214                }
215            }
216
217            /// Creates a symmetric 2x2 matrix from a 2x2 matrix.
218            ///
219            /// Only the lower left triangle of the matrix is used. No check is performed to ensure
220            /// that the given matrix is truly symmetric.
221            #[inline]
222            #[must_use]
223            pub fn from_mat2_unchecked(mat: $nonsymmetricn) -> Self {
224                Self::new(
225                    mat.x_axis.x,
226                    mat.x_axis.y,
227                    mat.y_axis.y,
228                )
229            }
230
231            /// Creates a 2x2 matrix from the symmetric 2x2 matrix in `self`.
232            #[inline]
233            #[must_use]
234            pub const fn to_mat2(&self) -> $nonsymmetricn {
235                $nonsymmetricn::from_cols_array(&self.to_cols_array())
236            }
237
238            /// Creates a new symmetric 2x2 matrix from the outer product `v * v^T`.
239            #[inline(always)]
240            #[must_use]
241            pub fn from_outer_product(v: $vt) -> Self {
242                Self::new(v.x * v.x, v.x * v.y, v.y * v.y)
243            }
244
245            /// Returns the matrix column for the given `index`.
246            ///
247            /// # Panics
248            ///
249            /// Panics if `index` is greater than 1.
250            #[inline]
251            #[must_use]
252            pub const fn col(&self, index: usize) -> $vt {
253                match index {
254                    0 => $vt::new(self.m00, self.m01),
255                    1 => $vt::new(self.m01, self.m11),
256                    _ => panic!("index out of bounds"),
257                }
258            }
259
260            /// Returns the matrix row for the given `index`.
261            ///
262            /// # Panics
263            ///
264            /// Panics if `index` is greater than 1.
265            #[inline]
266            #[must_use]
267            pub const fn row(&self, index: usize) -> $vt {
268                match index {
269                    0 => $vt::new(self.m00, self.m01),
270                    1 => $vt::new(self.m01, self.m11),
271                    _ => panic!("index out of bounds"),
272                }
273            }
274
275            /// Returns the diagonal of the matrix.
276            #[inline]
277            #[must_use]
278            pub fn diagonal(&self) -> $vt {
279                $vt::new(self.m00, self.m11)
280            }
281
282            /// Returns `true` if, and only if, all elements are finite.
283            /// If any element is either `NaN` or positive or negative infinity, this will return `false`.
284            #[inline]
285            #[must_use]
286            pub fn is_finite(&self) -> bool {
287                self.m00.is_finite() && self.m01.is_finite() && self.m11.is_finite()
288            }
289
290            /// Returns `true` if any elements are `NaN`.
291            #[inline]
292            #[must_use]
293            pub fn is_nan(&self) -> bool {
294                self.m00.is_nan() || self.m01.is_nan() || self.m11.is_nan()
295            }
296
297            /// Returns the determinant of `self`.
298            #[inline]
299            #[must_use]
300            pub fn determinant(&self) -> $t {
301                // A = [ a c ]
302                //     | c b |
303                //
304                // det(A) = ab - c^2
305                let [a, b, c] = [self.m00, self.m11, self.m01];
306                a * b - c * c
307            }
308
309            /// Returns the inverse of `self`.
310            ///
311            /// If the matrix is not invertible the returned matrix will be invalid.
312            #[inline]
313            #[must_use]
314            pub fn inverse(&self) -> Self {
315                let inv_det = 1.0 / self.determinant();
316                Self {
317                    m00: self.m11 * inv_det,
318                    m01: -self.m01 * inv_det,
319                    m11: self.m00 * inv_det,
320                }
321            }
322
323            /// Returns the inverse of `self`, or a zero matrix if the matrix is not invertible.
324            #[inline]
325            #[must_use]
326            pub fn inverse_or_zero(&self) -> Self {
327                let det = self.determinant();
328                if det == 0.0 {
329                    Self::ZERO
330                } else {
331                    let inv_det = 1.0 / det;
332                    Self {
333                        m00: self.m11 * inv_det,
334                        m01: -self.m01 * inv_det,
335                        m11: self.m00 * inv_det,
336                    }
337                }
338            }
339
340            /// Takes the absolute value of each element in `self`.
341            #[inline]
342            #[must_use]
343            pub fn abs(&self) -> Self {
344                Self::new(
345                    FloatAbs::abs(self.m00),
346                    FloatAbs::abs(self.m01),
347                    FloatAbs::abs(self.m11),
348                )
349            }
350
351            /// Transforms a 2D vector.
352            #[inline]
353            #[must_use]
354            pub fn mul_vec2(&self, rhs: $vt) -> $vt {
355                let mut res = self.col(0).mul(rhs.x);
356                res = res.add(self.col(1).mul(rhs.y));
357                res
358            }
359
360            /// Multiplies two 2x2 matrices.
361            #[inline]
362            #[must_use]
363            pub fn mul_mat2(&self, rhs: &$nonsymmetricn) -> $nonsymmetricn {
364                self.mul(rhs)
365            }
366
367            /// Multiplies `self` by a 2x3 matrix, `self * rhs`.
368            #[inline]
369            #[must_use]
370            pub fn mul_mat23(&self, rhs: &$m23t) -> $m23t {
371                self.mul(rhs)
372            }
373
374            /// Computes `a * transpose(b)`, assuming `a = b * M` for some symmetric matrix `M`.
375            ///
376            /// This effectively completes the second half of the sandwich product `b * M * transpose(b)`.
377            #[inline]
378            #[must_use]
379            pub fn complete_mat23_sandwich(a: &$m23t, b: &$m23t) -> Self {
380                Self::new(
381                    a.row(0).dot(b.row(0)),
382                    a.row(1).dot(b.row(0)),
383                    a.row(1).dot(b.row(1)),
384                )
385            }
386
387            /// Computes `a * transpose(b)`, assuming `a = b * M` for some symmetric matrix `M`.
388            ///
389            /// This effectively completes the second half of the sandwich product `b * M * transpose(b)`.
390            #[inline]
391            #[must_use]
392            pub fn complete_mat32_sandwich(a: &$m32t, b: &$m32t) -> Self {
393                Self::new(
394                    a.col(0).dot(b.col(0)),
395                    a.col(1).dot(b.col(0)),
396                    a.col(1).dot(b.col(1)),
397                )
398            }
399
400            /// Adds two 2x2 matrices.
401            #[inline]
402            #[must_use]
403            pub fn add_mat2(&self, rhs: &$nonsymmetricn) -> $nonsymmetricn {
404                self.add(rhs)
405            }
406
407            /// Subtracts two 2x2 matrices.
408            #[inline]
409            #[must_use]
410            pub fn sub_mat2(&self, rhs: &$nonsymmetricn) -> $nonsymmetricn {
411                self.sub(rhs)
412            }
413
414            /// Multiplies two symmetric 2x2 matrices.
415            #[inline]
416            #[must_use]
417            pub fn mul_symmetric_mat2(&self, rhs: &Self) -> $nonsymmetricn {
418                self.mul(rhs)
419            }
420
421            /// Adds two symmetric 2x2 matrices.
422            #[inline]
423            #[must_use]
424            pub fn add_symmetric_mat2(&self, rhs: &Self) -> Self {
425                self.add(rhs)
426            }
427
428            /// Subtracts two symmetric 2x2 matrices.
429            #[inline]
430            #[must_use]
431            pub fn sub_symmetric_mat2(&self, rhs: &Self) -> Self {
432                self.sub(rhs)
433            }
434
435            /// Multiplies a 2x2 matrix by a scalar.
436            #[inline]
437            #[must_use]
438            pub fn mul_scalar(&self, rhs: $t) -> Self {
439                Self::new(
440                    self.m00 * rhs,
441                    self.m01 * rhs,
442                    self.m11 * rhs,
443                )
444            }
445
446            /// Divides a 2x2 matrix by a scalar.
447            #[inline]
448            #[must_use]
449            pub fn div_scalar(&self, rhs: $t) -> Self {
450                Self::new(
451                    self.m00 / rhs,
452                    self.m01 / rhs,
453                    self.m11 / rhs,
454                )
455            }
456        }
457
458        impl Default for $n {
459            #[inline(always)]
460            fn default() -> Self {
461                Self::IDENTITY
462            }
463        }
464
465        impl TryFrom<$nonsymmetricn> for $n {
466            type Error = MatConversionError;
467
468            #[inline]
469            fn try_from(mat: $nonsymmetricn) -> Result<Self, Self::Error> {
470                Self::try_from_mat2(mat)
471            }
472        }
473
474        impl Add for $n {
475            type Output = Self;
476            #[inline]
477            fn add(self, rhs: Self) -> Self::Output {
478                Self::new(
479                    self.m00 + rhs.m00,
480                    self.m01 + rhs.m01,
481                    self.m11 + rhs.m11,
482                )
483            }
484        }
485
486        impl Add<&Self> for $n {
487            type Output = Self;
488            #[inline]
489            fn add(self, rhs: &Self) -> Self::Output {
490                self.add(*rhs)
491            }
492        }
493
494        impl Add<Self> for &$n {
495            type Output = $n;
496            #[inline]
497            fn add(self, rhs: Self) -> Self::Output {
498                (*self).add(rhs)
499            }
500        }
501
502        impl Add<&Self> for &$n {
503            type Output = $n;
504            #[inline]
505            fn add(self, rhs: &Self) -> Self::Output {
506                (*self).add(*rhs)
507            }
508        }
509
510        impl AddAssign for $n {
511            #[inline]
512            fn add_assign(&mut self, rhs: Self) {
513                *self = self.add(rhs);
514            }
515        }
516
517        impl AddAssign<&Self> for $n {
518            #[inline]
519            fn add_assign(&mut self, rhs: &Self) {
520                self.add_assign(*rhs);
521            }
522        }
523
524        impl Add<$nonsymmetricn> for $n {
525            type Output = $nonsymmetricn;
526            #[inline]
527            fn add(self, rhs: $nonsymmetricn) -> Self::Output {
528                $nonsymmetricn::from_cols(
529                    self.col(0).add(rhs.x_axis),
530                    self.col(1).add(rhs.y_axis),
531                )
532            }
533        }
534
535        impl Add<&$nonsymmetricn> for $n {
536            type Output = $nonsymmetricn;
537            #[inline]
538            fn add(self, rhs: &$nonsymmetricn) -> Self::Output {
539                self.add(*rhs)
540            }
541        }
542
543        impl Add<$nonsymmetricn> for &$n {
544            type Output = $nonsymmetricn;
545            #[inline]
546            fn add(self, rhs: $nonsymmetricn) -> Self::Output {
547                (*self).add(rhs)
548            }
549        }
550
551        impl Add<&$nonsymmetricn> for &$n {
552            type Output = $nonsymmetricn;
553            #[inline]
554            fn add(self, rhs: &$nonsymmetricn) -> Self::Output {
555                (*self).add(*rhs)
556            }
557        }
558
559        impl Add<$n> for $nonsymmetricn {
560            type Output = $nonsymmetricn;
561            #[inline]
562            fn add(self, rhs: $n) -> Self::Output {
563                rhs.add(&self)
564            }
565        }
566
567        impl Add<&$n> for $nonsymmetricn {
568            type Output = $nonsymmetricn;
569            #[inline]
570            fn add(self, rhs: &$n) -> Self::Output {
571                self.add(*rhs)
572            }
573        }
574
575        impl Add<&$n> for &$nonsymmetricn {
576            type Output = $nonsymmetricn;
577            #[inline]
578            fn add(self, rhs: &$n) -> Self::Output {
579                (*self).add(*rhs)
580            }
581        }
582
583        impl AddAssign<$n> for $nonsymmetricn {
584            #[inline]
585            fn add_assign(&mut self, rhs: $n) {
586                *self = self.add(rhs);
587            }
588        }
589
590        impl AddAssign<&$n> for $nonsymmetricn {
591            #[inline]
592            fn add_assign(&mut self, rhs: &$n) {
593                *self = self.add(*rhs);
594            }
595        }
596
597        impl Sub for $n {
598            type Output = Self;
599            #[inline]
600            fn sub(self, rhs: Self) -> Self::Output {
601                Self::new(
602                    self.m00 - rhs.m00,
603                    self.m01 - rhs.m01,
604                    self.m11 - rhs.m11,
605                )
606            }
607        }
608
609        impl Sub<&Self> for $n {
610            type Output = Self;
611            #[inline]
612            fn sub(self, rhs: &Self) -> Self::Output {
613                self.sub(*rhs)
614            }
615        }
616
617        impl Sub<Self> for &$n {
618            type Output = $n;
619            #[inline]
620            fn sub(self, rhs: Self) -> Self::Output {
621                (*self).sub(rhs)
622            }
623        }
624
625        impl Sub<&Self> for &$n {
626            type Output = $n;
627            #[inline]
628            fn sub(self, rhs: &Self) -> Self::Output {
629                (*self).sub(*rhs)
630            }
631        }
632
633        impl SubAssign for $n {
634            #[inline]
635            fn sub_assign(&mut self, rhs: Self) {
636                *self = self.sub(rhs);
637            }
638        }
639
640        impl SubAssign<&Self> for $n {
641            #[inline]
642            fn sub_assign(&mut self, rhs: &Self) {
643                self.sub_assign(*rhs);
644            }
645        }
646
647        impl Sub<$nonsymmetricn> for $n {
648            type Output = $nonsymmetricn;
649            #[inline]
650            fn sub(self, rhs: $nonsymmetricn) -> Self::Output {
651                $nonsymmetricn::from_cols(
652                    self.col(0).sub(rhs.x_axis),
653                    self.col(1).sub(rhs.y_axis),
654                )
655            }
656        }
657
658        impl Sub<&$nonsymmetricn> for $n {
659            type Output = $nonsymmetricn;
660            #[inline]
661            fn sub(self, rhs: &$nonsymmetricn) -> Self::Output {
662                self.sub(*rhs)
663            }
664        }
665
666        impl Sub<$nonsymmetricn> for &$n {
667            type Output = $nonsymmetricn;
668            #[inline]
669            fn sub(self, rhs: $nonsymmetricn) -> Self::Output {
670                (*self).sub(rhs)
671            }
672        }
673
674        impl Sub<&$nonsymmetricn> for &$n {
675            type Output = $nonsymmetricn;
676            #[inline]
677            fn sub(self, rhs: &$nonsymmetricn) -> Self::Output {
678                (*self).sub(*rhs)
679            }
680        }
681
682        impl Sub<$n> for $nonsymmetricn {
683            type Output = $nonsymmetricn;
684            #[inline]
685            fn sub(self, rhs: $n) -> Self::Output {
686                rhs.sub(&self)
687            }
688        }
689
690        impl Sub<&$n> for $nonsymmetricn {
691            type Output = $nonsymmetricn;
692            #[inline]
693            fn sub(self, rhs: &$n) -> Self::Output {
694                self.sub(*rhs)
695            }
696        }
697
698        impl Sub<&$n> for &$nonsymmetricn {
699            type Output = $nonsymmetricn;
700            #[inline]
701            fn sub(self, rhs: &$n) -> Self::Output {
702                (*self).sub(*rhs)
703            }
704        }
705
706        impl SubAssign<$n> for $nonsymmetricn {
707            #[inline]
708            fn sub_assign(&mut self, rhs: $n) {
709                *self = self.sub(rhs);
710            }
711        }
712
713        impl SubAssign<&$n> for $nonsymmetricn {
714            #[inline]
715            fn sub_assign(&mut self, rhs: &$n) {
716                *self = self.sub(*rhs);
717            }
718        }
719
720        impl Neg for $n {
721            type Output = Self;
722            #[inline]
723            fn neg(self) -> Self::Output {
724                Self::new(
725                    -self.m00, -self.m01, -self.m11,
726                )
727            }
728        }
729
730        impl Neg for &$n {
731            type Output = $n;
732            #[inline]
733            fn neg(self) -> Self::Output {
734                (*self).neg()
735            }
736        }
737
738        impl Mul for $n {
739            type Output = $nonsymmetricn;
740            #[inline]
741            fn mul(self, rhs: Self) -> Self::Output {
742                $nonsymmetricn::from_cols(self.mul(rhs.col(0)), self.mul(rhs.col(1)))
743            }
744        }
745
746        impl Mul<&Self> for $n {
747            type Output = $nonsymmetricn;
748            #[inline]
749            fn mul(self, rhs: &Self) -> Self::Output {
750                self.mul(*rhs)
751            }
752        }
753
754        impl Mul<Self> for &$n {
755            type Output = $nonsymmetricn;
756            #[inline]
757            fn mul(self, rhs: Self) -> Self::Output {
758                (*self).mul(rhs)
759            }
760        }
761
762        impl Mul<&Self> for &$n {
763            type Output = $nonsymmetricn;
764            #[inline]
765            fn mul(self, rhs: &Self) -> Self::Output {
766                (*self).mul(*rhs)
767            }
768        }
769
770        impl Mul<$n> for $nonsymmetricn {
771            type Output = Self;
772            #[inline]
773            fn mul(self, rhs: $n) -> Self::Output {
774                Self::from_cols_array(&[
775                    self.x_axis.x * rhs.m00 + self.y_axis.x * rhs.m01,
776                    self.x_axis.y * rhs.m00 + self.y_axis.y * rhs.m01,
777                    self.x_axis.x * rhs.m01 + self.y_axis.x * rhs.m11,
778                    self.x_axis.y * rhs.m01 + self.y_axis.y * rhs.m11,
779                ])
780            }
781        }
782
783        impl Mul<&$n> for $nonsymmetricn {
784            type Output = Self;
785            #[inline]
786            fn mul(self, rhs: &$n) -> Self::Output {
787                self.mul(*rhs)
788            }
789        }
790
791        impl Mul<$n> for &$nonsymmetricn {
792            type Output = $nonsymmetricn;
793            #[inline]
794            fn mul(self, rhs: $n) -> Self::Output {
795                (*self).mul(rhs)
796            }
797        }
798
799        impl Mul<&$n> for &$nonsymmetricn {
800            type Output = $nonsymmetricn;
801            #[inline]
802            fn mul(self, rhs: &$n) -> Self::Output {
803                (*self).mul(*rhs)
804            }
805        }
806
807        impl MulAssign<$n> for $nonsymmetricn {
808            #[inline]
809            fn mul_assign(&mut self, rhs: $n) {
810                *self = self.mul(rhs);
811            }
812        }
813
814        impl MulAssign<&$n> for $nonsymmetricn {
815            #[inline]
816            fn mul_assign(&mut self, rhs: &$n) {
817                *self = self.mul(*rhs);
818            }
819        }
820
821        impl Mul<$nonsymmetricn> for $n {
822            type Output = $nonsymmetricn;
823            #[inline]
824            fn mul(self, rhs: $nonsymmetricn) -> Self::Output {
825                $nonsymmetricn::from_cols(
826                    self.mul(rhs.x_axis),
827                    self.mul(rhs.y_axis),
828                )
829            }
830        }
831
832        impl Mul<&$nonsymmetricn> for $n {
833            type Output = $nonsymmetricn;
834            #[inline]
835            fn mul(self, rhs: &$nonsymmetricn) -> Self::Output {
836                self.mul(*rhs)
837            }
838        }
839
840        impl Mul<$nonsymmetricn> for &$n {
841            type Output = $nonsymmetricn;
842            #[inline]
843            fn mul(self, rhs: $nonsymmetricn) -> Self::Output {
844                (*self).mul(rhs)
845            }
846        }
847
848        impl Mul<&$nonsymmetricn> for &$n {
849            type Output = $nonsymmetricn;
850            #[inline]
851            fn mul(self, rhs: &$nonsymmetricn) -> Self::Output {
852                (*self).mul(*rhs)
853            }
854        }
855
856        impl Mul<$m23t> for $n {
857            type Output = $m23t;
858            #[inline]
859            fn mul(self, rhs: $m23t) -> Self::Output {
860                $m23t::from_cols(
861                    $vt::new(
862                        self.row(0).dot(rhs.x_axis),
863                        self.row(1).dot(rhs.x_axis),
864                    ),
865                    $vt::new(
866                        self.row(0).dot(rhs.y_axis),
867                        self.row(1).dot(rhs.y_axis),
868                    ),
869                    $vt::new(
870                        self.row(0).dot(rhs.z_axis),
871                        self.row(1).dot(rhs.z_axis),
872                    ),
873                )
874            }
875        }
876
877        impl Mul<&$m23t> for $n {
878            type Output = $m23t;
879            #[inline]
880            fn mul(self, rhs: &$m23t) -> Self::Output {
881                self.mul(*rhs)
882            }
883        }
884
885        impl Mul<$m23t> for &$n {
886            type Output = $m23t;
887            #[inline]
888            fn mul(self, rhs: $m23t) -> Self::Output {
889                (*self).mul(rhs)
890            }
891        }
892
893        impl Mul<&$m23t> for &$n {
894            type Output = $m23t;
895            #[inline]
896            fn mul(self, rhs: &$m23t) -> Self::Output {
897                (*self).mul(*rhs)
898            }
899        }
900
901        impl Mul<$vt> for $n {
902            type Output = $vt;
903            #[inline]
904            fn mul(self, rhs: $vt) -> Self::Output {
905                self.mul_vec2(rhs)
906            }
907        }
908
909        impl Mul<&$vt> for $n {
910            type Output = $vt;
911            #[inline]
912            fn mul(self, rhs: &$vt) -> Self::Output {
913                self.mul(*rhs)
914            }
915        }
916
917        impl Mul<$vt> for &$n {
918            type Output = $vt;
919            #[inline]
920            fn mul(self, rhs: $vt) -> Self::Output {
921                (*self).mul(rhs)
922            }
923        }
924
925        impl Mul<&$vt> for &$n {
926            type Output = $vt;
927            #[inline]
928            fn mul(self, rhs: &$vt) -> Self::Output {
929                (*self).mul(*rhs)
930            }
931        }
932
933        impl Mul<$n> for $t {
934            type Output = $n;
935            #[inline]
936            fn mul(self, rhs: $n) -> Self::Output {
937                rhs.mul_scalar(self)
938            }
939        }
940
941        impl Mul<&$n> for $t {
942            type Output = $n;
943            #[inline]
944            fn mul(self, rhs: &$n) -> Self::Output {
945                self.mul(*rhs)
946            }
947        }
948
949        impl Mul<$n> for &$t {
950            type Output = $n;
951            #[inline]
952            fn mul(self, rhs: $n) -> Self::Output {
953                (*self).mul(rhs)
954            }
955        }
956
957        impl Mul<&$n> for &$t {
958            type Output = $n;
959            #[inline]
960            fn mul(self, rhs: &$n) -> Self::Output {
961                (*self).mul(*rhs)
962            }
963        }
964
965        impl Mul<$t> for $n {
966            type Output = Self;
967            #[inline]
968            fn mul(self, rhs: $t) -> Self::Output {
969                self.mul_scalar(rhs)
970            }
971        }
972
973        impl Mul<&$t> for $n {
974            type Output = Self;
975            #[inline]
976            fn mul(self, rhs: &$t) -> Self::Output {
977                self.mul(*rhs)
978            }
979        }
980
981        impl Mul<$t> for &$n {
982            type Output = $n;
983            #[inline]
984            fn mul(self, rhs: $t) -> Self::Output {
985                (*self).mul(rhs)
986            }
987        }
988
989        impl Mul<&$t> for &$n {
990            type Output = $n;
991            #[inline]
992            fn mul(self, rhs: &$t) -> Self::Output {
993                (*self).mul(*rhs)
994            }
995        }
996
997        impl MulAssign<$t> for $n {
998            #[inline]
999            fn mul_assign(&mut self, rhs: $t) {
1000                *self = self.mul(rhs);
1001            }
1002        }
1003
1004        impl MulAssign<&$t> for $n {
1005            #[inline]
1006            fn mul_assign(&mut self, rhs: &$t) {
1007                self.mul_assign(*rhs);
1008            }
1009        }
1010
1011        impl Div<$n> for $t {
1012            type Output = $n;
1013            #[inline]
1014            fn div(self, rhs: $n) -> Self::Output {
1015                rhs.div_scalar(self)
1016            }
1017        }
1018
1019        impl Div<&$n> for $t {
1020            type Output = $n;
1021            #[inline]
1022            fn div(self, rhs: &$n) -> Self::Output {
1023                self.div(*rhs)
1024            }
1025        }
1026
1027        impl Div<$n> for &$t {
1028            type Output = $n;
1029            #[inline]
1030            fn div(self, rhs: $n) -> Self::Output {
1031                (*self).div(rhs)
1032            }
1033        }
1034
1035        impl Div<&$n> for &$t {
1036            type Output = $n;
1037            #[inline]
1038            fn div(self, rhs: &$n) -> Self::Output {
1039                (*self).div(*rhs)
1040            }
1041        }
1042
1043        impl Div<$t> for $n {
1044            type Output = Self;
1045            #[inline]
1046            fn div(self, rhs: $t) -> Self::Output {
1047                self.div_scalar(rhs)
1048            }
1049        }
1050
1051        impl Div<&$t> for $n {
1052            type Output = Self;
1053            #[inline]
1054            fn div(self, rhs: &$t) -> Self::Output {
1055                self.div(*rhs)
1056            }
1057        }
1058
1059        impl Div<$t> for &$n {
1060            type Output = $n;
1061            #[inline]
1062            fn div(self, rhs: $t) -> Self::Output {
1063                (*self).div(rhs)
1064            }
1065        }
1066
1067        impl Div<&$t> for &$n {
1068            type Output = $n;
1069            #[inline]
1070            fn div(self, rhs: &$t) -> Self::Output {
1071                (*self).div(*rhs)
1072            }
1073        }
1074
1075        impl DivAssign<$t> for $n {
1076            #[inline]
1077            fn div_assign(&mut self, rhs: $t) {
1078                *self = self.div(rhs);
1079            }
1080        }
1081
1082        impl DivAssign<&$t> for $n {
1083            #[inline]
1084            fn div_assign(&mut self, rhs: &$t) {
1085                self.div_assign(*rhs);
1086            }
1087        }
1088
1089        impl From<$n> for $nonsymmetricn {
1090            #[inline]
1091            fn from(mat: $n) -> Self {
1092                mat.to_mat2()
1093            }
1094        }
1095
1096        impl Sum<$n> for $n {
1097            fn sum<I: Iterator<Item = $n>>(iter: I) -> Self {
1098                iter.fold(Self::ZERO, Self::add)
1099            }
1100        }
1101
1102        impl<'a> Sum<&'a $n> for $n {
1103            fn sum<I: Iterator<Item = &'a $n>>(iter: I) -> Self {
1104                iter.fold(Self::ZERO, |a, &b| a.add(b))
1105            }
1106        }
1107
1108        #[cfg(feature = "approx")]
1109        impl approx::AbsDiffEq for $n {
1110            type Epsilon = $t;
1111
1112            #[inline]
1113            fn default_epsilon() -> Self::Epsilon {
1114                $t::default_epsilon()
1115            }
1116
1117            #[inline]
1118            fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
1119                self.m00.abs_diff_eq(&other.m00, epsilon)
1120                    && self.m01.abs_diff_eq(&other.m01, epsilon)
1121                    && self.m11.abs_diff_eq(&other.m11, epsilon)
1122            }
1123        }
1124
1125        #[cfg(feature = "approx")]
1126        impl approx::RelativeEq for $n {
1127            #[inline]
1128            fn default_max_relative() -> Self::Epsilon {
1129                $t::default_max_relative()
1130            }
1131
1132            #[inline]
1133            fn relative_eq(
1134                &self,
1135                other: &Self,
1136                epsilon: Self::Epsilon,
1137                max_relative: Self::Epsilon,
1138            ) -> bool {
1139                self.m00.relative_eq(&other.m00, epsilon, max_relative)
1140                    && self.m01.relative_eq(&other.m01, epsilon, max_relative)
1141                    && self.m11.relative_eq(&other.m11, epsilon, max_relative)
1142            }
1143        }
1144
1145        #[cfg(feature = "approx")]
1146        impl approx::UlpsEq for $n {
1147            #[inline]
1148            fn default_max_ulps() -> u32 {
1149                $t::default_max_ulps()
1150            }
1151
1152            #[inline]
1153            fn ulps_eq(
1154                &self,
1155                other: &Self,
1156                epsilon: Self::Epsilon,
1157                max_ulps: u32,
1158            ) -> bool {
1159                self.m00.ulps_eq(&other.m00, epsilon, max_ulps)
1160                    && self.m01.ulps_eq(&other.m01, epsilon, max_ulps)
1161                    && self.m11.ulps_eq(&other.m11, epsilon, max_ulps)
1162            }
1163        }
1164
1165        impl core::fmt::Debug for $n {
1166            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1167                f.debug_struct(stringify!($n))
1168                    .field("m00", &self.m00)
1169                    .field("m01", &self.m01)
1170                    .field("m11", &self.m11)
1171                    .finish()
1172            }
1173        }
1174
1175        impl core::fmt::Display for $n {
1176            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1177                if let Some(p) = f.precision() {
1178                    write!(
1179                        f,
1180                        "[[{:.*}, {:.*}], [{:.*}, {:.*}]]",
1181                        p, self.m00, p, self.m01, p, self.m01, p, self.m11
1182                    )
1183                } else {
1184                    write!(
1185                        f,
1186                        "[[{}, {}], [{}, {}]]",
1187                        self.m00, self.m01, self.m01, self.m11
1188                    )
1189                }
1190            }
1191        }
1192        )+
1193    }
1194}
1195
1196#[cfg(feature = "f32")]
1197symmetric_mat2s!(SymmetricMat2 => Mat2, Mat23, Mat32, Vec2, f32);
1198
1199#[cfg(feature = "f64")]
1200symmetric_mat2s!(SymmetricDMat2 => DMat2, DMat23, DMat32, DVec2, f64);
1201
1202#[cfg(all(feature = "f32", feature = "f64"))]
1203impl SymmetricMat2 {
1204    /// Returns the double precision version of `self`.
1205    #[inline]
1206    #[must_use]
1207    pub fn as_symmetric_dmat2(&self) -> SymmetricDMat2 {
1208        SymmetricDMat2 {
1209            m00: self.m00 as f64,
1210            m01: self.m01 as f64,
1211            m11: self.m11 as f64,
1212        }
1213    }
1214}
1215
1216#[cfg(all(feature = "f32", feature = "f64"))]
1217impl SymmetricDMat2 {
1218    /// Returns the single precision version of `self`.
1219    #[inline]
1220    #[must_use]
1221    pub fn as_symmetric_mat2(&self) -> SymmetricMat2 {
1222        SymmetricMat2 {
1223            m00: self.m00 as f32,
1224            m01: self.m01 as f32,
1225            m11: self.m11 as f32,
1226        }
1227    }
1228}