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 #[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 pub x_axis: $v2t,
34 pub y_axis: $v2t,
36 pub z_axis: $v2t,
38 }
39
40 impl $n {
41 pub const ZERO: Self = Self::from_cols($v2t::ZERO, $v2t::ZERO, $v2t::ZERO);
43
44 pub const NAN: Self = Self::from_cols($v2t::NAN, $v2t::NAN, $v2t::NAN);
46
47 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[inline]
268 #[must_use]
269 pub fn mul_mat3(&self, rhs: &$m3t) -> Self {
270 self.mul(rhs)
271 }
272
273 #[inline]
275 #[must_use]
276 pub fn mul_symmetric_mat3(&self, rhs: &$symmetricm3t) -> Self {
277 self.mul(rhs)
278 }
279
280 #[inline]
282 #[must_use]
283 pub fn mul_mat32(&self, rhs: &$m32t) -> $m2t {
284 self.mul(rhs)
285 }
286
287 #[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 #[inline]
305 #[must_use]
306 pub fn add_mat32(&self, rhs: &Self) -> Self {
307 self.add(rhs)
308 }
309
310 #[inline]
312 #[must_use]
313 pub fn sub_mat32(&self, rhs: &Self) -> Self {
314 self.sub(rhs)
315 }
316
317 #[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 #[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 #[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 #[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}