1use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2};
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 pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
174 match (i, j) {
175 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
176 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
177 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
178 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
179 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
180 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
181 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
182 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
183 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
184 _ => panic!("index out of bounds"),
185 }
186 }
187
188 #[inline]
196 #[must_use]
197 pub const fn from_cols_slice(slice: &[f64]) -> Self {
198 Self::new(slice[0], slice[1], slice[2], slice[3])
199 }
200
201 #[inline]
207 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
208 slice[0] = self.x_axis.x;
209 slice[1] = self.x_axis.y;
210 slice[2] = self.y_axis.x;
211 slice[3] = self.y_axis.y;
212 }
213
214 #[inline]
225 #[must_use]
226 pub const fn from_rows_slice(slice: &[f64]) -> Self {
227 Self::new(slice[0], slice[2], slice[1], slice[3])
228 }
229
230 #[inline]
236 #[must_use]
237 pub fn col(&self, index: usize) -> DVec2 {
238 match index {
239 0 => self.x_axis,
240 1 => self.y_axis,
241 _ => panic!("index out of bounds"),
242 }
243 }
244
245 #[inline]
251 pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
252 match index {
253 0 => &mut self.x_axis,
254 1 => &mut self.y_axis,
255 _ => panic!("index out of bounds"),
256 }
257 }
258
259 #[inline]
267 #[must_use]
268 pub fn row(&self, index: usize) -> DVec2 {
269 match index {
270 0 => DVec2::new(self.x_axis.x, self.y_axis.x),
271 1 => DVec2::new(self.x_axis.y, self.y_axis.y),
272 _ => panic!("index out of bounds"),
273 }
274 }
275
276 #[inline]
286 pub fn set_row(&mut self, index: usize, row: DVec2) {
287 match index {
288 0 => {
289 self.x_axis.x = row.x;
290 self.y_axis.x = row.y;
291 }
292 1 => {
293 self.x_axis.y = row.x;
294 self.y_axis.y = row.y;
295 }
296 _ => panic!("index out of bounds"),
297 }
298 }
299
300 #[inline]
303 #[must_use]
304 pub fn is_finite(&self) -> bool {
305 self.x_axis.is_finite() && self.y_axis.is_finite()
306 }
307
308 #[inline]
310 #[must_use]
311 pub fn is_nan(&self) -> bool {
312 self.x_axis.is_nan() || self.y_axis.is_nan()
313 }
314
315 #[inline]
317 #[must_use]
318 pub fn transpose(&self) -> Self {
319 Self {
320 x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
321 y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
322 }
323 }
324
325 #[inline]
327 #[must_use]
328 pub fn diagonal(&self) -> DVec2 {
329 DVec2::new(self.x_axis.x, self.y_axis.y)
330 }
331
332 #[inline]
334 #[must_use]
335 pub fn determinant(&self) -> f64 {
336 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
337 }
338
339 #[inline(always)]
351 #[must_use]
352 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
353 let det = self.determinant();
354 if CHECKED {
355 if det == 0.0 {
356 return (Self::ZERO, false);
357 }
358 } else {
359 glam_assert!(det != 0.0);
360 }
361 let inv_det = 1.0 / det;
362 (
363 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 true,
370 )
371 }
372
373 #[inline]
381 #[must_use]
382 pub fn inverse(&self) -> Self {
383 self.inverse_checked::<false>().0
384 }
385
386 #[inline]
388 #[must_use]
389 pub fn try_inverse(&self) -> Option<Self> {
390 let (m, is_valid) = self.inverse_checked::<true>();
391 if is_valid {
392 Some(m)
393 } else {
394 None
395 }
396 }
397
398 #[inline]
400 #[must_use]
401 pub fn inverse_or_zero(&self) -> Self {
402 self.inverse_checked::<true>().0
403 }
404
405 #[inline]
407 #[must_use]
408 pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
409 #[allow(clippy::suspicious_operation_groupings)]
410 DVec2::new(
411 (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
412 (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
413 )
414 }
415
416 #[inline]
418 #[must_use]
419 pub fn mul_transpose_vec2(&self, rhs: DVec2) -> DVec2 {
420 DVec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
421 }
422
423 #[inline]
425 #[must_use]
426 pub fn mul_mat2(&self, rhs: &Self) -> Self {
427 self.mul(rhs)
428 }
429
430 #[inline]
432 #[must_use]
433 pub fn add_mat2(&self, rhs: &Self) -> Self {
434 self.add(rhs)
435 }
436
437 #[inline]
439 #[must_use]
440 pub fn sub_mat2(&self, rhs: &Self) -> Self {
441 self.sub(rhs)
442 }
443
444 #[inline]
446 #[must_use]
447 pub fn mul_scalar(&self, rhs: f64) -> Self {
448 Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
449 }
450
451 #[inline]
455 #[must_use]
456 pub fn mul_diagonal_scale(&self, scale: DVec2) -> Self {
457 Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
458 }
459
460 #[inline]
462 #[must_use]
463 pub fn div_scalar(&self, rhs: f64) -> Self {
464 let rhs = DVec2::splat(rhs);
465 Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
466 }
467
468 #[inline]
470 #[must_use]
471 pub fn recip(&self) -> Self {
472 Self::from_cols(self.x_axis.recip(), self.y_axis.recip())
473 }
474
475 #[inline]
485 #[must_use]
486 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
487 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
488 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
489 }
490
491 #[inline]
493 #[must_use]
494 pub fn abs(&self) -> Self {
495 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
496 }
497
498 #[cfg(feature = "f64")]
499 #[inline]
500 #[must_use]
501 pub fn as_mat2(&self) -> Mat2 {
502 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
503 }
504}
505
506impl Default for DMat2 {
507 #[inline]
508 fn default() -> Self {
509 Self::IDENTITY
510 }
511}
512
513impl Add for DMat2 {
514 type Output = Self;
515 #[inline]
516 fn add(self, rhs: Self) -> Self {
517 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
518 }
519}
520
521impl Add<&Self> for DMat2 {
522 type Output = Self;
523 #[inline]
524 fn add(self, rhs: &Self) -> Self {
525 self.add(*rhs)
526 }
527}
528
529impl Add<&DMat2> for &DMat2 {
530 type Output = DMat2;
531 #[inline]
532 fn add(self, rhs: &DMat2) -> DMat2 {
533 (*self).add(*rhs)
534 }
535}
536
537impl Add<DMat2> for &DMat2 {
538 type Output = DMat2;
539 #[inline]
540 fn add(self, rhs: DMat2) -> DMat2 {
541 (*self).add(rhs)
542 }
543}
544
545impl AddAssign for DMat2 {
546 #[inline]
547 fn add_assign(&mut self, rhs: Self) {
548 *self = self.add(rhs);
549 }
550}
551
552impl AddAssign<&Self> for DMat2 {
553 #[inline]
554 fn add_assign(&mut self, rhs: &Self) {
555 self.add_assign(*rhs);
556 }
557}
558
559impl Sub for DMat2 {
560 type Output = Self;
561 #[inline]
562 fn sub(self, rhs: Self) -> Self {
563 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
564 }
565}
566
567impl Sub<&Self> for DMat2 {
568 type Output = Self;
569 #[inline]
570 fn sub(self, rhs: &Self) -> Self {
571 self.sub(*rhs)
572 }
573}
574
575impl Sub<&DMat2> for &DMat2 {
576 type Output = DMat2;
577 #[inline]
578 fn sub(self, rhs: &DMat2) -> DMat2 {
579 (*self).sub(*rhs)
580 }
581}
582
583impl Sub<DMat2> for &DMat2 {
584 type Output = DMat2;
585 #[inline]
586 fn sub(self, rhs: DMat2) -> DMat2 {
587 (*self).sub(rhs)
588 }
589}
590
591impl SubAssign for DMat2 {
592 #[inline]
593 fn sub_assign(&mut self, rhs: Self) {
594 *self = self.sub(rhs);
595 }
596}
597
598impl SubAssign<&Self> for DMat2 {
599 #[inline]
600 fn sub_assign(&mut self, rhs: &Self) {
601 self.sub_assign(*rhs);
602 }
603}
604
605impl Neg for DMat2 {
606 type Output = Self;
607 #[inline]
608 fn neg(self) -> Self::Output {
609 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
610 }
611}
612
613impl Neg for &DMat2 {
614 type Output = DMat2;
615 #[inline]
616 fn neg(self) -> DMat2 {
617 (*self).neg()
618 }
619}
620
621impl Mul for DMat2 {
622 type Output = Self;
623 #[inline]
624 fn mul(self, rhs: Self) -> Self {
625 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
626 }
627}
628
629impl Mul<&Self> for DMat2 {
630 type Output = Self;
631 #[inline]
632 fn mul(self, rhs: &Self) -> Self {
633 self.mul(*rhs)
634 }
635}
636
637impl Mul<&DMat2> for &DMat2 {
638 type Output = DMat2;
639 #[inline]
640 fn mul(self, rhs: &DMat2) -> DMat2 {
641 (*self).mul(*rhs)
642 }
643}
644
645impl Mul<DMat2> for &DMat2 {
646 type Output = DMat2;
647 #[inline]
648 fn mul(self, rhs: DMat2) -> DMat2 {
649 (*self).mul(rhs)
650 }
651}
652
653impl MulAssign for DMat2 {
654 #[inline]
655 fn mul_assign(&mut self, rhs: Self) {
656 *self = self.mul(rhs);
657 }
658}
659
660impl MulAssign<&Self> for DMat2 {
661 #[inline]
662 fn mul_assign(&mut self, rhs: &Self) {
663 self.mul_assign(*rhs);
664 }
665}
666
667impl Mul<DVec2> for DMat2 {
668 type Output = DVec2;
669 #[inline]
670 fn mul(self, rhs: DVec2) -> Self::Output {
671 self.mul_vec2(rhs)
672 }
673}
674
675impl Mul<&DVec2> for DMat2 {
676 type Output = DVec2;
677 #[inline]
678 fn mul(self, rhs: &DVec2) -> DVec2 {
679 self.mul(*rhs)
680 }
681}
682
683impl Mul<&DVec2> for &DMat2 {
684 type Output = DVec2;
685 #[inline]
686 fn mul(self, rhs: &DVec2) -> DVec2 {
687 (*self).mul(*rhs)
688 }
689}
690
691impl Mul<DVec2> for &DMat2 {
692 type Output = DVec2;
693 #[inline]
694 fn mul(self, rhs: DVec2) -> DVec2 {
695 (*self).mul(rhs)
696 }
697}
698
699impl Mul<DMat2> for f64 {
700 type Output = DMat2;
701 #[inline]
702 fn mul(self, rhs: DMat2) -> Self::Output {
703 rhs.mul_scalar(self)
704 }
705}
706
707impl Mul<&DMat2> for f64 {
708 type Output = DMat2;
709 #[inline]
710 fn mul(self, rhs: &DMat2) -> DMat2 {
711 self.mul(*rhs)
712 }
713}
714
715impl Mul<&DMat2> for &f64 {
716 type Output = DMat2;
717 #[inline]
718 fn mul(self, rhs: &DMat2) -> DMat2 {
719 (*self).mul(*rhs)
720 }
721}
722
723impl Mul<DMat2> for &f64 {
724 type Output = DMat2;
725 #[inline]
726 fn mul(self, rhs: DMat2) -> DMat2 {
727 (*self).mul(rhs)
728 }
729}
730
731impl Mul<f64> for DMat2 {
732 type Output = Self;
733 #[inline]
734 fn mul(self, rhs: f64) -> Self {
735 self.mul_scalar(rhs)
736 }
737}
738
739impl Mul<&f64> for DMat2 {
740 type Output = Self;
741 #[inline]
742 fn mul(self, rhs: &f64) -> Self {
743 self.mul(*rhs)
744 }
745}
746
747impl Mul<&f64> for &DMat2 {
748 type Output = DMat2;
749 #[inline]
750 fn mul(self, rhs: &f64) -> DMat2 {
751 (*self).mul(*rhs)
752 }
753}
754
755impl Mul<f64> for &DMat2 {
756 type Output = DMat2;
757 #[inline]
758 fn mul(self, rhs: f64) -> DMat2 {
759 (*self).mul(rhs)
760 }
761}
762
763impl MulAssign<f64> for DMat2 {
764 #[inline]
765 fn mul_assign(&mut self, rhs: f64) {
766 *self = self.mul(rhs);
767 }
768}
769
770impl MulAssign<&f64> for DMat2 {
771 #[inline]
772 fn mul_assign(&mut self, rhs: &f64) {
773 self.mul_assign(*rhs);
774 }
775}
776
777impl Div<DMat2> for f64 {
778 type Output = DMat2;
779 #[inline]
780 fn div(self, rhs: DMat2) -> Self::Output {
781 DMat2::from_cols(self.div(rhs.x_axis), self.div(rhs.y_axis))
782 }
783}
784
785impl Div<&DMat2> for f64 {
786 type Output = DMat2;
787 #[inline]
788 fn div(self, rhs: &DMat2) -> DMat2 {
789 self.div(*rhs)
790 }
791}
792
793impl Div<&DMat2> for &f64 {
794 type Output = DMat2;
795 #[inline]
796 fn div(self, rhs: &DMat2) -> DMat2 {
797 (*self).div(*rhs)
798 }
799}
800
801impl Div<DMat2> for &f64 {
802 type Output = DMat2;
803 #[inline]
804 fn div(self, rhs: DMat2) -> DMat2 {
805 (*self).div(rhs)
806 }
807}
808
809impl Div<f64> for DMat2 {
810 type Output = Self;
811 #[inline]
812 fn div(self, rhs: f64) -> Self {
813 self.div_scalar(rhs)
814 }
815}
816
817impl Div<&f64> for DMat2 {
818 type Output = Self;
819 #[inline]
820 fn div(self, rhs: &f64) -> Self {
821 self.div(*rhs)
822 }
823}
824
825impl Div<&f64> for &DMat2 {
826 type Output = DMat2;
827 #[inline]
828 fn div(self, rhs: &f64) -> DMat2 {
829 (*self).div(*rhs)
830 }
831}
832
833impl Div<f64> for &DMat2 {
834 type Output = DMat2;
835 #[inline]
836 fn div(self, rhs: f64) -> DMat2 {
837 (*self).div(rhs)
838 }
839}
840
841impl DivAssign<f64> for DMat2 {
842 #[inline]
843 fn div_assign(&mut self, rhs: f64) {
844 *self = self.div(rhs);
845 }
846}
847
848impl DivAssign<&f64> for DMat2 {
849 #[inline]
850 fn div_assign(&mut self, rhs: &f64) {
851 self.div_assign(*rhs);
852 }
853}
854
855impl Sum<Self> for DMat2 {
856 fn sum<I>(iter: I) -> Self
857 where
858 I: Iterator<Item = Self>,
859 {
860 iter.fold(Self::ZERO, Self::add)
861 }
862}
863
864impl<'a> Sum<&'a Self> for DMat2 {
865 fn sum<I>(iter: I) -> Self
866 where
867 I: Iterator<Item = &'a Self>,
868 {
869 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
870 }
871}
872
873impl Product for DMat2 {
874 fn product<I>(iter: I) -> Self
875 where
876 I: Iterator<Item = Self>,
877 {
878 iter.fold(Self::IDENTITY, Self::mul)
879 }
880}
881
882impl<'a> Product<&'a Self> for DMat2 {
883 fn product<I>(iter: I) -> Self
884 where
885 I: Iterator<Item = &'a Self>,
886 {
887 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
888 }
889}
890
891impl PartialEq for DMat2 {
892 #[inline]
893 fn eq(&self, rhs: &Self) -> bool {
894 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
895 }
896}
897
898impl AsRef<[f64; 4]> for DMat2 {
899 #[inline]
900 fn as_ref(&self) -> &[f64; 4] {
901 unsafe { &*(self as *const Self as *const [f64; 4]) }
902 }
903}
904
905impl AsMut<[f64; 4]> for DMat2 {
906 #[inline]
907 fn as_mut(&mut self) -> &mut [f64; 4] {
908 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
909 }
910}
911
912impl fmt::Debug for DMat2 {
913 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
914 fmt.debug_struct(stringify!(DMat2))
915 .field("x_axis", &self.x_axis)
916 .field("y_axis", &self.y_axis)
917 .finish()
918 }
919}
920
921impl fmt::Display for DMat2 {
922 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
923 if let Some(p) = f.precision() {
924 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
925 } else {
926 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
927 }
928 }
929}