1use crate::{DMat3, DVec2, Mat2, f64::math, swizzles::*};
4use core::fmt;
5use core::iter::{Product, Sum};
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8#[cfg(feature = "zerocopy-08")]
9use zerocopy_derive_08::*;
10
11#[inline(always)]
13#[must_use]
14pub const fn dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat2 {
15 DMat2::from_cols(x_axis, y_axis)
16}
17
18#[derive(Clone, Copy)]
20#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
21#[cfg_attr(
22 feature = "zerocopy-08",
23 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
24)]
25#[cfg_attr(feature = "cuda", repr(align(16)))]
26#[repr(C)]
27pub struct DMat2 {
28 pub x_axis: DVec2,
29 pub y_axis: DVec2,
30}
31
32impl DMat2 {
33 pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
35
36 pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
38
39 pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
41
42 #[allow(clippy::too_many_arguments)]
43 #[inline(always)]
44 #[must_use]
45 const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
46 Self {
47 x_axis: DVec2::new(m00, m01),
48 y_axis: DVec2::new(m10, m11),
49 }
50 }
51
52 #[inline(always)]
56 #[must_use]
57 pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
58 Self { x_axis, y_axis }
59 }
60
61 #[inline(always)]
67 #[must_use]
68 pub const fn from_rows(row0: DVec2, row1: DVec2) -> Self {
69 let [m00, m01] = row0.to_array();
70 let [m10, m11] = row1.to_array();
71 Self::new(m00, m10, m01, m11)
72 }
73
74 #[inline]
78 #[must_use]
79 pub const fn from_cols_array(m: &[f64; 4]) -> Self {
80 Self::new(m[0], m[1], m[2], m[3])
81 }
82
83 #[inline]
87 #[must_use]
88 pub const fn to_cols_array(&self) -> [f64; 4] {
89 [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
90 }
91
92 #[inline]
96 #[must_use]
97 pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
98 Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
99 }
100
101 #[inline]
105 #[must_use]
106 pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
107 [self.x_axis.to_array(), self.y_axis.to_array()]
108 }
109
110 #[inline]
116 #[must_use]
117 pub const fn from_rows_array(m: &[f64; 4]) -> Self {
118 Self::new(m[0], m[2], m[1], m[3])
119 }
120
121 #[inline]
127 #[must_use]
128 pub const fn to_rows_array(&self) -> [f64; 4] {
129 let m = self.to_cols_array();
130 [m[0], m[2], m[1], m[3]]
131 }
132
133 #[doc(alias = "scale")]
135 #[inline]
136 #[must_use]
137 pub const fn from_diagonal(diagonal: DVec2) -> Self {
138 Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
139 }
140
141 #[inline]
144 #[must_use]
145 pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
146 let (sin, cos) = math::sin_cos(angle);
147 Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
148 }
149
150 #[inline]
152 #[must_use]
153 pub fn from_angle(angle: f64) -> Self {
154 let (sin, cos) = math::sin_cos(angle);
155 Self::new(cos, sin, -sin, cos)
156 }
157
158 #[inline]
160 #[must_use]
161 pub fn from_mat3(m: DMat3) -> Self {
162 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
163 }
164
165 #[inline]
172 #[must_use]
173 #[track_caller]
174 pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
175 match (i, j) {
176 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
177 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
178 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
179 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
180 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
181 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
182 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
183 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
184 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
185 _ => panic!("index out of bounds"),
186 }
187 }
188
189 #[inline]
197 #[must_use]
198 #[track_caller]
199 pub const fn from_cols_slice(slice: &[f64]) -> Self {
200 Self::new(slice[0], slice[1], slice[2], slice[3])
201 }
202
203 #[inline]
209 #[track_caller]
210 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
211 slice[0] = self.x_axis.x;
212 slice[1] = self.x_axis.y;
213 slice[2] = self.y_axis.x;
214 slice[3] = self.y_axis.y;
215 }
216
217 #[inline]
228 #[must_use]
229 #[track_caller]
230 pub const fn from_rows_slice(slice: &[f64]) -> Self {
231 Self::new(slice[0], slice[2], slice[1], slice[3])
232 }
233
234 #[inline]
240 #[must_use]
241 #[track_caller]
242 pub fn col(&self, index: usize) -> DVec2 {
243 match index {
244 0 => self.x_axis,
245 1 => self.y_axis,
246 _ => panic!("index out of bounds"),
247 }
248 }
249
250 #[inline]
256 #[track_caller]
257 pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
258 match index {
259 0 => &mut self.x_axis,
260 1 => &mut self.y_axis,
261 _ => panic!("index out of bounds"),
262 }
263 }
264
265 #[inline]
273 #[must_use]
274 #[track_caller]
275 pub fn row(&self, index: usize) -> DVec2 {
276 match index {
277 0 => DVec2::new(self.x_axis.x, self.y_axis.x),
278 1 => DVec2::new(self.x_axis.y, self.y_axis.y),
279 _ => panic!("index out of bounds"),
280 }
281 }
282
283 #[inline]
293 #[track_caller]
294 pub fn set_row(&mut self, index: usize, row: DVec2) {
295 match index {
296 0 => {
297 self.x_axis.x = row.x;
298 self.y_axis.x = row.y;
299 }
300 1 => {
301 self.x_axis.y = row.x;
302 self.y_axis.y = row.y;
303 }
304 _ => panic!("index out of bounds"),
305 }
306 }
307
308 #[inline]
311 #[must_use]
312 pub fn is_finite(&self) -> bool {
313 self.x_axis.is_finite() && self.y_axis.is_finite()
314 }
315
316 #[inline]
318 #[must_use]
319 pub fn is_nan(&self) -> bool {
320 self.x_axis.is_nan() || self.y_axis.is_nan()
321 }
322
323 #[inline]
325 #[must_use]
326 pub fn transpose(&self) -> Self {
327 Self {
328 x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
329 y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
330 }
331 }
332
333 #[inline]
335 #[must_use]
336 pub fn diagonal(&self) -> DVec2 {
337 DVec2::new(self.x_axis.x, self.y_axis.y)
338 }
339
340 #[inline]
342 #[must_use]
343 pub fn determinant(&self) -> f64 {
344 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
345 }
346
347 #[inline(always)]
359 #[must_use]
360 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
361 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
362 let inv_det = 1.0 / self.determinant();
363 let m = Self::new(
364 self.y_axis.y * inv_det,
365 self.x_axis.y * -inv_det,
366 self.y_axis.x * -inv_det,
367 self.x_axis.x * inv_det,
368 );
369 if CHECKED {
370 if !m.is_finite() {
371 return (Self::ZERO, false);
372 }
373 } else {
374 glam_assert!(m.is_finite());
375 }
376 (m, true)
377 }
378
379 #[inline]
391 #[must_use]
392 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
393 pub fn inverse(&self) -> Self {
394 self.inverse_checked::<false>().0
395 }
396
397 #[inline]
400 #[must_use]
401 pub fn try_inverse(&self) -> Option<Self> {
402 let (m, is_valid) = self.inverse_checked::<true>();
403 if is_valid { Some(m) } else { None }
404 }
405
406 #[inline]
409 #[must_use]
410 pub fn inverse_or_zero(&self) -> Self {
411 self.inverse_checked::<true>().0
412 }
413
414 #[inline]
416 #[must_use]
417 pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
418 #[allow(clippy::suspicious_operation_groupings)]
419 DVec2::new(
420 (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
421 (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
422 )
423 }
424
425 #[inline]
427 #[must_use]
428 pub fn mul_transpose_vec2(&self, rhs: DVec2) -> DVec2 {
429 DVec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
430 }
431
432 #[inline]
434 #[must_use]
435 pub fn mul_mat2(&self, rhs: &Self) -> Self {
436 self.mul(rhs)
437 }
438
439 #[inline]
441 #[must_use]
442 pub fn add_mat2(&self, rhs: &Self) -> Self {
443 self.add(rhs)
444 }
445
446 #[inline]
448 #[must_use]
449 pub fn sub_mat2(&self, rhs: &Self) -> Self {
450 self.sub(rhs)
451 }
452
453 #[inline]
455 #[must_use]
456 pub fn mul_scalar(&self, rhs: f64) -> Self {
457 Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
458 }
459
460 #[inline]
464 #[must_use]
465 pub fn mul_diagonal_scale(&self, scale: DVec2) -> Self {
466 Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
467 }
468
469 #[inline]
471 #[must_use]
472 pub fn div_scalar(&self, rhs: f64) -> Self {
473 let rhs = DVec2::splat(rhs);
474 Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
475 }
476
477 #[inline]
479 #[must_use]
480 pub fn recip(&self) -> Self {
481 Self::from_cols(self.x_axis.recip(), self.y_axis.recip())
482 }
483
484 #[inline]
494 #[must_use]
495 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
496 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
497 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
498 }
499
500 #[inline]
502 #[must_use]
503 pub fn abs(&self) -> Self {
504 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
505 }
506
507 #[cfg(feature = "f64")]
508 #[inline]
509 #[must_use]
510 pub fn as_mat2(&self) -> Mat2 {
511 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
512 }
513}
514
515impl Default for DMat2 {
516 #[inline]
517 fn default() -> Self {
518 Self::IDENTITY
519 }
520}
521
522impl Add for DMat2 {
523 type Output = Self;
524 #[inline]
525 fn add(self, rhs: Self) -> Self {
526 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
527 }
528}
529
530impl Add<&Self> for DMat2 {
531 type Output = Self;
532 #[inline]
533 fn add(self, rhs: &Self) -> Self {
534 self.add(*rhs)
535 }
536}
537
538impl Add<&DMat2> for &DMat2 {
539 type Output = DMat2;
540 #[inline]
541 fn add(self, rhs: &DMat2) -> DMat2 {
542 (*self).add(*rhs)
543 }
544}
545
546impl Add<DMat2> for &DMat2 {
547 type Output = DMat2;
548 #[inline]
549 fn add(self, rhs: DMat2) -> DMat2 {
550 (*self).add(rhs)
551 }
552}
553
554impl AddAssign for DMat2 {
555 #[inline]
556 fn add_assign(&mut self, rhs: Self) {
557 *self = self.add(rhs);
558 }
559}
560
561impl AddAssign<&Self> for DMat2 {
562 #[inline]
563 fn add_assign(&mut self, rhs: &Self) {
564 self.add_assign(*rhs);
565 }
566}
567
568impl Sub for DMat2 {
569 type Output = Self;
570 #[inline]
571 fn sub(self, rhs: Self) -> Self {
572 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
573 }
574}
575
576impl Sub<&Self> for DMat2 {
577 type Output = Self;
578 #[inline]
579 fn sub(self, rhs: &Self) -> Self {
580 self.sub(*rhs)
581 }
582}
583
584impl Sub<&DMat2> for &DMat2 {
585 type Output = DMat2;
586 #[inline]
587 fn sub(self, rhs: &DMat2) -> DMat2 {
588 (*self).sub(*rhs)
589 }
590}
591
592impl Sub<DMat2> for &DMat2 {
593 type Output = DMat2;
594 #[inline]
595 fn sub(self, rhs: DMat2) -> DMat2 {
596 (*self).sub(rhs)
597 }
598}
599
600impl SubAssign for DMat2 {
601 #[inline]
602 fn sub_assign(&mut self, rhs: Self) {
603 *self = self.sub(rhs);
604 }
605}
606
607impl SubAssign<&Self> for DMat2 {
608 #[inline]
609 fn sub_assign(&mut self, rhs: &Self) {
610 self.sub_assign(*rhs);
611 }
612}
613
614impl Neg for DMat2 {
615 type Output = Self;
616 #[inline]
617 fn neg(self) -> Self::Output {
618 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
619 }
620}
621
622impl Neg for &DMat2 {
623 type Output = DMat2;
624 #[inline]
625 fn neg(self) -> DMat2 {
626 (*self).neg()
627 }
628}
629
630impl Mul for DMat2 {
631 type Output = Self;
632 #[inline]
633 fn mul(self, rhs: Self) -> Self {
634 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
635 }
636}
637
638impl Mul<&Self> for DMat2 {
639 type Output = Self;
640 #[inline]
641 fn mul(self, rhs: &Self) -> Self {
642 self.mul(*rhs)
643 }
644}
645
646impl Mul<&DMat2> for &DMat2 {
647 type Output = DMat2;
648 #[inline]
649 fn mul(self, rhs: &DMat2) -> DMat2 {
650 (*self).mul(*rhs)
651 }
652}
653
654impl Mul<DMat2> for &DMat2 {
655 type Output = DMat2;
656 #[inline]
657 fn mul(self, rhs: DMat2) -> DMat2 {
658 (*self).mul(rhs)
659 }
660}
661
662impl MulAssign for DMat2 {
663 #[inline]
664 fn mul_assign(&mut self, rhs: Self) {
665 *self = self.mul(rhs);
666 }
667}
668
669impl MulAssign<&Self> for DMat2 {
670 #[inline]
671 fn mul_assign(&mut self, rhs: &Self) {
672 self.mul_assign(*rhs);
673 }
674}
675
676impl Mul<DVec2> for DMat2 {
677 type Output = DVec2;
678 #[inline]
679 fn mul(self, rhs: DVec2) -> Self::Output {
680 self.mul_vec2(rhs)
681 }
682}
683
684impl Mul<&DVec2> for DMat2 {
685 type Output = DVec2;
686 #[inline]
687 fn mul(self, rhs: &DVec2) -> DVec2 {
688 self.mul(*rhs)
689 }
690}
691
692impl Mul<&DVec2> for &DMat2 {
693 type Output = DVec2;
694 #[inline]
695 fn mul(self, rhs: &DVec2) -> DVec2 {
696 (*self).mul(*rhs)
697 }
698}
699
700impl Mul<DVec2> for &DMat2 {
701 type Output = DVec2;
702 #[inline]
703 fn mul(self, rhs: DVec2) -> DVec2 {
704 (*self).mul(rhs)
705 }
706}
707
708impl Mul<DMat2> for f64 {
709 type Output = DMat2;
710 #[inline]
711 fn mul(self, rhs: DMat2) -> Self::Output {
712 rhs.mul_scalar(self)
713 }
714}
715
716impl Mul<&DMat2> for f64 {
717 type Output = DMat2;
718 #[inline]
719 fn mul(self, rhs: &DMat2) -> DMat2 {
720 self.mul(*rhs)
721 }
722}
723
724impl Mul<&DMat2> for &f64 {
725 type Output = DMat2;
726 #[inline]
727 fn mul(self, rhs: &DMat2) -> DMat2 {
728 (*self).mul(*rhs)
729 }
730}
731
732impl Mul<DMat2> for &f64 {
733 type Output = DMat2;
734 #[inline]
735 fn mul(self, rhs: DMat2) -> DMat2 {
736 (*self).mul(rhs)
737 }
738}
739
740impl Mul<f64> for DMat2 {
741 type Output = Self;
742 #[inline]
743 fn mul(self, rhs: f64) -> Self {
744 self.mul_scalar(rhs)
745 }
746}
747
748impl Mul<&f64> for DMat2 {
749 type Output = Self;
750 #[inline]
751 fn mul(self, rhs: &f64) -> Self {
752 self.mul(*rhs)
753 }
754}
755
756impl Mul<&f64> for &DMat2 {
757 type Output = DMat2;
758 #[inline]
759 fn mul(self, rhs: &f64) -> DMat2 {
760 (*self).mul(*rhs)
761 }
762}
763
764impl Mul<f64> for &DMat2 {
765 type Output = DMat2;
766 #[inline]
767 fn mul(self, rhs: f64) -> DMat2 {
768 (*self).mul(rhs)
769 }
770}
771
772impl MulAssign<f64> for DMat2 {
773 #[inline]
774 fn mul_assign(&mut self, rhs: f64) {
775 *self = self.mul(rhs);
776 }
777}
778
779impl MulAssign<&f64> for DMat2 {
780 #[inline]
781 fn mul_assign(&mut self, rhs: &f64) {
782 self.mul_assign(*rhs);
783 }
784}
785
786impl Div<DMat2> for f64 {
787 type Output = DMat2;
788 #[inline]
789 fn div(self, rhs: DMat2) -> Self::Output {
790 DMat2::from_cols(self.div(rhs.x_axis), self.div(rhs.y_axis))
791 }
792}
793
794impl Div<&DMat2> for f64 {
795 type Output = DMat2;
796 #[inline]
797 fn div(self, rhs: &DMat2) -> DMat2 {
798 self.div(*rhs)
799 }
800}
801
802impl Div<&DMat2> for &f64 {
803 type Output = DMat2;
804 #[inline]
805 fn div(self, rhs: &DMat2) -> DMat2 {
806 (*self).div(*rhs)
807 }
808}
809
810impl Div<DMat2> for &f64 {
811 type Output = DMat2;
812 #[inline]
813 fn div(self, rhs: DMat2) -> DMat2 {
814 (*self).div(rhs)
815 }
816}
817
818impl Div<f64> for DMat2 {
819 type Output = Self;
820 #[inline]
821 fn div(self, rhs: f64) -> Self {
822 self.div_scalar(rhs)
823 }
824}
825
826impl Div<&f64> for DMat2 {
827 type Output = Self;
828 #[inline]
829 fn div(self, rhs: &f64) -> Self {
830 self.div(*rhs)
831 }
832}
833
834impl Div<&f64> for &DMat2 {
835 type Output = DMat2;
836 #[inline]
837 fn div(self, rhs: &f64) -> DMat2 {
838 (*self).div(*rhs)
839 }
840}
841
842impl Div<f64> for &DMat2 {
843 type Output = DMat2;
844 #[inline]
845 fn div(self, rhs: f64) -> DMat2 {
846 (*self).div(rhs)
847 }
848}
849
850impl DivAssign<f64> for DMat2 {
851 #[inline]
852 fn div_assign(&mut self, rhs: f64) {
853 *self = self.div(rhs);
854 }
855}
856
857impl DivAssign<&f64> for DMat2 {
858 #[inline]
859 fn div_assign(&mut self, rhs: &f64) {
860 self.div_assign(*rhs);
861 }
862}
863
864impl Sum<Self> for DMat2 {
865 fn sum<I>(iter: I) -> Self
866 where
867 I: Iterator<Item = Self>,
868 {
869 iter.fold(Self::ZERO, Self::add)
870 }
871}
872
873impl<'a> Sum<&'a Self> for DMat2 {
874 fn sum<I>(iter: I) -> Self
875 where
876 I: Iterator<Item = &'a Self>,
877 {
878 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
879 }
880}
881
882impl Product for DMat2 {
883 fn product<I>(iter: I) -> Self
884 where
885 I: Iterator<Item = Self>,
886 {
887 iter.fold(Self::IDENTITY, Self::mul)
888 }
889}
890
891impl<'a> Product<&'a Self> for DMat2 {
892 fn product<I>(iter: I) -> Self
893 where
894 I: Iterator<Item = &'a Self>,
895 {
896 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
897 }
898}
899
900impl PartialEq for DMat2 {
901 #[inline]
902 fn eq(&self, rhs: &Self) -> bool {
903 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
904 }
905}
906
907impl AsRef<[f64; 4]> for DMat2 {
908 #[inline]
909 fn as_ref(&self) -> &[f64; 4] {
910 unsafe { &*(self as *const Self as *const [f64; 4]) }
911 }
912}
913
914impl AsMut<[f64; 4]> for DMat2 {
915 #[inline]
916 fn as_mut(&mut self) -> &mut [f64; 4] {
917 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
918 }
919}
920
921impl fmt::Debug for DMat2 {
922 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
923 fmt.debug_struct(stringify!(DMat2))
924 .field("x_axis", &self.x_axis)
925 .field("y_axis", &self.y_axis)
926 .finish()
927 }
928}
929
930impl fmt::Display for DMat2 {
931 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
932 if let Some(p) = f.precision() {
933 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
934 } else {
935 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
936 }
937 }
938}