1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[doc(inline)]
7pub use matrix2::Matrix2;
8#[doc(inline)]
9pub use matrix3::Matrix3;
10#[doc(inline)]
11pub use matrix4::Matrix4;
12
13pub mod matrix2 {
15 use core::num::FpCategory;
16 use core::ops::{Add, Div, Mul, Neg, Sub};
17
18 use use_vector::Vector2;
19
20 #[inline]
21 fn dot2(a0: f64, b0: f64, a1: f64, b1: f64) -> f64 {
22 a0.mul_add(b0, a1 * b1)
23 }
24
25 #[derive(Debug, Clone, Copy, PartialEq)]
41 pub struct Matrix2 {
42 pub m00: f64,
43 pub m01: f64,
44 pub m10: f64,
45 pub m11: f64,
46 }
47
48 impl Matrix2 {
49 pub const ZERO: Self = Self::new(0.0, 0.0, 0.0, 0.0);
51
52 pub const IDENTITY: Self = Self::new(1.0, 0.0, 0.0, 1.0);
68
69 #[must_use]
71 #[allow(clippy::similar_names, clippy::too_many_arguments)]
72 pub const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
73 Self { m00, m01, m10, m11 }
74 }
75
76 #[must_use]
78 pub const fn from_rows(rows: [[f64; 2]; 2]) -> Self {
79 Self::new(rows[0][0], rows[0][1], rows[1][0], rows[1][1])
80 }
81
82 #[must_use]
84 pub const fn from_cols(cols: [[f64; 2]; 2]) -> Self {
85 Self::new(cols[0][0], cols[1][0], cols[0][1], cols[1][1])
86 }
87
88 #[must_use]
90 pub const fn transpose(self) -> Self {
91 Self::new(self.m00, self.m10, self.m01, self.m11)
92 }
93
94 #[must_use]
96 pub const fn determinant(self) -> f64 {
97 (self.m00 * self.m11) - (self.m01 * self.m10)
98 }
99
100 #[must_use]
102 pub const fn trace(self) -> f64 {
103 self.m00 + self.m11
104 }
105
106 #[must_use]
127 pub fn inverse(self) -> Option<Self> {
128 let determinant = self.determinant();
129
130 if !determinant.is_finite() || matches!(determinant.classify(), FpCategory::Zero) {
131 return None;
132 }
133
134 Some(Self::new(
135 self.m11 / determinant,
136 -self.m01 / determinant,
137 -self.m10 / determinant,
138 self.m00 / determinant,
139 ))
140 }
141 }
142
143 impl Add for Matrix2 {
144 type Output = Self;
145
146 fn add(self, rhs: Self) -> Self::Output {
147 Self::new(
148 self.m00 + rhs.m00,
149 self.m01 + rhs.m01,
150 self.m10 + rhs.m10,
151 self.m11 + rhs.m11,
152 )
153 }
154 }
155
156 impl Sub for Matrix2 {
157 type Output = Self;
158
159 fn sub(self, rhs: Self) -> Self::Output {
160 Self::new(
161 self.m00 - rhs.m00,
162 self.m01 - rhs.m01,
163 self.m10 - rhs.m10,
164 self.m11 - rhs.m11,
165 )
166 }
167 }
168
169 impl Mul<f64> for Matrix2 {
170 type Output = Self;
171
172 fn mul(self, rhs: f64) -> Self::Output {
173 Self::new(
174 self.m00 * rhs,
175 self.m01 * rhs,
176 self.m10 * rhs,
177 self.m11 * rhs,
178 )
179 }
180 }
181
182 impl Div<f64> for Matrix2 {
183 type Output = Self;
184
185 fn div(self, rhs: f64) -> Self::Output {
186 Self::new(
187 self.m00 / rhs,
188 self.m01 / rhs,
189 self.m10 / rhs,
190 self.m11 / rhs,
191 )
192 }
193 }
194
195 impl Neg for Matrix2 {
196 type Output = Self;
197
198 fn neg(self) -> Self::Output {
199 Self::new(-self.m00, -self.m01, -self.m10, -self.m11)
200 }
201 }
202
203 impl Mul for Matrix2 {
204 type Output = Self;
205
206 fn mul(self, rhs: Self) -> Self::Output {
207 Self::new(
208 dot2(self.m00, rhs.m00, self.m01, rhs.m10),
209 dot2(self.m00, rhs.m01, self.m01, rhs.m11),
210 dot2(self.m10, rhs.m00, self.m11, rhs.m10),
211 dot2(self.m10, rhs.m01, self.m11, rhs.m11),
212 )
213 }
214 }
215
216 impl Mul<Vector2> for Matrix2 {
217 type Output = Vector2;
218
219 fn mul(self, rhs: Vector2) -> Self::Output {
220 let x_component = rhs.x();
221 let y_component = rhs.y();
222
223 Vector2::new(
224 dot2(self.m00, x_component, self.m01, y_component),
225 dot2(self.m10, x_component, self.m11, y_component),
226 )
227 }
228 }
229}
230
231pub mod matrix3 {
233 use core::num::FpCategory;
234 use core::ops::{Add, Div, Mul, Neg, Sub};
235
236 use use_vector::Vector3;
237
238 #[inline]
239 fn dot3(a0: f64, b0: f64, a1: f64, b1: f64, a2: f64, b2: f64) -> f64 {
240 a0.mul_add(b0, a1.mul_add(b1, a2 * b2))
241 }
242
243 #[inline]
244 fn mul_sub(a: f64, b: f64, c: f64, d: f64) -> f64 {
245 a.mul_add(b, -(c * d))
246 }
247
248 #[derive(Debug, Clone, Copy, PartialEq)]
264 pub struct Matrix3 {
265 pub m00: f64,
266 pub m01: f64,
267 pub m02: f64,
268 pub m10: f64,
269 pub m11: f64,
270 pub m12: f64,
271 pub m20: f64,
272 pub m21: f64,
273 pub m22: f64,
274 }
275
276 impl Matrix3 {
277 pub const ZERO: Self = Self::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
279
280 pub const IDENTITY: Self = Self::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
296
297 #[must_use]
299 #[allow(clippy::similar_names, clippy::too_many_arguments)]
300 pub const fn new(
301 m00: f64,
302 m01: f64,
303 m02: f64,
304 m10: f64,
305 m11: f64,
306 m12: f64,
307 m20: f64,
308 m21: f64,
309 m22: f64,
310 ) -> Self {
311 Self {
312 m00,
313 m01,
314 m02,
315 m10,
316 m11,
317 m12,
318 m20,
319 m21,
320 m22,
321 }
322 }
323
324 #[must_use]
326 pub const fn from_rows(rows: [[f64; 3]; 3]) -> Self {
327 Self::new(
328 rows[0][0], rows[0][1], rows[0][2], rows[1][0], rows[1][1], rows[1][2], rows[2][0],
329 rows[2][1], rows[2][2],
330 )
331 }
332
333 #[must_use]
335 pub const fn from_cols(cols: [[f64; 3]; 3]) -> Self {
336 Self::new(
337 cols[0][0], cols[1][0], cols[2][0], cols[0][1], cols[1][1], cols[2][1], cols[0][2],
338 cols[1][2], cols[2][2],
339 )
340 }
341
342 #[must_use]
344 pub const fn transpose(self) -> Self {
345 Self::new(
346 self.m00, self.m10, self.m20, self.m01, self.m11, self.m21, self.m02, self.m12,
347 self.m22,
348 )
349 }
350
351 #[must_use]
353 pub const fn determinant(self) -> f64 {
354 self.m00 * ((self.m11 * self.m22) - (self.m12 * self.m21))
355 - self.m01 * ((self.m10 * self.m22) - (self.m12 * self.m20))
356 + self.m02 * ((self.m10 * self.m21) - (self.m11 * self.m20))
357 }
358
359 #[must_use]
361 pub const fn trace(self) -> f64 {
362 self.m00 + self.m11 + self.m22
363 }
364
365 #[must_use]
386 pub fn inverse(self) -> Option<Self> {
387 let determinant = self.determinant();
388
389 if !determinant.is_finite() || matches!(determinant.classify(), FpCategory::Zero) {
390 return None;
391 }
392
393 let c00 = mul_sub(self.m11, self.m22, self.m12, self.m21);
394 let c01 = mul_sub(self.m12, self.m20, self.m10, self.m22);
395 let c02 = mul_sub(self.m10, self.m21, self.m11, self.m20);
396 let c10 = mul_sub(self.m02, self.m21, self.m01, self.m22);
397 let c11 = mul_sub(self.m00, self.m22, self.m02, self.m20);
398 let c12 = mul_sub(self.m01, self.m20, self.m00, self.m21);
399 let c20 = mul_sub(self.m01, self.m12, self.m02, self.m11);
400 let c21 = mul_sub(self.m02, self.m10, self.m00, self.m12);
401 let c22 = mul_sub(self.m00, self.m11, self.m01, self.m10);
402
403 Some(Self::new(c00, c10, c20, c01, c11, c21, c02, c12, c22) / determinant)
404 }
405 }
406
407 impl Add for Matrix3 {
408 type Output = Self;
409
410 fn add(self, rhs: Self) -> Self::Output {
411 Self::new(
412 self.m00 + rhs.m00,
413 self.m01 + rhs.m01,
414 self.m02 + rhs.m02,
415 self.m10 + rhs.m10,
416 self.m11 + rhs.m11,
417 self.m12 + rhs.m12,
418 self.m20 + rhs.m20,
419 self.m21 + rhs.m21,
420 self.m22 + rhs.m22,
421 )
422 }
423 }
424
425 impl Sub for Matrix3 {
426 type Output = Self;
427
428 fn sub(self, rhs: Self) -> Self::Output {
429 Self::new(
430 self.m00 - rhs.m00,
431 self.m01 - rhs.m01,
432 self.m02 - rhs.m02,
433 self.m10 - rhs.m10,
434 self.m11 - rhs.m11,
435 self.m12 - rhs.m12,
436 self.m20 - rhs.m20,
437 self.m21 - rhs.m21,
438 self.m22 - rhs.m22,
439 )
440 }
441 }
442
443 impl Mul<f64> for Matrix3 {
444 type Output = Self;
445
446 fn mul(self, rhs: f64) -> Self::Output {
447 Self::new(
448 self.m00 * rhs,
449 self.m01 * rhs,
450 self.m02 * rhs,
451 self.m10 * rhs,
452 self.m11 * rhs,
453 self.m12 * rhs,
454 self.m20 * rhs,
455 self.m21 * rhs,
456 self.m22 * rhs,
457 )
458 }
459 }
460
461 impl Div<f64> for Matrix3 {
462 type Output = Self;
463
464 fn div(self, rhs: f64) -> Self::Output {
465 Self::new(
466 self.m00 / rhs,
467 self.m01 / rhs,
468 self.m02 / rhs,
469 self.m10 / rhs,
470 self.m11 / rhs,
471 self.m12 / rhs,
472 self.m20 / rhs,
473 self.m21 / rhs,
474 self.m22 / rhs,
475 )
476 }
477 }
478
479 impl Neg for Matrix3 {
480 type Output = Self;
481
482 fn neg(self) -> Self::Output {
483 Self::new(
484 -self.m00, -self.m01, -self.m02, -self.m10, -self.m11, -self.m12, -self.m20,
485 -self.m21, -self.m22,
486 )
487 }
488 }
489
490 impl Mul for Matrix3 {
491 type Output = Self;
492
493 fn mul(self, rhs: Self) -> Self::Output {
494 Self::new(
495 dot3(self.m00, rhs.m00, self.m01, rhs.m10, self.m02, rhs.m20),
496 dot3(self.m00, rhs.m01, self.m01, rhs.m11, self.m02, rhs.m21),
497 dot3(self.m00, rhs.m02, self.m01, rhs.m12, self.m02, rhs.m22),
498 dot3(self.m10, rhs.m00, self.m11, rhs.m10, self.m12, rhs.m20),
499 dot3(self.m10, rhs.m01, self.m11, rhs.m11, self.m12, rhs.m21),
500 dot3(self.m10, rhs.m02, self.m11, rhs.m12, self.m12, rhs.m22),
501 dot3(self.m20, rhs.m00, self.m21, rhs.m10, self.m22, rhs.m20),
502 dot3(self.m20, rhs.m01, self.m21, rhs.m11, self.m22, rhs.m21),
503 dot3(self.m20, rhs.m02, self.m21, rhs.m12, self.m22, rhs.m22),
504 )
505 }
506 }
507
508 impl Mul<Vector3> for Matrix3 {
509 type Output = Vector3;
510
511 fn mul(self, rhs: Vector3) -> Self::Output {
512 let x_component = rhs.x();
513 let y_component = rhs.y();
514 let z_component = rhs.z();
515
516 Vector3::new(
517 dot3(
518 self.m00,
519 x_component,
520 self.m01,
521 y_component,
522 self.m02,
523 z_component,
524 ),
525 dot3(
526 self.m10,
527 x_component,
528 self.m11,
529 y_component,
530 self.m12,
531 z_component,
532 ),
533 dot3(
534 self.m20,
535 x_component,
536 self.m21,
537 y_component,
538 self.m22,
539 z_component,
540 ),
541 )
542 }
543 }
544}
545
546pub mod matrix4 {
548 use core::ops::{Add, Div, Mul, Neg, Sub};
549
550 use use_vector::Vector4;
551
552 #[inline]
553 fn dot4(a0: f64, b0: f64, a1: f64, b1: f64, a2: f64, b2: f64, a3: f64, b3: f64) -> f64 {
554 a0.mul_add(b0, a1.mul_add(b1, a2.mul_add(b2, a3 * b3)))
555 }
556
557 #[derive(Debug, Clone, Copy, PartialEq)]
574 pub struct Matrix4 {
575 pub m00: f64,
576 pub m01: f64,
577 pub m02: f64,
578 pub m03: f64,
579 pub m10: f64,
580 pub m11: f64,
581 pub m12: f64,
582 pub m13: f64,
583 pub m20: f64,
584 pub m21: f64,
585 pub m22: f64,
586 pub m23: f64,
587 pub m30: f64,
588 pub m31: f64,
589 pub m32: f64,
590 pub m33: f64,
591 }
592
593 impl Matrix4 {
594 pub const ZERO: Self = Self::new(
596 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
597 );
598
599 pub const IDENTITY: Self = Self::new(
616 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
617 );
618
619 #[must_use]
621 #[allow(clippy::similar_names, clippy::too_many_arguments)]
622 pub const fn new(
623 m00: f64,
624 m01: f64,
625 m02: f64,
626 m03: f64,
627 m10: f64,
628 m11: f64,
629 m12: f64,
630 m13: f64,
631 m20: f64,
632 m21: f64,
633 m22: f64,
634 m23: f64,
635 m30: f64,
636 m31: f64,
637 m32: f64,
638 m33: f64,
639 ) -> Self {
640 Self {
641 m00,
642 m01,
643 m02,
644 m03,
645 m10,
646 m11,
647 m12,
648 m13,
649 m20,
650 m21,
651 m22,
652 m23,
653 m30,
654 m31,
655 m32,
656 m33,
657 }
658 }
659
660 #[must_use]
662 pub const fn from_rows(rows: [[f64; 4]; 4]) -> Self {
663 Self::new(
664 rows[0][0], rows[0][1], rows[0][2], rows[0][3], rows[1][0], rows[1][1], rows[1][2],
665 rows[1][3], rows[2][0], rows[2][1], rows[2][2], rows[2][3], rows[3][0], rows[3][1],
666 rows[3][2], rows[3][3],
667 )
668 }
669
670 #[must_use]
672 pub const fn from_cols(cols: [[f64; 4]; 4]) -> Self {
673 Self::new(
674 cols[0][0], cols[1][0], cols[2][0], cols[3][0], cols[0][1], cols[1][1], cols[2][1],
675 cols[3][1], cols[0][2], cols[1][2], cols[2][2], cols[3][2], cols[0][3], cols[1][3],
676 cols[2][3], cols[3][3],
677 )
678 }
679
680 #[must_use]
682 pub const fn transpose(self) -> Self {
683 Self::new(
684 self.m00, self.m10, self.m20, self.m30, self.m01, self.m11, self.m21, self.m31,
685 self.m02, self.m12, self.m22, self.m32, self.m03, self.m13, self.m23, self.m33,
686 )
687 }
688
689 #[must_use]
691 pub const fn determinant(self) -> f64 {
692 let minor00 = determinant3([
693 [self.m11, self.m12, self.m13],
694 [self.m21, self.m22, self.m23],
695 [self.m31, self.m32, self.m33],
696 ]);
697 let minor01 = determinant3([
698 [self.m10, self.m12, self.m13],
699 [self.m20, self.m22, self.m23],
700 [self.m30, self.m32, self.m33],
701 ]);
702 let minor02 = determinant3([
703 [self.m10, self.m11, self.m13],
704 [self.m20, self.m21, self.m23],
705 [self.m30, self.m31, self.m33],
706 ]);
707 let minor03 = determinant3([
708 [self.m10, self.m11, self.m12],
709 [self.m20, self.m21, self.m22],
710 [self.m30, self.m31, self.m32],
711 ]);
712
713 (self.m00 * minor00) - (self.m01 * minor01) + (self.m02 * minor02)
714 - (self.m03 * minor03)
715 }
716
717 #[must_use]
719 pub const fn trace(self) -> f64 {
720 self.m00 + self.m11 + self.m22 + self.m33
721 }
722 }
723
724 impl Add for Matrix4 {
725 type Output = Self;
726
727 fn add(self, rhs: Self) -> Self::Output {
728 Self::new(
729 self.m00 + rhs.m00,
730 self.m01 + rhs.m01,
731 self.m02 + rhs.m02,
732 self.m03 + rhs.m03,
733 self.m10 + rhs.m10,
734 self.m11 + rhs.m11,
735 self.m12 + rhs.m12,
736 self.m13 + rhs.m13,
737 self.m20 + rhs.m20,
738 self.m21 + rhs.m21,
739 self.m22 + rhs.m22,
740 self.m23 + rhs.m23,
741 self.m30 + rhs.m30,
742 self.m31 + rhs.m31,
743 self.m32 + rhs.m32,
744 self.m33 + rhs.m33,
745 )
746 }
747 }
748
749 impl Sub for Matrix4 {
750 type Output = Self;
751
752 fn sub(self, rhs: Self) -> Self::Output {
753 Self::new(
754 self.m00 - rhs.m00,
755 self.m01 - rhs.m01,
756 self.m02 - rhs.m02,
757 self.m03 - rhs.m03,
758 self.m10 - rhs.m10,
759 self.m11 - rhs.m11,
760 self.m12 - rhs.m12,
761 self.m13 - rhs.m13,
762 self.m20 - rhs.m20,
763 self.m21 - rhs.m21,
764 self.m22 - rhs.m22,
765 self.m23 - rhs.m23,
766 self.m30 - rhs.m30,
767 self.m31 - rhs.m31,
768 self.m32 - rhs.m32,
769 self.m33 - rhs.m33,
770 )
771 }
772 }
773
774 impl Mul<f64> for Matrix4 {
775 type Output = Self;
776
777 fn mul(self, rhs: f64) -> Self::Output {
778 Self::new(
779 self.m00 * rhs,
780 self.m01 * rhs,
781 self.m02 * rhs,
782 self.m03 * rhs,
783 self.m10 * rhs,
784 self.m11 * rhs,
785 self.m12 * rhs,
786 self.m13 * rhs,
787 self.m20 * rhs,
788 self.m21 * rhs,
789 self.m22 * rhs,
790 self.m23 * rhs,
791 self.m30 * rhs,
792 self.m31 * rhs,
793 self.m32 * rhs,
794 self.m33 * rhs,
795 )
796 }
797 }
798
799 impl Div<f64> for Matrix4 {
800 type Output = Self;
801
802 fn div(self, rhs: f64) -> Self::Output {
803 Self::new(
804 self.m00 / rhs,
805 self.m01 / rhs,
806 self.m02 / rhs,
807 self.m03 / rhs,
808 self.m10 / rhs,
809 self.m11 / rhs,
810 self.m12 / rhs,
811 self.m13 / rhs,
812 self.m20 / rhs,
813 self.m21 / rhs,
814 self.m22 / rhs,
815 self.m23 / rhs,
816 self.m30 / rhs,
817 self.m31 / rhs,
818 self.m32 / rhs,
819 self.m33 / rhs,
820 )
821 }
822 }
823
824 impl Neg for Matrix4 {
825 type Output = Self;
826
827 fn neg(self) -> Self::Output {
828 Self::new(
829 -self.m00, -self.m01, -self.m02, -self.m03, -self.m10, -self.m11, -self.m12,
830 -self.m13, -self.m20, -self.m21, -self.m22, -self.m23, -self.m30, -self.m31,
831 -self.m32, -self.m33,
832 )
833 }
834 }
835
836 impl Mul for Matrix4 {
837 type Output = Self;
838
839 fn mul(self, rhs: Self) -> Self::Output {
840 Self::new(
841 dot4(
842 self.m00, rhs.m00, self.m01, rhs.m10, self.m02, rhs.m20, self.m03, rhs.m30,
843 ),
844 dot4(
845 self.m00, rhs.m01, self.m01, rhs.m11, self.m02, rhs.m21, self.m03, rhs.m31,
846 ),
847 dot4(
848 self.m00, rhs.m02, self.m01, rhs.m12, self.m02, rhs.m22, self.m03, rhs.m32,
849 ),
850 dot4(
851 self.m00, rhs.m03, self.m01, rhs.m13, self.m02, rhs.m23, self.m03, rhs.m33,
852 ),
853 dot4(
854 self.m10, rhs.m00, self.m11, rhs.m10, self.m12, rhs.m20, self.m13, rhs.m30,
855 ),
856 dot4(
857 self.m10, rhs.m01, self.m11, rhs.m11, self.m12, rhs.m21, self.m13, rhs.m31,
858 ),
859 dot4(
860 self.m10, rhs.m02, self.m11, rhs.m12, self.m12, rhs.m22, self.m13, rhs.m32,
861 ),
862 dot4(
863 self.m10, rhs.m03, self.m11, rhs.m13, self.m12, rhs.m23, self.m13, rhs.m33,
864 ),
865 dot4(
866 self.m20, rhs.m00, self.m21, rhs.m10, self.m22, rhs.m20, self.m23, rhs.m30,
867 ),
868 dot4(
869 self.m20, rhs.m01, self.m21, rhs.m11, self.m22, rhs.m21, self.m23, rhs.m31,
870 ),
871 dot4(
872 self.m20, rhs.m02, self.m21, rhs.m12, self.m22, rhs.m22, self.m23, rhs.m32,
873 ),
874 dot4(
875 self.m20, rhs.m03, self.m21, rhs.m13, self.m22, rhs.m23, self.m23, rhs.m33,
876 ),
877 dot4(
878 self.m30, rhs.m00, self.m31, rhs.m10, self.m32, rhs.m20, self.m33, rhs.m30,
879 ),
880 dot4(
881 self.m30, rhs.m01, self.m31, rhs.m11, self.m32, rhs.m21, self.m33, rhs.m31,
882 ),
883 dot4(
884 self.m30, rhs.m02, self.m31, rhs.m12, self.m32, rhs.m22, self.m33, rhs.m32,
885 ),
886 dot4(
887 self.m30, rhs.m03, self.m31, rhs.m13, self.m32, rhs.m23, self.m33, rhs.m33,
888 ),
889 )
890 }
891 }
892
893 impl Mul<Vector4> for Matrix4 {
894 type Output = Vector4;
895
896 fn mul(self, rhs: Vector4) -> Self::Output {
897 let x_component = rhs.x();
898 let y_component = rhs.y();
899 let z_component = rhs.z();
900 let w_component = rhs.w();
901
902 Vector4::new(
903 dot4(
904 self.m00,
905 x_component,
906 self.m01,
907 y_component,
908 self.m02,
909 z_component,
910 self.m03,
911 w_component,
912 ),
913 dot4(
914 self.m10,
915 x_component,
916 self.m11,
917 y_component,
918 self.m12,
919 z_component,
920 self.m13,
921 w_component,
922 ),
923 dot4(
924 self.m20,
925 x_component,
926 self.m21,
927 y_component,
928 self.m22,
929 z_component,
930 self.m23,
931 w_component,
932 ),
933 dot4(
934 self.m30,
935 x_component,
936 self.m31,
937 y_component,
938 self.m32,
939 z_component,
940 self.m33,
941 w_component,
942 ),
943 )
944 }
945 }
946
947 const fn determinant3(rows: [[f64; 3]; 3]) -> f64 {
948 (rows[0][0] * ((rows[1][1] * rows[2][2]) - (rows[1][2] * rows[2][1])))
949 - (rows[0][1] * ((rows[1][0] * rows[2][2]) - (rows[1][2] * rows[2][0])))
950 + (rows[0][2] * ((rows[1][0] * rows[2][1]) - (rows[1][1] * rows[2][0])))
951 }
952}
953
954#[cfg(test)]
955mod tests {
956 use super::{Matrix2, Matrix3, Matrix4};
957 use use_vector::{Vector2, Vector3, Vector4};
958
959 fn assert_close(left: f64, right: f64) {
960 assert!((left - right).abs() < 1.0e-10, "left={left}, right={right}");
961 }
962
963 fn assert_matrix2_close(left: Matrix2, right: Matrix2) {
964 assert_close(left.m00, right.m00);
965 assert_close(left.m01, right.m01);
966 assert_close(left.m10, right.m10);
967 assert_close(left.m11, right.m11);
968 }
969
970 fn assert_matrix3_close(left: Matrix3, right: Matrix3) {
971 assert_close(left.m00, right.m00);
972 assert_close(left.m01, right.m01);
973 assert_close(left.m02, right.m02);
974 assert_close(left.m10, right.m10);
975 assert_close(left.m11, right.m11);
976 assert_close(left.m12, right.m12);
977 assert_close(left.m20, right.m20);
978 assert_close(left.m21, right.m21);
979 assert_close(left.m22, right.m22);
980 }
981
982 fn assert_matrix4_close(left: Matrix4, right: Matrix4) {
983 assert_close(left.m00, right.m00);
984 assert_close(left.m01, right.m01);
985 assert_close(left.m02, right.m02);
986 assert_close(left.m03, right.m03);
987 assert_close(left.m10, right.m10);
988 assert_close(left.m11, right.m11);
989 assert_close(left.m12, right.m12);
990 assert_close(left.m13, right.m13);
991 assert_close(left.m20, right.m20);
992 assert_close(left.m21, right.m21);
993 assert_close(left.m22, right.m22);
994 assert_close(left.m23, right.m23);
995 assert_close(left.m30, right.m30);
996 assert_close(left.m31, right.m31);
997 assert_close(left.m32, right.m32);
998 assert_close(left.m33, right.m33);
999 }
1000
1001 #[test]
1002 fn matrix2_construction_and_constants_work() {
1003 let matrix = Matrix2::new(1.0, 2.0, 3.0, 4.0);
1004
1005 assert_eq!(Matrix2::ZERO, Matrix2::new(0.0, 0.0, 0.0, 0.0));
1006 assert_eq!(Matrix2::IDENTITY, Matrix2::new(1.0, 0.0, 0.0, 1.0));
1007 assert_eq!(matrix, Matrix2::from_rows([[1.0, 2.0], [3.0, 4.0]]));
1008 assert_eq!(matrix, Matrix2::from_cols([[1.0, 3.0], [2.0, 4.0]]));
1009 }
1010
1011 #[test]
1012 fn matrix2_arithmetic_and_products_work() {
1013 let left = Matrix2::new(1.0, 2.0, 3.0, 4.0);
1014 let right = Matrix2::new(5.0, 6.0, 7.0, 8.0);
1015 let scale = Matrix2::from_rows([[2.0, 0.0], [0.0, 3.0]]);
1016
1017 assert_eq!(left + right, Matrix2::new(6.0, 8.0, 10.0, 12.0));
1018 assert_eq!(left - right, Matrix2::new(-4.0, -4.0, -4.0, -4.0));
1019 assert_eq!(left * 2.0, Matrix2::new(2.0, 4.0, 6.0, 8.0));
1020 assert_eq!(left / 2.0, Matrix2::new(0.5, 1.0, 1.5, 2.0));
1021 assert_eq!(-left, Matrix2::new(-1.0, -2.0, -3.0, -4.0));
1022 assert_eq!(left * scale, Matrix2::new(2.0, 6.0, 6.0, 12.0));
1023 assert_eq!(left * Vector2::new(1.0, -1.0), Vector2::new(-1.0, -1.0));
1024 assert_eq!(Matrix2::IDENTITY * left, left);
1025 assert_eq!(left * Matrix2::IDENTITY, left);
1026 }
1027
1028 #[test]
1029 fn matrix2_transpose_determinant_trace_and_inverse_work() {
1030 let matrix = Matrix2::new(4.0, 7.0, 2.0, 6.0);
1031
1032 assert_eq!(matrix.transpose(), Matrix2::new(4.0, 2.0, 7.0, 6.0));
1033 assert_eq!(matrix.transpose().transpose(), matrix);
1034 assert_close(matrix.determinant(), 10.0);
1035 assert_close(matrix.trace(), 10.0);
1036
1037 let inverse = matrix.inverse().expect("matrix should invert");
1038
1039 assert_matrix2_close(inverse, Matrix2::new(0.6, -0.7, -0.2, 0.4));
1040 assert_matrix2_close(matrix * inverse, Matrix2::IDENTITY);
1041 assert!(Matrix2::new(1.0, 2.0, 2.0, 4.0).inverse().is_none());
1042 assert!(
1043 Matrix2::new(f64::INFINITY, 0.0, 0.0, 1.0)
1044 .inverse()
1045 .is_none()
1046 );
1047 }
1048
1049 #[test]
1050 fn matrix3_construction_and_constants_work() {
1051 let matrix = Matrix3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0);
1052
1053 assert_eq!(
1054 Matrix3::ZERO,
1055 Matrix3::new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
1056 );
1057 assert_eq!(
1058 Matrix3::IDENTITY,
1059 Matrix3::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
1060 );
1061 assert_eq!(
1062 matrix,
1063 Matrix3::from_rows([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0],])
1064 );
1065 assert_eq!(
1066 matrix,
1067 Matrix3::from_cols([[1.0, 4.0, 7.0], [2.0, 5.0, 8.0], [3.0, 6.0, 9.0],])
1068 );
1069 }
1070
1071 #[test]
1072 fn matrix3_arithmetic_and_products_work() {
1073 let left = Matrix3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0);
1074 let right = Matrix3::new(9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
1075 let scale = Matrix3::from_rows([[2.0, 0.0, 0.0], [0.0, 3.0, 0.0], [0.0, 0.0, 4.0]]);
1076
1077 assert_eq!(
1078 left + right,
1079 Matrix3::new(10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 11.0)
1080 );
1081 assert_eq!(
1082 left - right,
1083 Matrix3::new(-8.0, -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 9.0)
1084 );
1085 assert_eq!(
1086 left * 2.0,
1087 Matrix3::new(2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0, 20.0)
1088 );
1089 assert_eq!(
1090 left / 2.0,
1091 Matrix3::new(0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0)
1092 );
1093 assert_eq!(
1094 -left,
1095 Matrix3::new(-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0, -8.0, -10.0)
1096 );
1097 assert_eq!(
1098 left * scale,
1099 Matrix3::new(2.0, 6.0, 12.0, 8.0, 15.0, 24.0, 14.0, 24.0, 40.0)
1100 );
1101 assert_eq!(
1102 left * Vector3::new(1.0, 0.0, -1.0),
1103 Vector3::new(-2.0, -2.0, -3.0)
1104 );
1105 assert_eq!(Matrix3::IDENTITY * left, left);
1106 assert_eq!(left * Matrix3::IDENTITY, left);
1107 }
1108
1109 #[test]
1110 fn matrix3_transpose_determinant_trace_and_inverse_work() {
1111 let matrix = Matrix3::new(1.0, 2.0, 3.0, 0.0, 1.0, 4.0, 5.0, 6.0, 0.0);
1112
1113 assert_eq!(
1114 matrix.transpose(),
1115 Matrix3::new(1.0, 0.0, 5.0, 2.0, 1.0, 6.0, 3.0, 4.0, 0.0)
1116 );
1117 assert_eq!(matrix.transpose().transpose(), matrix);
1118 assert_close(matrix.determinant(), 1.0);
1119 assert_close(matrix.trace(), 2.0);
1120
1121 let inverse = matrix.inverse().expect("matrix should invert");
1122
1123 assert_eq!(
1124 inverse,
1125 Matrix3::new(-24.0, 18.0, 5.0, 20.0, -15.0, -4.0, -5.0, 4.0, 1.0)
1126 );
1127 assert_matrix3_close(matrix * inverse, Matrix3::IDENTITY);
1128 assert!(
1129 Matrix3::new(1.0, 2.0, 3.0, 2.0, 4.0, 6.0, 7.0, 8.0, 9.0)
1130 .inverse()
1131 .is_none()
1132 );
1133 assert!(
1134 Matrix3::new(f64::INFINITY, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
1135 .inverse()
1136 .is_none()
1137 );
1138 }
1139
1140 #[test]
1141 fn matrix4_construction_and_constants_work() {
1142 let matrix = Matrix4::from_rows([
1143 [1.0, 2.0, 3.0, 4.0],
1144 [5.0, 6.0, 7.0, 8.0],
1145 [2.0, 0.0, 1.0, 3.0],
1146 [4.0, 1.0, 0.0, 2.0],
1147 ]);
1148
1149 assert_eq!(
1150 Matrix4::ZERO,
1151 Matrix4::new(
1152 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
1153 )
1154 );
1155 assert_eq!(
1156 Matrix4::IDENTITY,
1157 Matrix4::new(
1158 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
1159 )
1160 );
1161 assert_eq!(
1162 matrix,
1163 Matrix4::from_cols([
1164 [1.0, 5.0, 2.0, 4.0],
1165 [2.0, 6.0, 0.0, 1.0],
1166 [3.0, 7.0, 1.0, 0.0],
1167 [4.0, 8.0, 3.0, 2.0],
1168 ])
1169 );
1170 }
1171
1172 #[test]
1173 fn matrix4_arithmetic_and_products_work() {
1174 let left = Matrix4::from_rows([
1175 [1.0, 2.0, 3.0, 4.0],
1176 [5.0, 6.0, 7.0, 8.0],
1177 [2.0, 0.0, 1.0, 3.0],
1178 [4.0, 1.0, 0.0, 2.0],
1179 ]);
1180 let right = Matrix4::from_rows([
1181 [4.0, 3.0, 2.0, 1.0],
1182 [0.0, 1.0, 2.0, 3.0],
1183 [1.0, 0.0, 1.0, 0.0],
1184 [2.0, 1.0, 0.0, 2.0],
1185 ]);
1186 let scale = Matrix4::from_rows([
1187 [2.0, 0.0, 0.0, 0.0],
1188 [0.0, 3.0, 0.0, 0.0],
1189 [0.0, 0.0, 4.0, 0.0],
1190 [0.0, 0.0, 0.0, 5.0],
1191 ]);
1192
1193 assert_eq!(
1194 left + right,
1195 Matrix4::from_rows([
1196 [5.0, 5.0, 5.0, 5.0],
1197 [5.0, 7.0, 9.0, 11.0],
1198 [3.0, 0.0, 2.0, 3.0],
1199 [6.0, 2.0, 0.0, 4.0],
1200 ])
1201 );
1202 assert_eq!(
1203 left - right,
1204 Matrix4::from_rows([
1205 [-3.0, -1.0, 1.0, 3.0],
1206 [5.0, 5.0, 5.0, 5.0],
1207 [1.0, 0.0, 0.0, 3.0],
1208 [2.0, 0.0, 0.0, 0.0],
1209 ])
1210 );
1211 assert_eq!(
1212 left * 2.0,
1213 Matrix4::from_rows([
1214 [2.0, 4.0, 6.0, 8.0],
1215 [10.0, 12.0, 14.0, 16.0],
1216 [4.0, 0.0, 2.0, 6.0],
1217 [8.0, 2.0, 0.0, 4.0],
1218 ])
1219 );
1220 assert_eq!(
1221 left / 2.0,
1222 Matrix4::from_rows([
1223 [0.5, 1.0, 1.5, 2.0],
1224 [2.5, 3.0, 3.5, 4.0],
1225 [1.0, 0.0, 0.5, 1.5],
1226 [2.0, 0.5, 0.0, 1.0],
1227 ])
1228 );
1229 assert_eq!(
1230 -left,
1231 Matrix4::from_rows([
1232 [-1.0, -2.0, -3.0, -4.0],
1233 [-5.0, -6.0, -7.0, -8.0],
1234 [-2.0, 0.0, -1.0, -3.0],
1235 [-4.0, -1.0, 0.0, -2.0],
1236 ])
1237 );
1238 assert_eq!(
1239 left * scale,
1240 Matrix4::from_rows([
1241 [2.0, 6.0, 12.0, 20.0],
1242 [10.0, 18.0, 28.0, 40.0],
1243 [4.0, 0.0, 4.0, 15.0],
1244 [8.0, 3.0, 0.0, 10.0],
1245 ])
1246 );
1247 assert_eq!(
1248 left * Vector4::new(1.0, 0.0, -1.0, 2.0),
1249 Vector4::new(6.0, 14.0, 7.0, 8.0)
1250 );
1251 assert_eq!(Matrix4::IDENTITY * left, left);
1252 assert_eq!(left * Matrix4::IDENTITY, left);
1253 }
1254
1255 #[test]
1256 fn matrix4_transpose_determinant_and_trace_work() {
1257 let matrix = Matrix4::from_rows([
1258 [1.0, 2.0, 3.0, 4.0],
1259 [5.0, 6.0, 7.0, 8.0],
1260 [2.0, 0.0, 1.0, 3.0],
1261 [4.0, 1.0, 0.0, 2.0],
1262 ]);
1263 let triangular = Matrix4::from_rows([
1264 [2.0, 1.0, 0.0, 0.0],
1265 [0.0, 3.0, 4.0, 0.0],
1266 [0.0, 0.0, 5.0, 6.0],
1267 [0.0, 0.0, 0.0, 7.0],
1268 ]);
1269
1270 assert_eq!(
1271 matrix.transpose(),
1272 Matrix4::from_rows([
1273 [1.0, 5.0, 2.0, 4.0],
1274 [2.0, 6.0, 0.0, 1.0],
1275 [3.0, 7.0, 1.0, 0.0],
1276 [4.0, 8.0, 3.0, 2.0],
1277 ])
1278 );
1279 assert_eq!(matrix.transpose().transpose(), matrix);
1280 assert_close(matrix.trace(), 10.0);
1281 assert_close(triangular.determinant(), 210.0);
1282 assert_matrix4_close(Matrix4::IDENTITY * triangular, triangular);
1283 }
1284}