glam_matrix_extras/rectangular/
mat23.rs

1use core::iter::Sum;
2use core::ops::*;
3#[cfg(feature = "f64")]
4use glam::{DMat2, DMat3, DVec2, DVec3};
5#[cfg(feature = "f32")]
6use glam::{Mat2, Mat3, Vec2, Vec3};
7
8#[cfg(feature = "bevy_reflect")]
9use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize, std_traits::ReflectDefault};
10
11#[cfg(feature = "f64")]
12use crate::rectangular::DMat32;
13#[cfg(feature = "f32")]
14use crate::rectangular::Mat32;
15#[cfg(feature = "f64")]
16use crate::symmetric::SymmetricDMat3;
17#[cfg(feature = "f32")]
18use crate::symmetric::SymmetricMat3;
19
20macro_rules! mat23s {
21    ($($n:ident => $m32t:ident, $symmetricm3t:ident, $m2t:ident, $m3t:ident, $v2t:ident, $v3t:ident, $t:ident),+) => {
22        $(
23        /// A 2x3 column-major matrix.
24        #[derive(Clone, Copy, PartialEq)]
25        #[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
26        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27        #[cfg_attr(
28            all(feature = "bevy_reflect", feature = "serde"),
29            reflect(Debug, Default, PartialEq, Serialize, Deserialize)
30        )]
31        pub struct $n {
32            /// The first column of the matrix.
33            pub x_axis: $v2t,
34            /// The second column of the matrix.
35            pub y_axis: $v2t,
36            /// The third column of the matrix.
37            pub z_axis: $v2t,
38        }
39
40        impl $n {
41            /// A 2x3 matrix with all elements set to `0.0`.
42            pub const ZERO: Self = Self::from_cols($v2t::ZERO, $v2t::ZERO, $v2t::ZERO);
43
44            /// All NaNs.
45            pub const NAN: Self = Self::from_cols($v2t::NAN, $v2t::NAN, $v2t::NAN);
46
47            /// Creates a 2x3 matrix from two column vectors.
48            #[inline(always)]
49            #[must_use]
50            pub const fn from_cols(x_axis: $v2t, y_axis: $v2t, z_axis: $v2t) -> Self {
51                Self { x_axis, y_axis, z_axis }
52            }
53
54            /// Creates a 2x3 matrix from an array stored in column major order.
55            #[inline]
56            #[must_use]
57            pub const fn from_cols_array(m: &[$t; 6]) -> Self {
58                Self::from_cols(
59                    $v2t::new(m[0], m[1]),
60                    $v2t::new(m[2], m[3]),
61                    $v2t::new(m[4], m[5]),
62                )
63            }
64
65            /// Creates an array storing data in column major order.
66            #[inline]
67            #[must_use]
68            pub const fn to_cols_array(&self) -> [$t; 6] {
69                [
70                    self.x_axis.x,
71                    self.x_axis.y,
72                    self.y_axis.x,
73                    self.y_axis.y,
74                    self.z_axis.x,
75                    self.z_axis.y,
76                ]
77            }
78
79            /// Creates a 2x3 matrix from a 2D array stored in column major order.
80            #[inline]
81            #[must_use]
82            pub const fn from_cols_array_2d(m: &[[$t; 2]; 3]) -> Self {
83                Self::from_cols(
84                    $v2t::from_array(m[0]),
85                    $v2t::from_array(m[1]),
86                    $v2t::from_array(m[2]),
87                )
88            }
89
90            /// Creates a 2D array storing data in column major order.
91            #[inline]
92            #[must_use]
93            pub const fn to_cols_array_2d(&self) -> [[$t; 2]; 3] {
94                [
95                    self.x_axis.to_array(),
96                    self.y_axis.to_array(),
97                    self.z_axis.to_array(),
98                ]
99            }
100
101            /// Creates a 2x3 matrix from the first 6 values in `slice`.
102            ///
103            /// # Panics
104            ///
105            /// Panics if `slice` is less than 6 elements long.
106            #[inline]
107            #[must_use]
108            pub const fn from_cols_slice(slice: &[$t]) -> Self {
109                Self::from_cols(
110                    $v2t::new(slice[0], slice[1]),
111                    $v2t::new(slice[2], slice[3]),
112                    $v2t::new(slice[4], slice[5]),
113                )
114            }
115
116            /// Creates a 2x3 matrix from two row vectors.
117            #[inline(always)]
118            #[must_use]
119            pub const fn from_rows(row0: $v3t, row1: $v3t) -> Self {
120                Self {
121                    x_axis: $v2t::new(row0.x, row1.x),
122                    y_axis: $v2t::new(row0.y, row1.y),
123                    z_axis: $v2t::new(row0.z, row1.z),
124                }
125            }
126
127            /// Creates a 2x3 matrix from an array stored in row major order.
128            #[inline]
129            #[must_use]
130            pub const fn from_rows_array(m: &[$t; 6]) -> Self {
131                Self::from_rows(
132                    $v3t::new(m[0], m[1], m[2]),
133                    $v3t::new(m[3], m[4], m[5]),
134                )
135            }
136
137            /// Creates an array storing data in row major order.
138            #[inline]
139            #[must_use]
140            pub const fn to_rows_array(&self) -> [$t; 6] {
141                [
142                    self.x_axis.x,
143                    self.y_axis.x,
144                    self.z_axis.x,
145                    self.x_axis.y,
146                    self.y_axis.y,
147                    self.z_axis.y,
148                ]
149            }
150
151            /// Creates a 2x3 matrix from a 2D array stored in row major order.
152            #[inline]
153            #[must_use]
154            pub const fn from_rows_array_2d(m: &[[$t; 3]; 2]) -> Self {
155                Self::from_rows(
156                    $v3t::from_array(m[0]),
157                    $v3t::from_array(m[1]),
158                )
159            }
160
161            /// Creates a 2D array storing data in row major order.
162            #[inline]
163            #[must_use]
164            pub const fn to_rows_array_2d(&self) -> [[$t; 3]; 2] {
165                [
166                    [self.x_axis.x, self.y_axis.x, self.z_axis.x],
167                    [self.x_axis.y, self.y_axis.y, self.z_axis.y],
168                ]
169            }
170
171            /// Creates a 2x3 matrix from the first 6 values in `slice`.
172            ///
173            /// # Panics
174            ///
175            /// Panics if `slice` is less than 6 elements long.
176            #[inline]
177            #[must_use]
178            pub const fn from_rows_slice(slice: &[$t]) -> Self {
179                Self::from_rows(
180                    $v3t::new(slice[0], slice[1], slice[2]),
181                    $v3t::new(slice[3], slice[4], slice[5]),
182                )
183            }
184
185            /// Creates a new 2x3 matrix from the outer product `a * b^T`.
186            #[inline(always)]
187            #[must_use]
188            pub fn from_outer_product(a: $v2t, b: $v3t) -> Self {
189                Self::from_cols(
190                    $v2t::new(a.x * b.x, a.y * b.x),
191                    $v2t::new(a.x * b.y, a.y * b.y),
192                    $v2t::new(a.x * b.z, a.y * b.z),
193                )
194            }
195
196            /// Returns the matrix column for the given `index`.
197            ///
198            /// # Panics
199            ///
200            /// Panics if `index` is greater than 2.
201            #[inline]
202            #[must_use]
203            pub const fn col(&self, index: usize) -> $v2t {
204                match index {
205                    0 => self.x_axis,
206                    1 => self.y_axis,
207                    2 => self.z_axis,
208                    _ => panic!("index out of bounds"),
209                }
210            }
211
212            /// Returns the matrix row for the given `index`.
213            ///
214            /// # Panics
215            ///
216            /// Panics if `index` is greater than 1.
217            #[inline]
218            #[must_use]
219            pub const fn row(&self, index: usize) -> $v3t {
220                match index {
221                    0 => $v3t::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
222                    1 => $v3t::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
223                    _ => panic!("index out of bounds"),
224                }
225            }
226
227            /// Returns `true` if, and only if, all elements are finite.
228            /// If any element is either `NaN` or positive or negative infinity, this will return `false`.
229            #[inline]
230            #[must_use]
231            pub fn is_finite(&self) -> bool {
232                self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
233            }
234
235            /// Returns `true` if any elements are `NaN`.
236            #[inline]
237            #[must_use]
238            pub fn is_nan(&self) -> bool {
239                self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
240            }
241
242            /// Returns the transpose of `self`.
243            #[inline]
244            #[must_use]
245            pub fn transpose(&self) -> $m32t {
246                $m32t::from_rows(self.x_axis, self.y_axis, self.z_axis)
247            }
248
249            /// Takes the absolute value of each element in `self`.
250            #[inline]
251            #[must_use]
252            pub fn abs(&self) -> Self {
253                Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
254            }
255
256            /// Transforms a 3D vector into a 2D vector.
257            #[inline]
258            #[must_use]
259            pub fn mul_vec3(&self, rhs: $v3t) -> $v2t {
260                $v2t::new(
261                    rhs.dot(self.row(0)),
262                    rhs.dot(self.row(1)),
263                )
264            }
265
266            /// Multiplies `self` by a 3x3 matrix, `self * rhs`.
267            #[inline]
268            #[must_use]
269            pub fn mul_mat3(&self, rhs: &$m3t) -> Self {
270                self.mul(rhs)
271            }
272
273            /// Multiplies `self` by a symmetric 3x3 matrix, `self * rhs`.
274            #[inline]
275            #[must_use]
276            pub fn mul_symmetric_mat3(&self, rhs: &$symmetricm3t) -> Self {
277                self.mul(rhs)
278            }
279
280            /// Multiplies `self` by a 3x2 matrix, `self * rhs`.
281            #[inline]
282            #[must_use]
283            pub fn mul_mat32(&self, rhs: &$m32t) -> $m2t {
284                self.mul(rhs)
285            }
286
287            /// Multiplies `self` by another matrix that is treated as transposed, `self * rhs.transpose()`.
288            #[inline]
289            #[must_use]
290            pub fn mul_transposed_mat23(&self, rhs: &Self) -> $m2t {
291                $m2t::from_cols(
292                    $v2t::new(
293                        self.row(0).dot(rhs.row(0)),
294                        self.row(1).dot(rhs.row(0)),
295                    ),
296                    $v2t::new(
297                        self.row(0).dot(rhs.row(1)),
298                        self.row(1).dot(rhs.row(1)),
299                    ),
300                )
301            }
302
303            /// Adds two 2x2 matrices.
304            #[inline]
305            #[must_use]
306            pub fn add_mat32(&self, rhs: &Self) -> Self {
307                self.add(rhs)
308            }
309
310            /// Subtracts two 2x2 matrices.
311            #[inline]
312            #[must_use]
313            pub fn sub_mat32(&self, rhs: &Self) -> Self {
314                self.sub(rhs)
315            }
316
317            /// Multiplies a 2x3 matrix by a scalar.
318            #[inline]
319            #[must_use]
320            pub fn mul_scalar(&self, rhs: $t) -> Self {
321                Self::from_cols(self.x_axis * rhs, self.y_axis * rhs, self.z_axis * rhs)
322            }
323
324            /// Divides a 2x3 matrix by a scalar.
325            #[inline]
326            #[must_use]
327            pub fn div_scalar(&self, rhs: $t) -> Self {
328                let inv_rhs = rhs.recip();
329                Self::from_cols(self.x_axis * inv_rhs, self.y_axis * inv_rhs, self.z_axis * inv_rhs)
330            }
331        }
332
333        impl Default for $n {
334            #[inline(always)]
335            fn default() -> Self {
336                Self::ZERO
337            }
338        }
339
340        impl Add for $n {
341            type Output = Self;
342            #[inline]
343            fn add(self, rhs: Self) -> Self::Output {
344                Self::from_cols(
345                    self.x_axis + rhs.x_axis,
346                    self.y_axis + rhs.y_axis,
347                    self.z_axis + rhs.z_axis,
348                )
349            }
350        }
351
352        impl Add<&Self> for $n {
353            type Output = Self;
354            #[inline]
355            fn add(self, rhs: &Self) -> Self::Output {
356                self.add(*rhs)
357            }
358        }
359
360        impl Add<Self> for &$n {
361            type Output = $n;
362            #[inline]
363            fn add(self, rhs: Self) -> Self::Output {
364                (*self).add(rhs)
365            }
366        }
367
368        impl Add<&Self> for &$n {
369            type Output = $n;
370            #[inline]
371            fn add(self, rhs: &Self) -> Self::Output {
372                (*self).add(*rhs)
373            }
374        }
375
376        impl AddAssign for $n {
377            #[inline]
378            fn add_assign(&mut self, rhs: Self) {
379                *self = self.add(rhs);
380            }
381        }
382
383        impl AddAssign<&Self> for $n {
384            #[inline]
385            fn add_assign(&mut self, rhs: &Self) {
386                self.add_assign(*rhs);
387            }
388        }
389
390        impl Sub for $n {
391            type Output = Self;
392            #[inline]
393            fn sub(self, rhs: Self) -> Self::Output {
394                Self::from_cols(
395                    self.x_axis - rhs.x_axis,
396                    self.y_axis - rhs.y_axis,
397                    self.z_axis - rhs.z_axis,
398                )
399            }
400        }
401
402        impl Sub<&Self> for $n {
403            type Output = Self;
404            #[inline]
405            fn sub(self, rhs: &Self) -> Self::Output {
406                self.sub(*rhs)
407            }
408        }
409
410        impl Sub<Self> for &$n {
411            type Output = $n;
412            #[inline]
413            fn sub(self, rhs: Self) -> Self::Output {
414                (*self).sub(rhs)
415            }
416        }
417
418        impl Sub<&Self> for &$n {
419            type Output = $n;
420            #[inline]
421            fn sub(self, rhs: &Self) -> Self::Output {
422                (*self).sub(*rhs)
423            }
424        }
425
426        impl SubAssign for $n {
427            #[inline]
428            fn sub_assign(&mut self, rhs: Self) {
429                *self = self.sub(rhs);
430            }
431        }
432
433        impl SubAssign<&Self> for $n {
434            #[inline]
435            fn sub_assign(&mut self, rhs: &Self) {
436                self.sub_assign(*rhs);
437            }
438        }
439
440        impl Neg for $n {
441            type Output = Self;
442            #[inline]
443            fn neg(self) -> Self::Output {
444                Self::from_cols(-self.x_axis, -self.y_axis, -self.z_axis)
445            }
446        }
447
448        impl Neg for &$n {
449            type Output = $n;
450            #[inline]
451            fn neg(self) -> Self::Output {
452                (*self).neg()
453            }
454        }
455
456        impl Mul<$m3t> for $n {
457            type Output = Self;
458            #[inline]
459            fn mul(self, rhs: $m3t) -> Self::Output {
460                Self::from_rows(
461                    $v3t::new(
462                        self.row(0).dot(rhs.x_axis),
463                        self.row(0).dot(rhs.y_axis),
464                        self.row(0).dot(rhs.z_axis),
465                    ),
466                    $v3t::new(
467                        self.row(1).dot(rhs.x_axis),
468                        self.row(1).dot(rhs.y_axis),
469                        self.row(1).dot(rhs.z_axis),
470                    ),
471                )
472            }
473        }
474
475        impl Mul<&$m3t> for $n {
476            type Output = Self;
477            #[inline]
478            fn mul(self, rhs: &$m3t) -> Self::Output {
479                self.mul(*rhs)
480            }
481        }
482
483        impl Mul<$m3t> for &$n {
484            type Output = $n;
485            #[inline]
486            fn mul(self, rhs: $m3t) -> Self::Output {
487                (*self).mul(rhs)
488            }
489        }
490
491        impl Mul<&$m3t> for &$n {
492            type Output = $n;
493            #[inline]
494            fn mul(self, rhs: &$m3t) -> Self::Output {
495                (*self).mul(*rhs)
496            }
497        }
498
499        impl Mul<$symmetricm3t> for $n {
500            type Output = Self;
501            #[inline]
502            fn mul(self, rhs: $symmetricm3t) -> Self::Output {
503                Self::from_rows(
504                    $v3t::new(
505                        self.row(0).dot(rhs.col(0)),
506                        self.row(0).dot(rhs.col(1)),
507                        self.row(0).dot(rhs.col(2)),
508                    ),
509                    $v3t::new(
510                        self.row(1).dot(rhs.col(0)),
511                        self.row(1).dot(rhs.col(1)),
512                        self.row(1).dot(rhs.col(2)),
513                    ),
514                )
515            }
516        }
517
518        impl Mul<&$symmetricm3t> for $n {
519            type Output = Self;
520            #[inline]
521            fn mul(self, rhs: &$symmetricm3t) -> Self::Output {
522                self.mul(*rhs)
523            }
524        }
525
526        impl Mul<$symmetricm3t> for &$n {
527            type Output = $n;
528            #[inline]
529            fn mul(self, rhs: $symmetricm3t) -> Self::Output {
530                (*self).mul(rhs)
531            }
532        }
533
534        impl Mul<&$symmetricm3t> for &$n {
535            type Output = $n;
536            #[inline]
537            fn mul(self, rhs: &$symmetricm3t) -> Self::Output {
538                (*self).mul(*rhs)
539            }
540        }
541
542        impl Mul<$m32t> for $n {
543            type Output = $m2t;
544            #[inline]
545            fn mul(self, rhs: $m32t) -> Self::Output {
546                $m2t::from_cols(
547                    $v2t::new(
548                        self.row(0).dot(rhs.x_axis),
549                        self.row(1).dot(rhs.x_axis),
550                    ),
551                    $v2t::new(
552                        self.row(0).dot(rhs.y_axis),
553                        self.row(1).dot(rhs.y_axis),
554                    ),
555                )
556            }
557        }
558
559        impl Mul<&$m32t> for $n {
560            type Output = $m2t;
561            #[inline]
562            fn mul(self, rhs: &$m32t) -> Self::Output {
563                self.mul(*rhs)
564            }
565        }
566
567        impl Mul<$m32t> for &$n {
568            type Output = $m2t;
569            #[inline]
570            fn mul(self, rhs: $m32t) -> Self::Output {
571                (*self).mul(rhs)
572            }
573        }
574
575        impl Mul<&$m32t> for &$n {
576            type Output = $m2t;
577            #[inline]
578            fn mul(self, rhs: &$m32t) -> Self::Output {
579                (*self).mul(*rhs)
580            }
581        }
582
583        impl Mul<$v3t> for $n {
584            type Output = $v2t;
585            #[inline]
586            fn mul(self, rhs: $v3t) -> Self::Output {
587                self.mul_vec3(rhs)
588            }
589        }
590
591        impl Mul<&$v3t> for $n {
592            type Output = $v2t;
593            #[inline]
594            fn mul(self, rhs: &$v3t) -> Self::Output {
595                self.mul(*rhs)
596            }
597        }
598
599        impl Mul<$v3t> for &$n {
600            type Output = $v2t;
601            #[inline]
602            fn mul(self, rhs: $v3t) -> Self::Output {
603                (*self).mul(rhs)
604            }
605        }
606
607        impl Mul<&$v3t> for &$n {
608            type Output = $v2t;
609            #[inline]
610            fn mul(self, rhs: &$v3t) -> Self::Output {
611                (*self).mul(*rhs)
612            }
613        }
614
615        impl Mul<$n> for $t {
616            type Output = $n;
617            #[inline]
618            fn mul(self, rhs: $n) -> Self::Output {
619                rhs.mul_scalar(self)
620            }
621        }
622
623        impl Mul<&$n> for $t {
624            type Output = $n;
625            #[inline]
626            fn mul(self, rhs: &$n) -> Self::Output {
627                self.mul(*rhs)
628            }
629        }
630
631        impl Mul<$n> for &$t {
632            type Output = $n;
633            #[inline]
634            fn mul(self, rhs: $n) -> Self::Output {
635                (*self).mul(rhs)
636            }
637        }
638
639        impl Mul<&$n> for &$t {
640            type Output = $n;
641            #[inline]
642            fn mul(self, rhs: &$n) -> Self::Output {
643                (*self).mul(*rhs)
644            }
645        }
646
647        impl Mul<$t> for $n {
648            type Output = Self;
649            #[inline]
650            fn mul(self, rhs: $t) -> Self::Output {
651                self.mul_scalar(rhs)
652            }
653        }
654
655        impl Mul<&$t> for $n {
656            type Output = Self;
657            #[inline]
658            fn mul(self, rhs: &$t) -> Self::Output {
659                self.mul(*rhs)
660            }
661        }
662
663        impl Mul<$t> for &$n {
664            type Output = $n;
665            #[inline]
666            fn mul(self, rhs: $t) -> Self::Output {
667                (*self).mul(rhs)
668            }
669        }
670
671        impl Mul<&$t> for &$n {
672            type Output = $n;
673            #[inline]
674            fn mul(self, rhs: &$t) -> Self::Output {
675                (*self).mul(*rhs)
676            }
677        }
678
679        impl MulAssign<$t> for $n {
680            #[inline]
681            fn mul_assign(&mut self, rhs: $t) {
682                *self = self.mul(rhs);
683            }
684        }
685
686        impl MulAssign<&$t> for $n {
687            #[inline]
688            fn mul_assign(&mut self, rhs: &$t) {
689                self.mul_assign(*rhs);
690            }
691        }
692
693        impl Div<$n> for $t {
694            type Output = $n;
695            #[inline]
696            fn div(self, rhs: $n) -> Self::Output {
697                rhs.div_scalar(self)
698            }
699        }
700
701        impl Div<&$n> for $t {
702            type Output = $n;
703            #[inline]
704            fn div(self, rhs: &$n) -> Self::Output {
705                self.div(*rhs)
706            }
707        }
708
709        impl Div<$n> for &$t {
710            type Output = $n;
711            #[inline]
712            fn div(self, rhs: $n) -> Self::Output {
713                (*self).div(rhs)
714            }
715        }
716
717        impl Div<&$n> for &$t {
718            type Output = $n;
719            #[inline]
720            fn div(self, rhs: &$n) -> Self::Output {
721                (*self).div(*rhs)
722            }
723        }
724
725        impl Div<$t> for $n {
726            type Output = Self;
727            #[inline]
728            fn div(self, rhs: $t) -> Self::Output {
729                self.div_scalar(rhs)
730            }
731        }
732
733        impl Div<&$t> for $n {
734            type Output = Self;
735            #[inline]
736            fn div(self, rhs: &$t) -> Self::Output {
737                self.div(*rhs)
738            }
739        }
740
741        impl Div<$t> for &$n {
742            type Output = $n;
743            #[inline]
744            fn div(self, rhs: $t) -> Self::Output {
745                (*self).div(rhs)
746            }
747        }
748
749        impl Div<&$t> for &$n {
750            type Output = $n;
751            #[inline]
752            fn div(self, rhs: &$t) -> Self::Output {
753                (*self).div(*rhs)
754            }
755        }
756
757        impl DivAssign<$t> for $n {
758            #[inline]
759            fn div_assign(&mut self, rhs: $t) {
760                *self = self.div(rhs);
761            }
762        }
763
764        impl DivAssign<&$t> for $n {
765            #[inline]
766            fn div_assign(&mut self, rhs: &$t) {
767                self.div_assign(*rhs);
768            }
769        }
770
771        impl Sum<$n> for $n {
772            fn sum<I: Iterator<Item = $n>>(iter: I) -> Self {
773                iter.fold(Self::ZERO, Self::add)
774            }
775        }
776
777        impl<'a> Sum<&'a $n> for $n {
778            fn sum<I: Iterator<Item = &'a $n>>(iter: I) -> Self {
779                iter.fold(Self::ZERO, |a, &b| a.add(b))
780            }
781        }
782
783        #[cfg(feature = "approx")]
784        impl approx::AbsDiffEq for $n {
785            type Epsilon = $t;
786
787            #[inline]
788            fn default_epsilon() -> Self::Epsilon {
789                $t::default_epsilon()
790            }
791
792            #[inline]
793            fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
794                self.x_axis.abs_diff_eq(other.x_axis, epsilon)
795                    && self.y_axis.abs_diff_eq(other.y_axis, epsilon)
796            }
797        }
798
799        #[cfg(feature = "approx")]
800        impl approx::RelativeEq for $n {
801            #[inline]
802            fn default_max_relative() -> Self::Epsilon {
803                $t::default_max_relative()
804            }
805
806            #[inline]
807            fn relative_eq(
808                &self,
809                other: &Self,
810                epsilon: Self::Epsilon,
811                max_relative: Self::Epsilon,
812            ) -> bool {
813                self.x_axis.relative_eq(&other.x_axis, epsilon, max_relative)
814                    && self.y_axis.relative_eq(&other.y_axis, epsilon, max_relative)
815            }
816        }
817
818        #[cfg(feature = "approx")]
819        impl approx::UlpsEq for $n {
820            #[inline]
821            fn default_max_ulps() -> u32 {
822                $t::default_max_ulps()
823            }
824
825            #[inline]
826            fn ulps_eq(
827                &self,
828                other: &Self,
829                epsilon: Self::Epsilon,
830                max_ulps: u32,
831            ) -> bool {
832                self.x_axis.ulps_eq(&other.x_axis, epsilon, max_ulps)
833                    && self.y_axis.ulps_eq(&other.y_axis, epsilon, max_ulps)
834            }
835        }
836
837        impl core::fmt::Debug for $n {
838            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
839                f.debug_struct(stringify!($n))
840                    .field("x_axis", &self.x_axis)
841                    .field("y_axis", &self.y_axis)
842                    .finish()
843            }
844        }
845
846        impl core::fmt::Display for $n {
847            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
848                if let Some(p) = f.precision() {
849                    write!(
850                        f,
851                        "[[{:.*}, {:.*}], [{:.*}, {:.*}], [{:.*}, {:.*}]]",
852                        p, self.x_axis.x, p, self.x_axis.y,
853                        p, self.y_axis.x, p, self.y_axis.y,
854                        p, self.z_axis.x, p, self.z_axis.y,
855                    )
856                } else {
857                    write!(
858                        f,
859                        "[[{}, {}], [{}, {}], [{}, {}]]",
860                        self.x_axis.x, self.x_axis.y,
861                        self.y_axis.x, self.y_axis.y,
862                        self.z_axis.x, self.z_axis.y,
863                    )
864                }
865            }
866        }
867        )+
868    }
869}
870
871#[cfg(feature = "f32")]
872mat23s!(Mat23 => Mat32, SymmetricMat3, Mat2, Mat3, Vec2, Vec3, f32);
873
874#[cfg(feature = "f64")]
875mat23s!(DMat23 => DMat32, SymmetricDMat3, DMat2, DMat3, DVec2, DVec3, f64);
876
877#[cfg(all(feature = "f32", feature = "f64"))]
878impl Mat23 {
879    /// Returns the double precision version of `self`.
880    #[inline]
881    #[must_use]
882    pub fn as_dmat23(&self) -> DMat23 {
883        DMat23 {
884            x_axis: self.x_axis.as_dvec2(),
885            y_axis: self.y_axis.as_dvec2(),
886            z_axis: self.z_axis.as_dvec2(),
887        }
888    }
889}
890
891#[cfg(all(feature = "f32", feature = "f64"))]
892impl DMat23 {
893    /// Returns the single precision version of `self`.
894    #[inline]
895    #[must_use]
896    pub fn as_mat23(&self) -> Mat23 {
897        Mat23 {
898            x_axis: self.x_axis.as_vec2(),
899            y_axis: self.y_axis.as_vec2(),
900            z_axis: self.z_axis.as_vec2(),
901        }
902    }
903}
904
905#[cfg(test)]
906mod tests {
907    use glam::{Mat2, Mat3, vec2, vec3};
908
909    use crate::{Mat23, Mat32};
910
911    #[test]
912    fn mat23_mul_vec3() {
913        let mat = Mat23::from_rows(vec3(4.0, 1.0, 6.0), vec3(7.0, 9.0, 2.0));
914        let vec = vec3(1.0, 2.0, 3.0);
915
916        let expected = vec2(24.0, 31.0);
917        let result = mat.mul_vec3(vec);
918
919        assert_eq!(result, expected);
920    }
921
922    #[test]
923    fn mat23_mul_mat3() {
924        let mat23 = Mat23::from_rows(vec3(4.0, 1.0, 6.0), vec3(7.0, 9.0, 2.0));
925        let mat3 = Mat3::from_cols(
926            vec3(2.0, 5.0, 9.0),
927            vec3(1.0, 8.0, 4.0),
928            vec3(6.0, 3.0, 7.0),
929        );
930
931        let expected = Mat23::from_rows(vec3(67.0, 36.0, 69.0), vec3(77.0, 87.0, 83.0));
932        let result = mat23.mul_mat3(&mat3);
933
934        assert_eq!(result, expected);
935    }
936
937    #[test]
938    fn mat23_mul_mat32() {
939        let mat23 = Mat23::from_rows(vec3(4.0, 1.0, 6.0), vec3(7.0, 9.0, 2.0));
940        let mat32 = Mat32::from_cols(vec3(2.0, 5.0, 1.0), vec3(8.0, 3.0, 4.0));
941
942        let expected = Mat2::from_cols(vec2(19.0, 61.0), vec2(59.0, 91.0));
943        let result = mat23.mul_mat32(&mat32);
944
945        assert_eq!(result, expected);
946    }
947
948    #[test]
949    fn mat23_mul_transposed_mat23() {
950        let mat23_a = Mat23::from_rows(vec3(4.0, 1.0, 6.0), vec3(7.0, 9.0, 2.0));
951        let mat23_b = Mat23::from_rows(vec3(2.0, 5.0, 1.0), vec3(8.0, 3.0, 4.0));
952
953        let expected = Mat2::from_cols(vec2(19.0, 61.0), vec2(59.0, 91.0));
954        let result = mat23_a.mul_transposed_mat23(&mat23_b);
955
956        assert_eq!(result, expected);
957        assert_eq!(result, mat23_a * mat23_b.transpose());
958    }
959}