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