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