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")]
9use zerocopy_derive::*;
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",
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)]
54 #[must_use]
55 pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
56 Self { x_axis, y_axis }
57 }
58
59 #[inline]
63 #[must_use]
64 pub const fn from_cols_array(m: &[f64; 4]) -> Self {
65 Self::new(m[0], m[1], m[2], m[3])
66 }
67
68 #[inline]
71 #[must_use]
72 pub const fn to_cols_array(&self) -> [f64; 4] {
73 [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
74 }
75
76 #[inline]
80 #[must_use]
81 pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
82 Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
83 }
84
85 #[inline]
88 #[must_use]
89 pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
90 [self.x_axis.to_array(), self.y_axis.to_array()]
91 }
92
93 #[doc(alias = "scale")]
95 #[inline]
96 #[must_use]
97 pub const fn from_diagonal(diagonal: DVec2) -> Self {
98 Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
99 }
100
101 #[inline]
104 #[must_use]
105 pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
106 let (sin, cos) = math::sin_cos(angle);
107 Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
108 }
109
110 #[inline]
112 #[must_use]
113 pub fn from_angle(angle: f64) -> Self {
114 let (sin, cos) = math::sin_cos(angle);
115 Self::new(cos, sin, -sin, cos)
116 }
117
118 #[inline]
120 #[must_use]
121 pub fn from_mat3(m: DMat3) -> Self {
122 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
123 }
124
125 #[inline]
132 #[must_use]
133 pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
134 match (i, j) {
135 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
136 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
137 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
138 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
139 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
140 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
141 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
142 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
143 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
144 _ => panic!("index out of bounds"),
145 }
146 }
147
148 #[inline]
154 #[must_use]
155 pub const fn from_cols_slice(slice: &[f64]) -> Self {
156 Self::new(slice[0], slice[1], slice[2], slice[3])
157 }
158
159 #[inline]
165 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
166 slice[0] = self.x_axis.x;
167 slice[1] = self.x_axis.y;
168 slice[2] = self.y_axis.x;
169 slice[3] = self.y_axis.y;
170 }
171
172 #[inline]
178 #[must_use]
179 pub fn col(&self, index: usize) -> DVec2 {
180 match index {
181 0 => self.x_axis,
182 1 => self.y_axis,
183 _ => panic!("index out of bounds"),
184 }
185 }
186
187 #[inline]
193 pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
194 match index {
195 0 => &mut self.x_axis,
196 1 => &mut self.y_axis,
197 _ => panic!("index out of bounds"),
198 }
199 }
200
201 #[inline]
207 #[must_use]
208 pub fn row(&self, index: usize) -> DVec2 {
209 match index {
210 0 => DVec2::new(self.x_axis.x, self.y_axis.x),
211 1 => DVec2::new(self.x_axis.y, self.y_axis.y),
212 _ => panic!("index out of bounds"),
213 }
214 }
215
216 #[inline]
219 #[must_use]
220 pub fn is_finite(&self) -> bool {
221 self.x_axis.is_finite() && self.y_axis.is_finite()
222 }
223
224 #[inline]
226 #[must_use]
227 pub fn is_nan(&self) -> bool {
228 self.x_axis.is_nan() || self.y_axis.is_nan()
229 }
230
231 #[inline]
233 #[must_use]
234 pub fn transpose(&self) -> Self {
235 Self {
236 x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
237 y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
238 }
239 }
240
241 #[inline]
243 #[must_use]
244 pub fn diagonal(&self) -> DVec2 {
245 DVec2::new(self.x_axis.x, self.y_axis.y)
246 }
247
248 #[inline]
250 #[must_use]
251 pub fn determinant(&self) -> f64 {
252 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
253 }
254
255 #[inline(always)]
267 #[must_use]
268 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
269 let det = self.determinant();
270 if CHECKED {
271 if det == 0.0 {
272 return (Self::ZERO, false);
273 }
274 } else {
275 glam_assert!(det != 0.0);
276 }
277 let inv_det = det.recip();
278 (
279 Self::new(
280 self.y_axis.y * inv_det,
281 self.x_axis.y * -inv_det,
282 self.y_axis.x * -inv_det,
283 self.x_axis.x * inv_det,
284 ),
285 true,
286 )
287 }
288
289 #[inline]
297 #[must_use]
298 pub fn inverse(&self) -> Self {
299 self.inverse_checked::<false>().0
300 }
301
302 #[inline]
304 #[must_use]
305 pub fn try_inverse(&self) -> Option<Self> {
306 let (m, is_valid) = self.inverse_checked::<true>();
307 if is_valid {
308 Some(m)
309 } else {
310 None
311 }
312 }
313
314 #[inline]
316 #[must_use]
317 pub fn inverse_or_zero(&self) -> Self {
318 self.inverse_checked::<true>().0
319 }
320
321 #[inline]
323 #[must_use]
324 pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
325 #[allow(clippy::suspicious_operation_groupings)]
326 DVec2::new(
327 (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
328 (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
329 )
330 }
331
332 #[inline]
334 #[must_use]
335 pub fn mul_transpose_vec2(&self, rhs: DVec2) -> DVec2 {
336 DVec2::new(self.x_axis.dot(rhs), self.y_axis.dot(rhs))
337 }
338
339 #[inline]
341 #[must_use]
342 pub fn mul_mat2(&self, rhs: &Self) -> Self {
343 self.mul(rhs)
344 }
345
346 #[inline]
348 #[must_use]
349 pub fn add_mat2(&self, rhs: &Self) -> Self {
350 self.add(rhs)
351 }
352
353 #[inline]
355 #[must_use]
356 pub fn sub_mat2(&self, rhs: &Self) -> Self {
357 self.sub(rhs)
358 }
359
360 #[inline]
362 #[must_use]
363 pub fn mul_scalar(&self, rhs: f64) -> Self {
364 Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
365 }
366
367 #[inline]
371 #[must_use]
372 pub fn mul_diagonal_scale(&self, scale: DVec2) -> Self {
373 Self::from_cols(self.x_axis * scale.x, self.y_axis * scale.y)
374 }
375
376 #[inline]
378 #[must_use]
379 pub fn div_scalar(&self, rhs: f64) -> Self {
380 let rhs = DVec2::splat(rhs);
381 Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
382 }
383
384 #[inline]
386 #[must_use]
387 pub fn recip(&self) -> Self {
388 Self::from_cols(self.x_axis.recip(), self.y_axis.recip())
389 }
390
391 #[inline]
401 #[must_use]
402 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
403 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
404 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
405 }
406
407 #[inline]
409 #[must_use]
410 pub fn abs(&self) -> Self {
411 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
412 }
413
414 #[inline]
415 pub fn as_mat2(&self) -> Mat2 {
416 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
417 }
418}
419
420impl Default for DMat2 {
421 #[inline]
422 fn default() -> Self {
423 Self::IDENTITY
424 }
425}
426
427impl Add for DMat2 {
428 type Output = Self;
429 #[inline]
430 fn add(self, rhs: Self) -> Self {
431 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
432 }
433}
434
435impl Add<&Self> for DMat2 {
436 type Output = Self;
437 #[inline]
438 fn add(self, rhs: &Self) -> Self {
439 self.add(*rhs)
440 }
441}
442
443impl Add<&DMat2> for &DMat2 {
444 type Output = DMat2;
445 #[inline]
446 fn add(self, rhs: &DMat2) -> DMat2 {
447 (*self).add(*rhs)
448 }
449}
450
451impl Add<DMat2> for &DMat2 {
452 type Output = DMat2;
453 #[inline]
454 fn add(self, rhs: DMat2) -> DMat2 {
455 (*self).add(rhs)
456 }
457}
458
459impl AddAssign for DMat2 {
460 #[inline]
461 fn add_assign(&mut self, rhs: Self) {
462 *self = self.add(rhs);
463 }
464}
465
466impl AddAssign<&Self> for DMat2 {
467 #[inline]
468 fn add_assign(&mut self, rhs: &Self) {
469 self.add_assign(*rhs);
470 }
471}
472
473impl Sub for DMat2 {
474 type Output = Self;
475 #[inline]
476 fn sub(self, rhs: Self) -> Self {
477 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
478 }
479}
480
481impl Sub<&Self> for DMat2 {
482 type Output = Self;
483 #[inline]
484 fn sub(self, rhs: &Self) -> Self {
485 self.sub(*rhs)
486 }
487}
488
489impl Sub<&DMat2> for &DMat2 {
490 type Output = DMat2;
491 #[inline]
492 fn sub(self, rhs: &DMat2) -> DMat2 {
493 (*self).sub(*rhs)
494 }
495}
496
497impl Sub<DMat2> for &DMat2 {
498 type Output = DMat2;
499 #[inline]
500 fn sub(self, rhs: DMat2) -> DMat2 {
501 (*self).sub(rhs)
502 }
503}
504
505impl SubAssign for DMat2 {
506 #[inline]
507 fn sub_assign(&mut self, rhs: Self) {
508 *self = self.sub(rhs);
509 }
510}
511
512impl SubAssign<&Self> for DMat2 {
513 #[inline]
514 fn sub_assign(&mut self, rhs: &Self) {
515 self.sub_assign(*rhs);
516 }
517}
518
519impl Neg for DMat2 {
520 type Output = Self;
521 #[inline]
522 fn neg(self) -> Self::Output {
523 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
524 }
525}
526
527impl Neg for &DMat2 {
528 type Output = DMat2;
529 #[inline]
530 fn neg(self) -> DMat2 {
531 (*self).neg()
532 }
533}
534
535impl Mul for DMat2 {
536 type Output = Self;
537 #[inline]
538 fn mul(self, rhs: Self) -> Self {
539 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
540 }
541}
542
543impl Mul<&Self> for DMat2 {
544 type Output = Self;
545 #[inline]
546 fn mul(self, rhs: &Self) -> Self {
547 self.mul(*rhs)
548 }
549}
550
551impl Mul<&DMat2> for &DMat2 {
552 type Output = DMat2;
553 #[inline]
554 fn mul(self, rhs: &DMat2) -> DMat2 {
555 (*self).mul(*rhs)
556 }
557}
558
559impl Mul<DMat2> for &DMat2 {
560 type Output = DMat2;
561 #[inline]
562 fn mul(self, rhs: DMat2) -> DMat2 {
563 (*self).mul(rhs)
564 }
565}
566
567impl MulAssign for DMat2 {
568 #[inline]
569 fn mul_assign(&mut self, rhs: Self) {
570 *self = self.mul(rhs);
571 }
572}
573
574impl MulAssign<&Self> for DMat2 {
575 #[inline]
576 fn mul_assign(&mut self, rhs: &Self) {
577 self.mul_assign(*rhs);
578 }
579}
580
581impl Mul<DVec2> for DMat2 {
582 type Output = DVec2;
583 #[inline]
584 fn mul(self, rhs: DVec2) -> Self::Output {
585 self.mul_vec2(rhs)
586 }
587}
588
589impl Mul<&DVec2> for DMat2 {
590 type Output = DVec2;
591 #[inline]
592 fn mul(self, rhs: &DVec2) -> DVec2 {
593 self.mul(*rhs)
594 }
595}
596
597impl Mul<&DVec2> for &DMat2 {
598 type Output = DVec2;
599 #[inline]
600 fn mul(self, rhs: &DVec2) -> DVec2 {
601 (*self).mul(*rhs)
602 }
603}
604
605impl Mul<DVec2> for &DMat2 {
606 type Output = DVec2;
607 #[inline]
608 fn mul(self, rhs: DVec2) -> DVec2 {
609 (*self).mul(rhs)
610 }
611}
612
613impl Mul<DMat2> for f64 {
614 type Output = DMat2;
615 #[inline]
616 fn mul(self, rhs: DMat2) -> Self::Output {
617 rhs.mul_scalar(self)
618 }
619}
620
621impl Mul<&DMat2> for f64 {
622 type Output = DMat2;
623 #[inline]
624 fn mul(self, rhs: &DMat2) -> DMat2 {
625 self.mul(*rhs)
626 }
627}
628
629impl Mul<&DMat2> for &f64 {
630 type Output = DMat2;
631 #[inline]
632 fn mul(self, rhs: &DMat2) -> DMat2 {
633 (*self).mul(*rhs)
634 }
635}
636
637impl Mul<DMat2> for &f64 {
638 type Output = DMat2;
639 #[inline]
640 fn mul(self, rhs: DMat2) -> DMat2 {
641 (*self).mul(rhs)
642 }
643}
644
645impl Mul<f64> for DMat2 {
646 type Output = Self;
647 #[inline]
648 fn mul(self, rhs: f64) -> Self {
649 self.mul_scalar(rhs)
650 }
651}
652
653impl Mul<&f64> for DMat2 {
654 type Output = Self;
655 #[inline]
656 fn mul(self, rhs: &f64) -> Self {
657 self.mul(*rhs)
658 }
659}
660
661impl Mul<&f64> for &DMat2 {
662 type Output = DMat2;
663 #[inline]
664 fn mul(self, rhs: &f64) -> DMat2 {
665 (*self).mul(*rhs)
666 }
667}
668
669impl Mul<f64> for &DMat2 {
670 type Output = DMat2;
671 #[inline]
672 fn mul(self, rhs: f64) -> DMat2 {
673 (*self).mul(rhs)
674 }
675}
676
677impl MulAssign<f64> for DMat2 {
678 #[inline]
679 fn mul_assign(&mut self, rhs: f64) {
680 *self = self.mul(rhs);
681 }
682}
683
684impl MulAssign<&f64> for DMat2 {
685 #[inline]
686 fn mul_assign(&mut self, rhs: &f64) {
687 self.mul_assign(*rhs);
688 }
689}
690
691impl Div<DMat2> for f64 {
692 type Output = DMat2;
693 #[inline]
694 fn div(self, rhs: DMat2) -> Self::Output {
695 DMat2::from_cols(self.div(rhs.x_axis), self.div(rhs.y_axis))
696 }
697}
698
699impl Div<&DMat2> for f64 {
700 type Output = DMat2;
701 #[inline]
702 fn div(self, rhs: &DMat2) -> DMat2 {
703 self.div(*rhs)
704 }
705}
706
707impl Div<&DMat2> for &f64 {
708 type Output = DMat2;
709 #[inline]
710 fn div(self, rhs: &DMat2) -> DMat2 {
711 (*self).div(*rhs)
712 }
713}
714
715impl Div<DMat2> for &f64 {
716 type Output = DMat2;
717 #[inline]
718 fn div(self, rhs: DMat2) -> DMat2 {
719 (*self).div(rhs)
720 }
721}
722
723impl Div<f64> for DMat2 {
724 type Output = Self;
725 #[inline]
726 fn div(self, rhs: f64) -> Self {
727 self.div_scalar(rhs)
728 }
729}
730
731impl Div<&f64> for DMat2 {
732 type Output = Self;
733 #[inline]
734 fn div(self, rhs: &f64) -> Self {
735 self.div(*rhs)
736 }
737}
738
739impl Div<&f64> for &DMat2 {
740 type Output = DMat2;
741 #[inline]
742 fn div(self, rhs: &f64) -> DMat2 {
743 (*self).div(*rhs)
744 }
745}
746
747impl Div<f64> for &DMat2 {
748 type Output = DMat2;
749 #[inline]
750 fn div(self, rhs: f64) -> DMat2 {
751 (*self).div(rhs)
752 }
753}
754
755impl DivAssign<f64> for DMat2 {
756 #[inline]
757 fn div_assign(&mut self, rhs: f64) {
758 *self = self.div(rhs);
759 }
760}
761
762impl DivAssign<&f64> for DMat2 {
763 #[inline]
764 fn div_assign(&mut self, rhs: &f64) {
765 self.div_assign(*rhs);
766 }
767}
768
769impl Sum<Self> for DMat2 {
770 fn sum<I>(iter: I) -> Self
771 where
772 I: Iterator<Item = Self>,
773 {
774 iter.fold(Self::ZERO, Self::add)
775 }
776}
777
778impl<'a> Sum<&'a Self> for DMat2 {
779 fn sum<I>(iter: I) -> Self
780 where
781 I: Iterator<Item = &'a Self>,
782 {
783 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
784 }
785}
786
787impl Product for DMat2 {
788 fn product<I>(iter: I) -> Self
789 where
790 I: Iterator<Item = Self>,
791 {
792 iter.fold(Self::IDENTITY, Self::mul)
793 }
794}
795
796impl<'a> Product<&'a Self> for DMat2 {
797 fn product<I>(iter: I) -> Self
798 where
799 I: Iterator<Item = &'a Self>,
800 {
801 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
802 }
803}
804
805impl PartialEq for DMat2 {
806 #[inline]
807 fn eq(&self, rhs: &Self) -> bool {
808 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
809 }
810}
811
812impl AsRef<[f64; 4]> for DMat2 {
813 #[inline]
814 fn as_ref(&self) -> &[f64; 4] {
815 unsafe { &*(self as *const Self as *const [f64; 4]) }
816 }
817}
818
819impl AsMut<[f64; 4]> for DMat2 {
820 #[inline]
821 fn as_mut(&mut self) -> &mut [f64; 4] {
822 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
823 }
824}
825
826impl fmt::Debug for DMat2 {
827 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
828 fmt.debug_struct(stringify!(DMat2))
829 .field("x_axis", &self.x_axis)
830 .field("y_axis", &self.y_axis)
831 .finish()
832 }
833}
834
835impl fmt::Display for DMat2 {
836 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
837 if let Some(p) = f.precision() {
838 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
839 } else {
840 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
841 }
842 }
843}