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]
394 #[must_use]
395 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
396 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
397 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
398 }
399
400 #[inline]
402 #[must_use]
403 pub fn abs(&self) -> Self {
404 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
405 }
406
407 #[inline]
408 pub fn as_mat2(&self) -> Mat2 {
409 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
410 }
411}
412
413impl Default for DMat2 {
414 #[inline]
415 fn default() -> Self {
416 Self::IDENTITY
417 }
418}
419
420impl Add for DMat2 {
421 type Output = Self;
422 #[inline]
423 fn add(self, rhs: Self) -> Self {
424 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
425 }
426}
427
428impl Add<&Self> for DMat2 {
429 type Output = Self;
430 #[inline]
431 fn add(self, rhs: &Self) -> Self {
432 self.add(*rhs)
433 }
434}
435
436impl Add<&DMat2> for &DMat2 {
437 type Output = DMat2;
438 #[inline]
439 fn add(self, rhs: &DMat2) -> DMat2 {
440 (*self).add(*rhs)
441 }
442}
443
444impl Add<DMat2> for &DMat2 {
445 type Output = DMat2;
446 #[inline]
447 fn add(self, rhs: DMat2) -> DMat2 {
448 (*self).add(rhs)
449 }
450}
451
452impl AddAssign for DMat2 {
453 #[inline]
454 fn add_assign(&mut self, rhs: Self) {
455 *self = self.add(rhs);
456 }
457}
458
459impl AddAssign<&Self> for DMat2 {
460 #[inline]
461 fn add_assign(&mut self, rhs: &Self) {
462 self.add_assign(*rhs);
463 }
464}
465
466impl Sub for DMat2 {
467 type Output = Self;
468 #[inline]
469 fn sub(self, rhs: Self) -> Self {
470 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
471 }
472}
473
474impl Sub<&Self> for DMat2 {
475 type Output = Self;
476 #[inline]
477 fn sub(self, rhs: &Self) -> Self {
478 self.sub(*rhs)
479 }
480}
481
482impl Sub<&DMat2> for &DMat2 {
483 type Output = DMat2;
484 #[inline]
485 fn sub(self, rhs: &DMat2) -> DMat2 {
486 (*self).sub(*rhs)
487 }
488}
489
490impl Sub<DMat2> for &DMat2 {
491 type Output = DMat2;
492 #[inline]
493 fn sub(self, rhs: DMat2) -> DMat2 {
494 (*self).sub(rhs)
495 }
496}
497
498impl SubAssign for DMat2 {
499 #[inline]
500 fn sub_assign(&mut self, rhs: Self) {
501 *self = self.sub(rhs);
502 }
503}
504
505impl SubAssign<&Self> for DMat2 {
506 #[inline]
507 fn sub_assign(&mut self, rhs: &Self) {
508 self.sub_assign(*rhs);
509 }
510}
511
512impl Neg for DMat2 {
513 type Output = Self;
514 #[inline]
515 fn neg(self) -> Self::Output {
516 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
517 }
518}
519
520impl Neg for &DMat2 {
521 type Output = DMat2;
522 #[inline]
523 fn neg(self) -> DMat2 {
524 (*self).neg()
525 }
526}
527
528impl Mul for DMat2 {
529 type Output = Self;
530 #[inline]
531 fn mul(self, rhs: Self) -> Self {
532 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
533 }
534}
535
536impl Mul<&Self> for DMat2 {
537 type Output = Self;
538 #[inline]
539 fn mul(self, rhs: &Self) -> Self {
540 self.mul(*rhs)
541 }
542}
543
544impl Mul<&DMat2> for &DMat2 {
545 type Output = DMat2;
546 #[inline]
547 fn mul(self, rhs: &DMat2) -> DMat2 {
548 (*self).mul(*rhs)
549 }
550}
551
552impl Mul<DMat2> for &DMat2 {
553 type Output = DMat2;
554 #[inline]
555 fn mul(self, rhs: DMat2) -> DMat2 {
556 (*self).mul(rhs)
557 }
558}
559
560impl MulAssign for DMat2 {
561 #[inline]
562 fn mul_assign(&mut self, rhs: Self) {
563 *self = self.mul(rhs);
564 }
565}
566
567impl MulAssign<&Self> for DMat2 {
568 #[inline]
569 fn mul_assign(&mut self, rhs: &Self) {
570 self.mul_assign(*rhs);
571 }
572}
573
574impl Mul<DVec2> for DMat2 {
575 type Output = DVec2;
576 #[inline]
577 fn mul(self, rhs: DVec2) -> Self::Output {
578 self.mul_vec2(rhs)
579 }
580}
581
582impl Mul<&DVec2> for DMat2 {
583 type Output = DVec2;
584 #[inline]
585 fn mul(self, rhs: &DVec2) -> DVec2 {
586 self.mul(*rhs)
587 }
588}
589
590impl Mul<&DVec2> for &DMat2 {
591 type Output = DVec2;
592 #[inline]
593 fn mul(self, rhs: &DVec2) -> DVec2 {
594 (*self).mul(*rhs)
595 }
596}
597
598impl Mul<DVec2> for &DMat2 {
599 type Output = DVec2;
600 #[inline]
601 fn mul(self, rhs: DVec2) -> DVec2 {
602 (*self).mul(rhs)
603 }
604}
605
606impl Mul<DMat2> for f64 {
607 type Output = DMat2;
608 #[inline]
609 fn mul(self, rhs: DMat2) -> Self::Output {
610 rhs.mul_scalar(self)
611 }
612}
613
614impl Mul<&DMat2> for f64 {
615 type Output = DMat2;
616 #[inline]
617 fn mul(self, rhs: &DMat2) -> DMat2 {
618 self.mul(*rhs)
619 }
620}
621
622impl Mul<&DMat2> for &f64 {
623 type Output = DMat2;
624 #[inline]
625 fn mul(self, rhs: &DMat2) -> DMat2 {
626 (*self).mul(*rhs)
627 }
628}
629
630impl Mul<DMat2> for &f64 {
631 type Output = DMat2;
632 #[inline]
633 fn mul(self, rhs: DMat2) -> DMat2 {
634 (*self).mul(rhs)
635 }
636}
637
638impl Mul<f64> for DMat2 {
639 type Output = Self;
640 #[inline]
641 fn mul(self, rhs: f64) -> Self {
642 self.mul_scalar(rhs)
643 }
644}
645
646impl Mul<&f64> for DMat2 {
647 type Output = Self;
648 #[inline]
649 fn mul(self, rhs: &f64) -> Self {
650 self.mul(*rhs)
651 }
652}
653
654impl Mul<&f64> for &DMat2 {
655 type Output = DMat2;
656 #[inline]
657 fn mul(self, rhs: &f64) -> DMat2 {
658 (*self).mul(*rhs)
659 }
660}
661
662impl Mul<f64> for &DMat2 {
663 type Output = DMat2;
664 #[inline]
665 fn mul(self, rhs: f64) -> DMat2 {
666 (*self).mul(rhs)
667 }
668}
669
670impl MulAssign<f64> for DMat2 {
671 #[inline]
672 fn mul_assign(&mut self, rhs: f64) {
673 *self = self.mul(rhs);
674 }
675}
676
677impl MulAssign<&f64> for DMat2 {
678 #[inline]
679 fn mul_assign(&mut self, rhs: &f64) {
680 self.mul_assign(*rhs);
681 }
682}
683
684impl Div<DMat2> for f64 {
685 type Output = DMat2;
686 #[inline]
687 fn div(self, rhs: DMat2) -> Self::Output {
688 rhs.div_scalar(self)
689 }
690}
691
692impl Div<&DMat2> for f64 {
693 type Output = DMat2;
694 #[inline]
695 fn div(self, rhs: &DMat2) -> DMat2 {
696 self.div(*rhs)
697 }
698}
699
700impl Div<&DMat2> for &f64 {
701 type Output = DMat2;
702 #[inline]
703 fn div(self, rhs: &DMat2) -> DMat2 {
704 (*self).div(*rhs)
705 }
706}
707
708impl Div<DMat2> for &f64 {
709 type Output = DMat2;
710 #[inline]
711 fn div(self, rhs: DMat2) -> DMat2 {
712 (*self).div(rhs)
713 }
714}
715
716impl Div<f64> for DMat2 {
717 type Output = Self;
718 #[inline]
719 fn div(self, rhs: f64) -> Self {
720 self.div_scalar(rhs)
721 }
722}
723
724impl Div<&f64> for DMat2 {
725 type Output = Self;
726 #[inline]
727 fn div(self, rhs: &f64) -> Self {
728 self.div(*rhs)
729 }
730}
731
732impl Div<&f64> for &DMat2 {
733 type Output = DMat2;
734 #[inline]
735 fn div(self, rhs: &f64) -> DMat2 {
736 (*self).div(*rhs)
737 }
738}
739
740impl Div<f64> for &DMat2 {
741 type Output = DMat2;
742 #[inline]
743 fn div(self, rhs: f64) -> DMat2 {
744 (*self).div(rhs)
745 }
746}
747
748impl DivAssign<f64> for DMat2 {
749 #[inline]
750 fn div_assign(&mut self, rhs: f64) {
751 *self = self.div(rhs);
752 }
753}
754
755impl DivAssign<&f64> for DMat2 {
756 #[inline]
757 fn div_assign(&mut self, rhs: &f64) {
758 self.div_assign(*rhs);
759 }
760}
761
762impl Sum<Self> for DMat2 {
763 fn sum<I>(iter: I) -> Self
764 where
765 I: Iterator<Item = Self>,
766 {
767 iter.fold(Self::ZERO, Self::add)
768 }
769}
770
771impl<'a> Sum<&'a Self> for DMat2 {
772 fn sum<I>(iter: I) -> Self
773 where
774 I: Iterator<Item = &'a Self>,
775 {
776 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
777 }
778}
779
780impl Product for DMat2 {
781 fn product<I>(iter: I) -> Self
782 where
783 I: Iterator<Item = Self>,
784 {
785 iter.fold(Self::IDENTITY, Self::mul)
786 }
787}
788
789impl<'a> Product<&'a Self> for DMat2 {
790 fn product<I>(iter: I) -> Self
791 where
792 I: Iterator<Item = &'a Self>,
793 {
794 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
795 }
796}
797
798impl PartialEq for DMat2 {
799 #[inline]
800 fn eq(&self, rhs: &Self) -> bool {
801 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
802 }
803}
804
805impl AsRef<[f64; 4]> for DMat2 {
806 #[inline]
807 fn as_ref(&self) -> &[f64; 4] {
808 unsafe { &*(self as *const Self as *const [f64; 4]) }
809 }
810}
811
812impl AsMut<[f64; 4]> for DMat2 {
813 #[inline]
814 fn as_mut(&mut self) -> &mut [f64; 4] {
815 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
816 }
817}
818
819impl fmt::Debug for DMat2 {
820 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
821 fmt.debug_struct(stringify!(DMat2))
822 .field("x_axis", &self.x_axis)
823 .field("y_axis", &self.y_axis)
824 .finish()
825 }
826}
827
828impl fmt::Display for DMat2 {
829 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830 if let Some(p) = f.precision() {
831 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
832 } else {
833 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
834 }
835 }
836}