1use core::iter::Sum;
2use core::ops::*;
3#[cfg(feature = "f64")]
4use glam::{DMat3, DVec3};
5use glam::{Mat3, Vec3, Vec3A};
6
7#[cfg(feature = "bevy_reflect")]
8use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize, std_traits::ReflectDefault};
9
10use crate::{MatConversionError, SquareMatExt, ops::FloatAbs};
11
12#[cfg(feature = "f64")]
13use crate::rectangular::{DMat23, DMat32};
14#[cfg(feature = "f32")]
15use crate::rectangular::{Mat23, Mat32};
16
17pub trait Mat3Ext {
19 type SymmetricMat3;
21
22 fn mul_symmetric_mat3(&self, rhs: &Self::SymmetricMat3) -> Self;
24
25 fn add_symmetric_mat3(&self, rhs: &Self::SymmetricMat3) -> Self;
27
28 fn sub_symmetric_mat3(&self, rhs: &Self::SymmetricMat3) -> Self;
30}
31
32#[cfg(feature = "f32")]
33impl Mat3Ext for Mat3 {
34 type SymmetricMat3 = SymmetricMat3;
35
36 #[inline]
37 fn mul_symmetric_mat3(&self, rhs: &SymmetricMat3) -> Mat3 {
38 self.mul(rhs)
39 }
40
41 #[inline]
42 fn add_symmetric_mat3(&self, rhs: &SymmetricMat3) -> Mat3 {
43 self.add(rhs)
44 }
45
46 #[inline]
47 fn sub_symmetric_mat3(&self, rhs: &SymmetricMat3) -> Mat3 {
48 self.sub(rhs)
49 }
50}
51
52#[cfg(feature = "f64")]
53impl Mat3Ext for DMat3 {
54 type SymmetricMat3 = SymmetricDMat3;
55
56 #[inline]
57 fn mul_symmetric_mat3(&self, rhs: &SymmetricDMat3) -> DMat3 {
58 self.mul(rhs)
59 }
60
61 #[inline]
62 fn add_symmetric_mat3(&self, rhs: &SymmetricDMat3) -> DMat3 {
63 self.add(rhs)
64 }
65
66 #[inline]
67 fn sub_symmetric_mat3(&self, rhs: &SymmetricDMat3) -> DMat3 {
68 self.sub(rhs)
69 }
70}
71
72macro_rules! symmetric_mat3s {
73 ($($n:ident => $nonsymmetricn:ident, $m23t:ident, $m32t:ident, $v2t:ident, $vt:ident, $t:ident),+) => {
74 $(
75 #[derive(Clone, Copy, PartialEq)]
91 #[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
92 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93 #[cfg_attr(
94 all(feature = "bevy_reflect", feature = "serde"),
95 reflect(Debug, Default, PartialEq, Serialize, Deserialize)
96 )]
97 pub struct $n {
98 pub m00: $t,
100 pub m01: $t,
102 pub m02: $t,
104 pub m11: $t,
106 pub m12: $t,
108 pub m22: $t,
110 }
111
112 impl $n {
113 pub const ZERO: Self = Self::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
115
116 pub const IDENTITY: Self = Self::new(1.0, 0.0, 0.0, 1.0, 0.0, 1.0);
119
120 pub const NAN: Self = Self::new(
122 $t::NAN,
123 $t::NAN,
124 $t::NAN,
125 $t::NAN,
126 $t::NAN,
127 $t::NAN,
128 );
129
130 #[inline(always)]
135 #[must_use]
136 pub const fn new(
137 m00: $t,
138 m01: $t,
139 m02: $t,
140 m11: $t,
141 m12: $t,
142 m22: $t,
143 ) -> Self {
144 Self {
145 m00,
146 m01,
147 m02,
148 m11,
149 m12,
150 m22,
151 }
152 }
153
154 #[inline(always)]
159 #[must_use]
160 pub const fn from_cols_unchecked(x_axis: $vt, y_axis: $vt, z_axis: $vt) -> Self {
161 Self {
162 m00: x_axis.x,
163 m01: x_axis.y,
164 m02: x_axis.z,
165 m11: y_axis.y,
166 m12: y_axis.z,
167 m22: z_axis.z,
168 }
169 }
170
171 #[inline]
176 #[must_use]
177 pub const fn from_cols_array_unchecked(m: &[$t; 9]) -> Self {
178 Self::new(m[0], m[1], m[2], m[4], m[5], m[8])
179 }
180
181 #[inline]
183 #[must_use]
184 pub const fn to_cols_array(&self) -> [$t; 9] {
185 [
186 self.m00, self.m01, self.m02, self.m01, self.m11, self.m12, self.m02, self.m12,
187 self.m22,
188 ]
189 }
190
191 #[inline]
196 #[must_use]
197 pub const fn from_cols_array_2d_unchecked(m: &[[$t; 3]; 3]) -> Self {
198 Self::from_cols_unchecked(
199 $vt::from_array(m[0]),
200 $vt::from_array(m[1]),
201 $vt::from_array(m[2]),
202 )
203 }
204
205 #[inline]
207 #[must_use]
208 pub const fn to_cols_array_2d(&self) -> [[$t; 3]; 3] {
209 [
210 [self.m00, self.m01, self.m02],
211 [self.m01, self.m11, self.m12],
212 [self.m02, self.m12, self.m22],
213 ]
214 }
215
216 #[inline]
225 #[must_use]
226 pub const fn from_cols_slice(slice: &[$t]) -> Self {
227 Self::new(slice[0], slice[1], slice[2], slice[4], slice[5], slice[8])
228 }
229
230 #[inline]
232 #[must_use]
233 #[doc(alias = "scale")]
234 pub const fn from_diagonal(diagonal: $vt) -> Self {
235 Self::new(diagonal.x, 0.0, 0.0, diagonal.y, 0.0, diagonal.z)
236 }
237
238 #[inline]
244 pub fn try_from_mat3(mat: $nonsymmetricn) -> Result<Self, MatConversionError> {
245 if mat.is_symmetric() {
246 Ok(Self::from_mat3_unchecked(mat))
247 } else {
248 Err(MatConversionError::Asymmetric)
249 }
250 }
251
252 #[inline]
257 #[must_use]
258 pub const fn from_mat3_unchecked(mat: $nonsymmetricn) -> Self {
259 Self::new(
260 mat.x_axis.x,
261 mat.x_axis.y,
262 mat.x_axis.z,
263 mat.y_axis.y,
264 mat.y_axis.z,
265 mat.z_axis.z,
266 )
267 }
268
269 #[inline]
271 #[must_use]
272 pub const fn to_mat3(&self) -> $nonsymmetricn {
273 $nonsymmetricn::from_cols_array(&self.to_cols_array())
274 }
275
276 #[inline(always)]
278 #[must_use]
279 pub fn from_outer_product(v: $vt) -> Self {
280 Self::new(
281 v.x * v.x,
282 v.x * v.y,
283 v.x * v.z,
284 v.y * v.y,
285 v.y * v.z,
286 v.z * v.z,
287 )
288 }
289
290 #[inline]
296 #[must_use]
297 pub const fn col(&self, index: usize) -> $vt {
298 match index {
299 0 => $vt::new(self.m00, self.m01, self.m02),
300 1 => $vt::new(self.m01, self.m11, self.m12),
301 2 => $vt::new(self.m02, self.m12, self.m22),
302 _ => panic!("index out of bounds"),
303 }
304 }
305
306 #[inline]
312 #[must_use]
313 pub const fn row(&self, index: usize) -> $vt {
314 match index {
315 0 => $vt::new(self.m00, self.m01, self.m02),
316 1 => $vt::new(self.m01, self.m11, self.m12),
317 2 => $vt::new(self.m02, self.m12, self.m22),
318 _ => panic!("index out of bounds"),
319 }
320 }
321
322 #[inline]
324 #[must_use]
325 pub fn diagonal(&self) -> $vt {
326 $vt::new(self.m00, self.m11, self.m22)
327 }
328
329 #[inline]
332 #[must_use]
333 pub fn is_finite(&self) -> bool {
334 self.m00.is_finite()
335 && self.m01.is_finite()
336 && self.m02.is_finite()
337 && self.m11.is_finite()
338 && self.m12.is_finite()
339 && self.m22.is_finite()
340 }
341
342 #[inline]
344 #[must_use]
345 pub fn is_nan(&self) -> bool {
346 self.m00.is_nan()
347 || self.m01.is_nan()
348 || self.m02.is_nan()
349 || self.m11.is_nan()
350 || self.m12.is_nan()
351 || self.m22.is_nan()
352 }
353
354 #[inline]
356 #[must_use]
357 pub fn determinant(&self) -> $t {
358 let [a, b, c] = [self.m00, self.m11, self.m22];
364 let [d, e, f] = [self.m01, self.m02, self.m12];
365 a * b * c + 2.0 * d * e * f - a * f * f - b * d * d - c * e * e
366 }
367
368 #[inline]
372 #[must_use]
373 pub fn inverse(&self) -> Self {
374 let m00 = self.m11 * self.m22 - self.m12 * self.m12;
375 let m01 = self.m12 * self.m02 - self.m22 * self.m01;
376 let m02 = self.m01 * self.m12 - self.m02 * self.m11;
377
378 let inverse_determinant = 1.0 / (m00 * self.m00 + m01 * self.m01 + m02 * self.m02);
379
380 let m11 = self.m22 * self.m00 - self.m02 * self.m02;
381 let m12 = self.m02 * self.m01 - self.m00 * self.m12;
382 let m22 = self.m00 * self.m11 - self.m01 * self.m01;
383
384 Self {
385 m00: m00 * inverse_determinant,
386 m01: m01 * inverse_determinant,
387 m02: m02 * inverse_determinant,
388 m11: m11 * inverse_determinant,
389 m12: m12 * inverse_determinant,
390 m22: m22 * inverse_determinant,
391 }
392 }
393
394 #[inline]
396 #[must_use]
397 pub fn inverse_or_zero(&self) -> Self {
398 let m00 = self.m11 * self.m22 - self.m12 * self.m12;
399 let m01 = self.m12 * self.m02 - self.m22 * self.m01;
400 let m02 = self.m01 * self.m12 - self.m02 * self.m11;
401
402 let determinant = m00 * self.m00 + m01 * self.m01 + m02 * self.m02;
403
404 if determinant == 0.0 {
405 return Self::ZERO;
406 }
407
408 let inverse_determinant = 1.0 / determinant;
409
410 let m11 = self.m22 * self.m00 - self.m02 * self.m02;
411 let m12 = self.m02 * self.m01 - self.m00 * self.m12;
412 let m22 = self.m00 * self.m11 - self.m01 * self.m01;
413
414 Self {
415 m00: m00 * inverse_determinant,
416 m01: m01 * inverse_determinant,
417 m02: m02 * inverse_determinant,
418 m11: m11 * inverse_determinant,
419 m12: m12 * inverse_determinant,
420 m22: m22 * inverse_determinant,
421 }
422 }
423
424 #[inline]
426 #[must_use]
427 pub fn abs(&self) -> Self {
428 Self::new(
429 FloatAbs::abs(self.m00),
430 FloatAbs::abs(self.m01),
431 FloatAbs::abs(self.m02),
432 FloatAbs::abs(self.m11),
433 FloatAbs::abs(self.m12),
434 FloatAbs::abs(self.m22),
435 )
436 }
437
438 #[inline]
440 #[must_use]
441 pub fn skew(&self, vec: $vt) -> Self {
442 let xzy = vec.x * self.m12;
445 let yzx = vec.y * self.m02;
446 let zyx = vec.z * self.m01;
447
448 let ixy = vec.y * self.m12 - vec.z * self.m11;
449 let ixz = vec.y * self.m22 - vec.z * self.m12;
450 let iyx = vec.z * self.m00 - vec.x * self.m02;
451 let iyy = zyx - xzy;
452
453 let iyz = vec.z * self.m02 - vec.x * self.m22;
454 let izx = vec.x * self.m01 - vec.y * self.m00;
455 let izy = vec.x * self.m11 - vec.y * self.m01;
456 let izz = xzy - yzx;
457
458 Self::new(
459 vec.y * ixz - vec.z * ixy,
460 vec.y * iyz - vec.z * iyy,
461 vec.y * izz - vec.z * izy,
462 vec.z * iyx - vec.x * iyz,
463 vec.z * izx - vec.x * izz,
464 vec.x * izy - vec.y * izx,
465 )
466 }
467
468 #[inline]
470 #[must_use]
471 pub fn mul_vec3(&self, rhs: $vt) -> $vt {
472 let mut res = self.col(0).mul(rhs.x);
473 res = res.add(self.col(1).mul(rhs.y));
474 res = res.add(self.col(2).mul(rhs.z));
475 res
476 }
477
478 #[inline]
482 #[must_use]
483 pub fn ldlt_solve(&self, rhs: $vt) -> $vt {
484 let d1 = self.m00;
485 let inv_d1 = 1.0 / d1;
486 let l21 = inv_d1 * self.m01;
487 let l31 = inv_d1 * self.m02;
488 let d2 = self.m11 - l21 * l21 * d1;
489 let inv_d2 = 1.0 / d2;
490 let l32 = inv_d2 * (self.m12 - l21 * l31 * d1);
491 let d3 = self.m22 - l31 * l31 * d1 - l32 * l32 * d2;
492 let inv_d3 = 1.0 / d3;
493
494 let y1 = rhs.x;
496 let y2 = rhs.y - l21 * y1;
497 let y3 = rhs.z - l31 * y1 - l32 * y2;
498
499 let z1 = y1 * inv_d1;
501 let z2 = y2 * inv_d2;
502 let z3 = y3 * inv_d3;
503
504 let x3 = z3;
506 let x2 = z2 - l32 * x3;
507 let x1 = z1 - l21 * x2 - l31 * x3;
508
509 $vt::new(x1, x2, x3)
510 }
511
512 #[inline]
514 #[must_use]
515 pub fn mul_mat3(&self, rhs: &$nonsymmetricn) -> $nonsymmetricn {
516 self.mul(rhs)
517 }
518
519 #[inline]
521 #[must_use]
522 pub fn mul_mat32(&self, rhs: &$m32t) -> $m32t {
523 self.mul(rhs)
524 }
525
526 #[inline]
530 #[must_use]
531 pub fn complete_mat23_sandwich(a: &$m23t, b: &$m23t) -> Self {
532 Self::new(
533 a.col(0).dot(b.col(0)),
534 a.col(1).dot(b.col(0)),
535 a.col(2).dot(b.col(0)),
536 a.col(1).dot(b.col(1)),
537 a.col(2).dot(b.col(1)),
538 a.col(2).dot(b.col(2)),
539 )
540 }
541
542 #[inline]
546 #[must_use]
547 pub fn complete_mat32_sandwich(a: &$m32t, b: &$m32t) -> Self {
548 Self::new(
549 a.row(0).dot(b.row(0)),
550 a.row(1).dot(b.row(0)),
551 a.row(2).dot(b.row(0)),
552 a.row(1).dot(b.row(1)),
553 a.row(2).dot(b.row(1)),
554 a.row(2).dot(b.row(2)),
555 )
556 }
557
558 #[inline]
560 #[must_use]
561 pub fn add_mat3(&self, rhs: &$nonsymmetricn) -> $nonsymmetricn {
562 self.add(rhs)
563 }
564
565 #[inline]
567 #[must_use]
568 pub fn sub_mat3(&self, rhs: &$nonsymmetricn) -> $nonsymmetricn {
569 self.sub(rhs)
570 }
571
572 #[inline]
574 #[must_use]
575 pub fn mul_symmetric_mat3(&self, rhs: &Self) -> $nonsymmetricn {
576 self.mul(rhs)
577 }
578
579 #[inline]
581 #[must_use]
582 pub fn add_symmetric_mat3(&self, rhs: &Self) -> Self {
583 self.add(rhs)
584 }
585
586 #[inline]
588 #[must_use]
589 pub fn sub_symmetric_mat3(&self, rhs: &Self) -> Self {
590 self.sub(rhs)
591 }
592
593 #[inline]
595 #[must_use]
596 pub fn mul_scalar(&self, rhs: $t) -> Self {
597 Self::new(
598 self.m00 * rhs,
599 self.m01 * rhs,
600 self.m02 * rhs,
601 self.m11 * rhs,
602 self.m12 * rhs,
603 self.m22 * rhs,
604 )
605 }
606
607 #[inline]
609 #[must_use]
610 pub fn div_scalar(&self, rhs: $t) -> Self {
611 Self::new(
612 self.m00 / rhs,
613 self.m01 / rhs,
614 self.m02 / rhs,
615 self.m11 / rhs,
616 self.m12 / rhs,
617 self.m22 / rhs,
618 )
619 }
620 }
621
622 impl Default for $n {
623 #[inline(always)]
624 fn default() -> Self {
625 Self::IDENTITY
626 }
627 }
628
629 impl TryFrom<$nonsymmetricn> for $n {
630 type Error = MatConversionError;
631
632 #[inline]
633 fn try_from(mat: $nonsymmetricn) -> Result<Self, Self::Error> {
634 Self::try_from_mat3(mat)
635 }
636 }
637
638 impl Add for $n {
639 type Output = Self;
640 #[inline]
641 fn add(self, rhs: Self) -> Self::Output {
642 Self::new(
643 self.m00 + rhs.m00,
644 self.m01 + rhs.m01,
645 self.m02 + rhs.m02,
646 self.m11 + rhs.m11,
647 self.m12 + rhs.m12,
648 self.m22 + rhs.m22,
649 )
650 }
651 }
652
653 impl Add<&Self> for $n {
654 type Output = Self;
655 #[inline]
656 fn add(self, rhs: &Self) -> Self::Output {
657 self.add(*rhs)
658 }
659 }
660
661 impl Add<Self> for &$n {
662 type Output = $n;
663 #[inline]
664 fn add(self, rhs: Self) -> Self::Output {
665 (*self).add(rhs)
666 }
667 }
668
669 impl Add<&Self> for &$n {
670 type Output = $n;
671 #[inline]
672 fn add(self, rhs: &Self) -> Self::Output {
673 (*self).add(*rhs)
674 }
675 }
676
677 impl AddAssign for $n {
678 #[inline]
679 fn add_assign(&mut self, rhs: Self) {
680 *self = self.add(rhs);
681 }
682 }
683
684 impl AddAssign<&Self> for $n {
685 #[inline]
686 fn add_assign(&mut self, rhs: &Self) {
687 self.add_assign(*rhs);
688 }
689 }
690
691 impl Add<$nonsymmetricn> for $n {
692 type Output = $nonsymmetricn;
693 #[inline]
694 fn add(self, rhs: $nonsymmetricn) -> Self::Output {
695 $nonsymmetricn::from_cols(
696 self.col(0).add(rhs.x_axis),
697 self.col(1).add(rhs.y_axis),
698 self.col(2).add(rhs.z_axis),
699 )
700 }
701 }
702
703 impl Add<&$nonsymmetricn> for $n {
704 type Output = $nonsymmetricn;
705 #[inline]
706 fn add(self, rhs: &$nonsymmetricn) -> Self::Output {
707 self.add(*rhs)
708 }
709 }
710
711 impl Add<$nonsymmetricn> for &$n {
712 type Output = $nonsymmetricn;
713 #[inline]
714 fn add(self, rhs: $nonsymmetricn) -> Self::Output {
715 (*self).add(rhs)
716 }
717 }
718
719 impl Add<&$nonsymmetricn> for &$n {
720 type Output = $nonsymmetricn;
721 #[inline]
722 fn add(self, rhs: &$nonsymmetricn) -> Self::Output {
723 (*self).add(*rhs)
724 }
725 }
726
727 impl Add<$n> for $nonsymmetricn {
728 type Output = $nonsymmetricn;
729 #[inline]
730 fn add(self, rhs: $n) -> Self::Output {
731 rhs.add(&self)
732 }
733 }
734
735 impl Add<&$n> for $nonsymmetricn {
736 type Output = $nonsymmetricn;
737 #[inline]
738 fn add(self, rhs: &$n) -> Self::Output {
739 self.add(*rhs)
740 }
741 }
742
743 impl Add<&$n> for &$nonsymmetricn {
744 type Output = $nonsymmetricn;
745 #[inline]
746 fn add(self, rhs: &$n) -> Self::Output {
747 (*self).add(*rhs)
748 }
749 }
750
751 impl AddAssign<$n> for $nonsymmetricn {
752 #[inline]
753 fn add_assign(&mut self, rhs: $n) {
754 *self = self.add(rhs);
755 }
756 }
757
758 impl AddAssign<&$n> for $nonsymmetricn {
759 #[inline]
760 fn add_assign(&mut self, rhs: &$n) {
761 *self = self.add(*rhs);
762 }
763 }
764
765 impl Sub for $n {
766 type Output = Self;
767 #[inline]
768 fn sub(self, rhs: Self) -> Self::Output {
769 Self::new(
770 self.m00 - rhs.m00,
771 self.m01 - rhs.m01,
772 self.m02 - rhs.m02,
773 self.m11 - rhs.m11,
774 self.m12 - rhs.m12,
775 self.m22 - rhs.m22,
776 )
777 }
778 }
779
780 impl Sub<&Self> for $n {
781 type Output = Self;
782 #[inline]
783 fn sub(self, rhs: &Self) -> Self::Output {
784 self.sub(*rhs)
785 }
786 }
787
788 impl Sub<Self> for &$n {
789 type Output = $n;
790 #[inline]
791 fn sub(self, rhs: Self) -> Self::Output {
792 (*self).sub(rhs)
793 }
794 }
795
796 impl Sub<&Self> for &$n {
797 type Output = $n;
798 #[inline]
799 fn sub(self, rhs: &Self) -> Self::Output {
800 (*self).sub(*rhs)
801 }
802 }
803
804 impl SubAssign for $n {
805 #[inline]
806 fn sub_assign(&mut self, rhs: Self) {
807 *self = self.sub(rhs);
808 }
809 }
810
811 impl SubAssign<&Self> for $n {
812 #[inline]
813 fn sub_assign(&mut self, rhs: &Self) {
814 self.sub_assign(*rhs);
815 }
816 }
817
818 impl Sub<$nonsymmetricn> for $n {
819 type Output = $nonsymmetricn;
820 #[inline]
821 fn sub(self, rhs: $nonsymmetricn) -> Self::Output {
822 $nonsymmetricn::from_cols(
823 self.col(0).sub(rhs.x_axis),
824 self.col(1).sub(rhs.y_axis),
825 self.col(2).sub(rhs.z_axis),
826 )
827 }
828 }
829
830 impl Sub<&$nonsymmetricn> for $n {
831 type Output = $nonsymmetricn;
832 #[inline]
833 fn sub(self, rhs: &$nonsymmetricn) -> Self::Output {
834 self.sub(*rhs)
835 }
836 }
837
838 impl Sub<$nonsymmetricn> for &$n {
839 type Output = $nonsymmetricn;
840 #[inline]
841 fn sub(self, rhs: $nonsymmetricn) -> Self::Output {
842 (*self).sub(rhs)
843 }
844 }
845
846 impl Sub<&$nonsymmetricn> for &$n {
847 type Output = $nonsymmetricn;
848 #[inline]
849 fn sub(self, rhs: &$nonsymmetricn) -> Self::Output {
850 (*self).sub(*rhs)
851 }
852 }
853
854 impl Sub<$n> for $nonsymmetricn {
855 type Output = $nonsymmetricn;
856 #[inline]
857 fn sub(self, rhs: $n) -> Self::Output {
858 rhs.sub(&self)
859 }
860 }
861
862 impl Sub<&$n> for $nonsymmetricn {
863 type Output = $nonsymmetricn;
864 #[inline]
865 fn sub(self, rhs: &$n) -> Self::Output {
866 self.sub(*rhs)
867 }
868 }
869
870 impl Sub<&$n> for &$nonsymmetricn {
871 type Output = $nonsymmetricn;
872 #[inline]
873 fn sub(self, rhs: &$n) -> Self::Output {
874 (*self).sub(*rhs)
875 }
876 }
877
878 impl SubAssign<$n> for $nonsymmetricn {
879 #[inline]
880 fn sub_assign(&mut self, rhs: $n) {
881 *self = self.sub(rhs);
882 }
883 }
884
885 impl SubAssign<&$n> for $nonsymmetricn {
886 #[inline]
887 fn sub_assign(&mut self, rhs: &$n) {
888 *self = self.sub(*rhs);
889 }
890 }
891
892 impl Neg for $n {
893 type Output = Self;
894 #[inline]
895 fn neg(self) -> Self::Output {
896 Self::new(
897 -self.m00,
898 -self.m01,
899 -self.m02,
900 -self.m11,
901 -self.m12,
902 -self.m22,
903 )
904 }
905 }
906
907 impl Neg for &$n {
908 type Output = $n;
909 #[inline]
910 fn neg(self) -> Self::Output {
911 (*self).neg()
912 }
913 }
914
915 impl Mul for $n {
916 type Output = $nonsymmetricn;
917 #[inline]
918 fn mul(self, rhs: Self) -> Self::Output {
919 $nonsymmetricn::from_cols(
920 self.mul(rhs.col(0)),
921 self.mul(rhs.col(1)),
922 self.mul(rhs.col(2)),
923 )
924 }
925 }
926
927 impl Mul<&Self> for $n {
928 type Output = $nonsymmetricn;
929 #[inline]
930 fn mul(self, rhs: &Self) -> Self::Output {
931 self.mul(*rhs)
932 }
933 }
934
935 impl Mul<Self> for &$n {
936 type Output = $nonsymmetricn;
937 #[inline]
938 fn mul(self, rhs: Self) -> Self::Output {
939 (*self).mul(rhs)
940 }
941 }
942
943 impl Mul<&Self> for &$n {
944 type Output = $nonsymmetricn;
945 #[inline]
946 fn mul(self, rhs: &Self) -> Self::Output {
947 (*self).mul(*rhs)
948 }
949 }
950
951 impl Mul<$n> for $nonsymmetricn {
952 type Output = Self;
953 #[inline]
954 fn mul(self, rhs: $n) -> Self::Output {
955 Self::from_cols_array_2d(&[
956 [
957 self.x_axis.x * rhs.m00 + self.y_axis.x * rhs.m01 + self.z_axis.x * rhs.m02,
958 self.x_axis.y * rhs.m00 + self.y_axis.y * rhs.m01 + self.z_axis.y * rhs.m02,
959 self.x_axis.z * rhs.m00 + self.y_axis.z * rhs.m01 + self.z_axis.z * rhs.m02,
960 ],
961 [
962 self.x_axis.x * rhs.m01 + self.y_axis.x * rhs.m11 + self.z_axis.x * rhs.m12,
963 self.x_axis.y * rhs.m01 + self.y_axis.y * rhs.m11 + self.z_axis.y * rhs.m12,
964 self.x_axis.z * rhs.m01 + self.y_axis.z * rhs.m11 + self.z_axis.z * rhs.m12,
965 ],
966 [
967 self.x_axis.x * rhs.m02 + self.y_axis.x * rhs.m12 + self.z_axis.x * rhs.m22,
968 self.x_axis.y * rhs.m02 + self.y_axis.y * rhs.m12 + self.z_axis.y * rhs.m22,
969 self.x_axis.z * rhs.m02 + self.y_axis.z * rhs.m12 + self.z_axis.z * rhs.m22,
970 ],
971 ])
972 }
973 }
974
975 impl Mul<&$n> for $nonsymmetricn {
976 type Output = Self;
977 #[inline]
978 fn mul(self, rhs: &$n) -> Self::Output {
979 self.mul(*rhs)
980 }
981 }
982
983 impl Mul<$n> for &$nonsymmetricn {
984 type Output = $nonsymmetricn;
985 #[inline]
986 fn mul(self, rhs: $n) -> Self::Output {
987 (*self).mul(rhs)
988 }
989 }
990
991 impl Mul<&$n> for &$nonsymmetricn {
992 type Output = $nonsymmetricn;
993 #[inline]
994 fn mul(self, rhs: &$n) -> Self::Output {
995 (*self).mul(*rhs)
996 }
997 }
998
999 impl MulAssign<$n> for $nonsymmetricn {
1000 #[inline]
1001 fn mul_assign(&mut self, rhs: $n) {
1002 *self = self.mul(rhs);
1003 }
1004 }
1005
1006 impl MulAssign<&$n> for $nonsymmetricn {
1007 #[inline]
1008 fn mul_assign(&mut self, rhs: &$n) {
1009 *self = self.mul(*rhs);
1010 }
1011 }
1012
1013 impl Mul<$nonsymmetricn> for $n {
1014 type Output = $nonsymmetricn;
1015 #[inline]
1016 fn mul(self, rhs: $nonsymmetricn) -> Self::Output {
1017 $nonsymmetricn::from_cols(
1018 self.mul(rhs.x_axis),
1019 self.mul(rhs.y_axis),
1020 self.mul(rhs.z_axis),
1021 )
1022 }
1023 }
1024
1025 impl Mul<&$nonsymmetricn> for $n {
1026 type Output = $nonsymmetricn;
1027 #[inline]
1028 fn mul(self, rhs: &$nonsymmetricn) -> Self::Output {
1029 self.mul(*rhs)
1030 }
1031 }
1032
1033 impl Mul<$nonsymmetricn> for &$n {
1034 type Output = $nonsymmetricn;
1035 #[inline]
1036 fn mul(self, rhs: $nonsymmetricn) -> Self::Output {
1037 (*self).mul(rhs)
1038 }
1039 }
1040
1041 impl Mul<&$nonsymmetricn> for &$n {
1042 type Output = $nonsymmetricn;
1043 #[inline]
1044 fn mul(self, rhs: &$nonsymmetricn) -> Self::Output {
1045 (*self).mul(*rhs)
1046 }
1047 }
1048
1049 impl Mul<$m32t> for $n {
1050 type Output = $m32t;
1051 #[inline]
1052 fn mul(self, rhs: $m32t) -> Self::Output {
1053 $m32t::from_cols(
1054 $vt::new(
1055 self.row(0).dot(rhs.x_axis),
1056 self.row(1).dot(rhs.x_axis),
1057 self.row(2).dot(rhs.x_axis),
1058 ),
1059 $vt::new(
1060 self.row(0).dot(rhs.y_axis),
1061 self.row(1).dot(rhs.y_axis),
1062 self.row(2).dot(rhs.y_axis),
1063 ),
1064 )
1065 }
1066 }
1067
1068 impl Mul<&$m32t> for $n {
1069 type Output = $m32t;
1070 #[inline]
1071 fn mul(self, rhs: &$m32t) -> Self::Output {
1072 self.mul(*rhs)
1073 }
1074 }
1075
1076 impl Mul<$m32t> for &$n {
1077 type Output = $m32t;
1078 #[inline]
1079 fn mul(self, rhs: $m32t) -> Self::Output {
1080 (*self).mul(rhs)
1081 }
1082 }
1083
1084 impl Mul<&$m32t> for &$n {
1085 type Output = $m32t;
1086 #[inline]
1087 fn mul(self, rhs: &$m32t) -> Self::Output {
1088 (*self).mul(*rhs)
1089 }
1090 }
1091
1092 impl Mul<$vt> for $n {
1093 type Output = $vt;
1094 #[inline]
1095 fn mul(self, rhs: $vt) -> Self::Output {
1096 self.mul_vec3(rhs)
1097 }
1098 }
1099
1100 impl Mul<&$vt> for $n {
1101 type Output = $vt;
1102 #[inline]
1103 fn mul(self, rhs: &$vt) -> Self::Output {
1104 self.mul(*rhs)
1105 }
1106 }
1107
1108 impl Mul<$vt> for &$n {
1109 type Output = $vt;
1110 #[inline]
1111 fn mul(self, rhs: $vt) -> Self::Output {
1112 (*self).mul(rhs)
1113 }
1114 }
1115
1116 impl Mul<&$vt> for &$n {
1117 type Output = $vt;
1118 #[inline]
1119 fn mul(self, rhs: &$vt) -> Self::Output {
1120 (*self).mul(*rhs)
1121 }
1122 }
1123
1124 impl Mul<$n> for $t {
1125 type Output = $n;
1126 #[inline]
1127 fn mul(self, rhs: $n) -> Self::Output {
1128 rhs.mul_scalar(self)
1129 }
1130 }
1131
1132 impl Mul<&$n> for $t {
1133 type Output = $n;
1134 #[inline]
1135 fn mul(self, rhs: &$n) -> Self::Output {
1136 self.mul(*rhs)
1137 }
1138 }
1139
1140 impl Mul<$n> for &$t {
1141 type Output = $n;
1142 #[inline]
1143 fn mul(self, rhs: $n) -> Self::Output {
1144 (*self).mul(rhs)
1145 }
1146 }
1147
1148 impl Mul<&$n> for &$t {
1149 type Output = $n;
1150 #[inline]
1151 fn mul(self, rhs: &$n) -> Self::Output {
1152 (*self).mul(*rhs)
1153 }
1154 }
1155
1156 impl Mul<$t> for $n {
1157 type Output = Self;
1158 #[inline]
1159 fn mul(self, rhs: $t) -> Self::Output {
1160 self.mul_scalar(rhs)
1161 }
1162 }
1163
1164 impl Mul<&$t> for $n {
1165 type Output = Self;
1166 #[inline]
1167 fn mul(self, rhs: &$t) -> Self::Output {
1168 self.mul(*rhs)
1169 }
1170 }
1171
1172 impl Mul<$t> for &$n {
1173 type Output = $n;
1174 #[inline]
1175 fn mul(self, rhs: $t) -> Self::Output {
1176 (*self).mul(rhs)
1177 }
1178 }
1179
1180 impl Mul<&$t> for &$n {
1181 type Output = $n;
1182 #[inline]
1183 fn mul(self, rhs: &$t) -> Self::Output {
1184 (*self).mul(*rhs)
1185 }
1186 }
1187
1188 impl MulAssign<$t> for $n {
1189 #[inline]
1190 fn mul_assign(&mut self, rhs: $t) {
1191 *self = self.mul(rhs);
1192 }
1193 }
1194
1195 impl MulAssign<&$t> for $n {
1196 #[inline]
1197 fn mul_assign(&mut self, rhs: &$t) {
1198 self.mul_assign(*rhs);
1199 }
1200 }
1201
1202 impl Div<$n> for $t {
1203 type Output = $n;
1204 #[inline]
1205 fn div(self, rhs: $n) -> Self::Output {
1206 rhs.div_scalar(self)
1207 }
1208 }
1209
1210 impl Div<&$n> for $t {
1211 type Output = $n;
1212 #[inline]
1213 fn div(self, rhs: &$n) -> Self::Output {
1214 self.div(*rhs)
1215 }
1216 }
1217
1218 impl Div<$n> for &$t {
1219 type Output = $n;
1220 #[inline]
1221 fn div(self, rhs: $n) -> Self::Output {
1222 (*self).div(rhs)
1223 }
1224 }
1225
1226 impl Div<&$n> for &$t {
1227 type Output = $n;
1228 #[inline]
1229 fn div(self, rhs: &$n) -> Self::Output {
1230 (*self).div(*rhs)
1231 }
1232 }
1233
1234 impl Div<$t> for $n {
1235 type Output = Self;
1236 #[inline]
1237 fn div(self, rhs: $t) -> Self::Output {
1238 self.div_scalar(rhs)
1239 }
1240 }
1241
1242 impl Div<&$t> for $n {
1243 type Output = Self;
1244 #[inline]
1245 fn div(self, rhs: &$t) -> Self::Output {
1246 self.div(*rhs)
1247 }
1248 }
1249
1250 impl Div<$t> for &$n {
1251 type Output = $n;
1252 #[inline]
1253 fn div(self, rhs: $t) -> Self::Output {
1254 (*self).div(rhs)
1255 }
1256 }
1257
1258 impl Div<&$t> for &$n {
1259 type Output = $n;
1260 #[inline]
1261 fn div(self, rhs: &$t) -> Self::Output {
1262 (*self).div(*rhs)
1263 }
1264 }
1265
1266 impl DivAssign<$t> for $n {
1267 #[inline]
1268 fn div_assign(&mut self, rhs: $t) {
1269 *self = self.div(rhs);
1270 }
1271 }
1272
1273 impl DivAssign<&$t> for $n {
1274 #[inline]
1275 fn div_assign(&mut self, rhs: &$t) {
1276 self.div_assign(*rhs);
1277 }
1278 }
1279
1280 impl From<$n> for $nonsymmetricn {
1281 #[inline]
1282 fn from(mat: $n) -> Self {
1283 mat.to_mat3()
1284 }
1285 }
1286
1287 impl Sum<$n> for $n {
1288 fn sum<I: Iterator<Item = $n>>(iter: I) -> Self {
1289 iter.fold(Self::ZERO, Self::add)
1290 }
1291 }
1292
1293 impl<'a> Sum<&'a $n> for $n {
1294 fn sum<I: Iterator<Item = &'a $n>>(iter: I) -> Self {
1295 iter.fold(Self::ZERO, |a, &b| a.add(b))
1296 }
1297 }
1298
1299 #[cfg(feature = "approx")]
1300 impl approx::AbsDiffEq for $n {
1301 type Epsilon = $t;
1302
1303 #[inline]
1304 fn default_epsilon() -> Self::Epsilon {
1305 $t::default_epsilon()
1306 }
1307
1308 #[inline]
1309 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
1310 self.m00.abs_diff_eq(&other.m00, epsilon)
1311 && self.m01.abs_diff_eq(&other.m01, epsilon)
1312 && self.m02.abs_diff_eq(&other.m02, epsilon)
1313 && self.m11.abs_diff_eq(&other.m11, epsilon)
1314 && self.m12.abs_diff_eq(&other.m12, epsilon)
1315 && self.m22.abs_diff_eq(&other.m22, epsilon)
1316 }
1317 }
1318
1319 #[cfg(feature = "approx")]
1320 impl approx::RelativeEq for $n {
1321 #[inline]
1322 fn default_max_relative() -> Self::Epsilon {
1323 $t::default_max_relative()
1324 }
1325
1326 #[inline]
1327 fn relative_eq(
1328 &self,
1329 other: &Self,
1330 epsilon: Self::Epsilon,
1331 max_relative: Self::Epsilon,
1332 ) -> bool {
1333 self.m00.relative_eq(&other.m00, epsilon, max_relative)
1334 && self.m01.relative_eq(&other.m01, epsilon, max_relative)
1335 && self.m02.relative_eq(&other.m02, epsilon, max_relative)
1336 && self.m11.relative_eq(&other.m11, epsilon, max_relative)
1337 && self.m12.relative_eq(&other.m12, epsilon, max_relative)
1338 && self.m22.relative_eq(&other.m22, epsilon, max_relative)
1339 }
1340 }
1341
1342 #[cfg(feature = "approx")]
1343 impl approx::UlpsEq for $n {
1344 #[inline]
1345 fn default_max_ulps() -> u32 {
1346 $t::default_max_ulps()
1347 }
1348
1349 #[inline]
1350 fn ulps_eq(
1351 &self,
1352 other: &Self,
1353 epsilon: Self::Epsilon,
1354 max_ulps: u32,
1355 ) -> bool {
1356 self.m00.ulps_eq(&other.m00, epsilon, max_ulps)
1357 && self.m01.ulps_eq(&other.m01, epsilon, max_ulps)
1358 && self.m02.ulps_eq(&other.m02, epsilon, max_ulps)
1359 && self.m11.ulps_eq(&other.m11, epsilon, max_ulps)
1360 && self.m12.ulps_eq(&other.m12, epsilon, max_ulps)
1361 && self.m22.ulps_eq(&other.m22, epsilon, max_ulps)
1362 }
1363 }
1364
1365 impl core::fmt::Debug for $n {
1366 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1367 f.debug_struct(stringify!($n))
1368 .field("m00", &self.m00)
1369 .field("m01", &self.m01)
1370 .field("m02", &self.m02)
1371 .field("m11", &self.m11)
1372 .field("m12", &self.m12)
1373 .field("m22", &self.m22)
1374 .finish()
1375 }
1376 }
1377
1378 impl core::fmt::Display for $n {
1379 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1380 if let Some(p) = f.precision() {
1381 write!(
1382 f,
1383 "[[{:.*}, {:.*}, {:.*}], [{:.*}, {:.*}, {:.*}], [{:.*}, {:.*}, {:.*}]]",
1384 p, self.m00, p, self.m01, p, self.m02,
1385 p, self.m01, p, self.m11, p, self.m12,
1386 p, self.m02, p, self.m12, p, self.m22,
1387 )
1388 } else {
1389 write!(
1390 f,
1391 "[[{}, {}, {}], [{}, {}, {}], [{}, {}, {}]]",
1392 self.m00, self.m01, self.m02,
1393 self.m01, self.m11, self.m12,
1394 self.m02, self.m12, self.m22,
1395 )
1396 }
1397 }
1398 }
1399 )+
1400 }
1401}
1402
1403#[cfg(feature = "f32")]
1404impl SymmetricMat3 {
1405 #[inline]
1407 #[must_use]
1408 pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
1409 self.mul_vec3(rhs.into()).into()
1410 }
1411}
1412
1413#[cfg(feature = "f32")]
1414impl Mul<Vec3A> for SymmetricMat3 {
1415 type Output = Vec3A;
1416 #[inline]
1417 fn mul(self, rhs: Vec3A) -> Self::Output {
1418 self.mul_vec3a(rhs)
1419 }
1420}
1421
1422#[cfg(feature = "f32")]
1423symmetric_mat3s!(SymmetricMat3 => Mat3, Mat23, Mat32, Vec2, Vec3, f32);
1424
1425#[cfg(feature = "f64")]
1426symmetric_mat3s!(SymmetricDMat3 => DMat3, DMat23, DMat32, DVec2, DVec3, f64);
1427
1428#[cfg(all(feature = "f32", feature = "f64"))]
1429impl SymmetricMat3 {
1430 #[inline]
1432 #[must_use]
1433 pub fn as_symmetric_dmat3(&self) -> SymmetricDMat3 {
1434 SymmetricDMat3 {
1435 m00: self.m00 as f64,
1436 m01: self.m01 as f64,
1437 m02: self.m02 as f64,
1438 m11: self.m11 as f64,
1439 m12: self.m12 as f64,
1440 m22: self.m22 as f64,
1441 }
1442 }
1443}
1444
1445#[cfg(all(feature = "f32", feature = "f64"))]
1446impl SymmetricDMat3 {
1447 #[inline]
1449 #[must_use]
1450 pub fn as_symmetric_mat3(&self) -> SymmetricMat3 {
1451 SymmetricMat3 {
1452 m00: self.m00 as f32,
1453 m01: self.m01 as f32,
1454 m02: self.m02 as f32,
1455 m11: self.m11 as f32,
1456 m12: self.m12 as f32,
1457 m22: self.m22 as f32,
1458 }
1459 }
1460}
1461
1462#[cfg(test)]
1463mod tests {
1464 use approx::assert_relative_eq;
1465 use glam::Vec3;
1466
1467 use crate::SymmetricMat3;
1468
1469 #[test]
1470 fn ldlt_solve() {
1471 let mat = SymmetricMat3::new(4.0, 1.0, 5.0, 0.0, 2.0, 6.0);
1472
1473 let x = Vec3::new(1.0, 2.0, 3.0);
1475
1476 let rhs = mat.mul_vec3(x);
1478 assert_eq!(rhs, Vec3::new(21.0, 7.0, 27.0));
1479
1480 let sol = mat.ldlt_solve(rhs);
1482
1483 assert_relative_eq!(sol, x, epsilon = 1e-4);
1485 }
1486
1487 #[test]
1488 fn ldlt_solve_identity() {
1489 let mat = SymmetricMat3::IDENTITY;
1490
1491 let x = Vec3::new(7.0, -3.0, 2.5);
1493
1494 let rhs = mat.mul_vec3(x);
1496
1497 let sol = mat.ldlt_solve(rhs);
1499
1500 assert_relative_eq!(sol, x, epsilon = 1e-6);
1502 }
1503}