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 determinant(&self) -> f64 {
245 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
246 }
247
248 #[inline]
256 #[must_use]
257 pub fn inverse(&self) -> Self {
258 let inv_det = {
259 let det = self.determinant();
260 glam_assert!(det != 0.0);
261 det.recip()
262 };
263 Self::new(
264 self.y_axis.y * inv_det,
265 self.x_axis.y * -inv_det,
266 self.y_axis.x * -inv_det,
267 self.x_axis.x * inv_det,
268 )
269 }
270
271 #[inline]
273 #[must_use]
274 pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
275 #[allow(clippy::suspicious_operation_groupings)]
276 DVec2::new(
277 (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
278 (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
279 )
280 }
281
282 #[inline]
284 #[must_use]
285 pub fn mul_mat2(&self, rhs: &Self) -> Self {
286 self.mul(rhs)
287 }
288
289 #[inline]
291 #[must_use]
292 pub fn add_mat2(&self, rhs: &Self) -> Self {
293 self.add(rhs)
294 }
295
296 #[inline]
298 #[must_use]
299 pub fn sub_mat2(&self, rhs: &Self) -> Self {
300 self.sub(rhs)
301 }
302
303 #[inline]
305 #[must_use]
306 pub fn mul_scalar(&self, rhs: f64) -> Self {
307 Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
308 }
309
310 #[inline]
312 #[must_use]
313 pub fn div_scalar(&self, rhs: f64) -> Self {
314 let rhs = DVec2::splat(rhs);
315 Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
316 }
317
318 #[inline]
328 #[must_use]
329 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
330 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
331 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
332 }
333
334 #[inline]
336 #[must_use]
337 pub fn abs(&self) -> Self {
338 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
339 }
340
341 #[inline]
342 pub fn as_mat2(&self) -> Mat2 {
343 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
344 }
345}
346
347impl Default for DMat2 {
348 #[inline]
349 fn default() -> Self {
350 Self::IDENTITY
351 }
352}
353
354impl Add for DMat2 {
355 type Output = Self;
356 #[inline]
357 fn add(self, rhs: Self) -> Self {
358 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
359 }
360}
361
362impl Add<&Self> for DMat2 {
363 type Output = Self;
364 #[inline]
365 fn add(self, rhs: &Self) -> Self {
366 self.add(*rhs)
367 }
368}
369
370impl Add<&DMat2> for &DMat2 {
371 type Output = DMat2;
372 #[inline]
373 fn add(self, rhs: &DMat2) -> DMat2 {
374 (*self).add(*rhs)
375 }
376}
377
378impl Add<DMat2> for &DMat2 {
379 type Output = DMat2;
380 #[inline]
381 fn add(self, rhs: DMat2) -> DMat2 {
382 (*self).add(rhs)
383 }
384}
385
386impl AddAssign for DMat2 {
387 #[inline]
388 fn add_assign(&mut self, rhs: Self) {
389 *self = self.add(rhs);
390 }
391}
392
393impl AddAssign<&Self> for DMat2 {
394 #[inline]
395 fn add_assign(&mut self, rhs: &Self) {
396 self.add_assign(*rhs);
397 }
398}
399
400impl Sub for DMat2 {
401 type Output = Self;
402 #[inline]
403 fn sub(self, rhs: Self) -> Self {
404 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
405 }
406}
407
408impl Sub<&Self> for DMat2 {
409 type Output = Self;
410 #[inline]
411 fn sub(self, rhs: &Self) -> Self {
412 self.sub(*rhs)
413 }
414}
415
416impl Sub<&DMat2> for &DMat2 {
417 type Output = DMat2;
418 #[inline]
419 fn sub(self, rhs: &DMat2) -> DMat2 {
420 (*self).sub(*rhs)
421 }
422}
423
424impl Sub<DMat2> for &DMat2 {
425 type Output = DMat2;
426 #[inline]
427 fn sub(self, rhs: DMat2) -> DMat2 {
428 (*self).sub(rhs)
429 }
430}
431
432impl SubAssign for DMat2 {
433 #[inline]
434 fn sub_assign(&mut self, rhs: Self) {
435 *self = self.sub(rhs);
436 }
437}
438
439impl SubAssign<&Self> for DMat2 {
440 #[inline]
441 fn sub_assign(&mut self, rhs: &Self) {
442 self.sub_assign(*rhs);
443 }
444}
445
446impl Neg for DMat2 {
447 type Output = Self;
448 #[inline]
449 fn neg(self) -> Self::Output {
450 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
451 }
452}
453
454impl Neg for &DMat2 {
455 type Output = DMat2;
456 #[inline]
457 fn neg(self) -> DMat2 {
458 (*self).neg()
459 }
460}
461
462impl Mul for DMat2 {
463 type Output = Self;
464 #[inline]
465 fn mul(self, rhs: Self) -> Self {
466 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
467 }
468}
469
470impl Mul<&Self> for DMat2 {
471 type Output = Self;
472 #[inline]
473 fn mul(self, rhs: &Self) -> Self {
474 self.mul(*rhs)
475 }
476}
477
478impl Mul<&DMat2> for &DMat2 {
479 type Output = DMat2;
480 #[inline]
481 fn mul(self, rhs: &DMat2) -> DMat2 {
482 (*self).mul(*rhs)
483 }
484}
485
486impl Mul<DMat2> for &DMat2 {
487 type Output = DMat2;
488 #[inline]
489 fn mul(self, rhs: DMat2) -> DMat2 {
490 (*self).mul(rhs)
491 }
492}
493
494impl MulAssign for DMat2 {
495 #[inline]
496 fn mul_assign(&mut self, rhs: Self) {
497 *self = self.mul(rhs);
498 }
499}
500
501impl MulAssign<&Self> for DMat2 {
502 #[inline]
503 fn mul_assign(&mut self, rhs: &Self) {
504 self.mul_assign(*rhs);
505 }
506}
507
508impl Mul<DVec2> for DMat2 {
509 type Output = DVec2;
510 #[inline]
511 fn mul(self, rhs: DVec2) -> Self::Output {
512 self.mul_vec2(rhs)
513 }
514}
515
516impl Mul<&DVec2> for DMat2 {
517 type Output = DVec2;
518 #[inline]
519 fn mul(self, rhs: &DVec2) -> DVec2 {
520 self.mul(*rhs)
521 }
522}
523
524impl Mul<&DVec2> for &DMat2 {
525 type Output = DVec2;
526 #[inline]
527 fn mul(self, rhs: &DVec2) -> DVec2 {
528 (*self).mul(*rhs)
529 }
530}
531
532impl Mul<DVec2> for &DMat2 {
533 type Output = DVec2;
534 #[inline]
535 fn mul(self, rhs: DVec2) -> DVec2 {
536 (*self).mul(rhs)
537 }
538}
539
540impl Mul<DMat2> for f64 {
541 type Output = DMat2;
542 #[inline]
543 fn mul(self, rhs: DMat2) -> Self::Output {
544 rhs.mul_scalar(self)
545 }
546}
547
548impl Mul<&DMat2> for f64 {
549 type Output = DMat2;
550 #[inline]
551 fn mul(self, rhs: &DMat2) -> DMat2 {
552 self.mul(*rhs)
553 }
554}
555
556impl Mul<&DMat2> for &f64 {
557 type Output = DMat2;
558 #[inline]
559 fn mul(self, rhs: &DMat2) -> DMat2 {
560 (*self).mul(*rhs)
561 }
562}
563
564impl Mul<DMat2> for &f64 {
565 type Output = DMat2;
566 #[inline]
567 fn mul(self, rhs: DMat2) -> DMat2 {
568 (*self).mul(rhs)
569 }
570}
571
572impl Mul<f64> for DMat2 {
573 type Output = Self;
574 #[inline]
575 fn mul(self, rhs: f64) -> Self {
576 self.mul_scalar(rhs)
577 }
578}
579
580impl Mul<&f64> for DMat2 {
581 type Output = Self;
582 #[inline]
583 fn mul(self, rhs: &f64) -> Self {
584 self.mul(*rhs)
585 }
586}
587
588impl Mul<&f64> for &DMat2 {
589 type Output = DMat2;
590 #[inline]
591 fn mul(self, rhs: &f64) -> DMat2 {
592 (*self).mul(*rhs)
593 }
594}
595
596impl Mul<f64> for &DMat2 {
597 type Output = DMat2;
598 #[inline]
599 fn mul(self, rhs: f64) -> DMat2 {
600 (*self).mul(rhs)
601 }
602}
603
604impl MulAssign<f64> for DMat2 {
605 #[inline]
606 fn mul_assign(&mut self, rhs: f64) {
607 *self = self.mul(rhs);
608 }
609}
610
611impl MulAssign<&f64> for DMat2 {
612 #[inline]
613 fn mul_assign(&mut self, rhs: &f64) {
614 self.mul_assign(*rhs);
615 }
616}
617
618impl Div<DMat2> for f64 {
619 type Output = DMat2;
620 #[inline]
621 fn div(self, rhs: DMat2) -> Self::Output {
622 rhs.div_scalar(self)
623 }
624}
625
626impl Div<&DMat2> for f64 {
627 type Output = DMat2;
628 #[inline]
629 fn div(self, rhs: &DMat2) -> DMat2 {
630 self.div(*rhs)
631 }
632}
633
634impl Div<&DMat2> for &f64 {
635 type Output = DMat2;
636 #[inline]
637 fn div(self, rhs: &DMat2) -> DMat2 {
638 (*self).div(*rhs)
639 }
640}
641
642impl Div<DMat2> for &f64 {
643 type Output = DMat2;
644 #[inline]
645 fn div(self, rhs: DMat2) -> DMat2 {
646 (*self).div(rhs)
647 }
648}
649
650impl Div<f64> for DMat2 {
651 type Output = Self;
652 #[inline]
653 fn div(self, rhs: f64) -> Self {
654 self.div_scalar(rhs)
655 }
656}
657
658impl Div<&f64> for DMat2 {
659 type Output = Self;
660 #[inline]
661 fn div(self, rhs: &f64) -> Self {
662 self.div(*rhs)
663 }
664}
665
666impl Div<&f64> for &DMat2 {
667 type Output = DMat2;
668 #[inline]
669 fn div(self, rhs: &f64) -> DMat2 {
670 (*self).div(*rhs)
671 }
672}
673
674impl Div<f64> for &DMat2 {
675 type Output = DMat2;
676 #[inline]
677 fn div(self, rhs: f64) -> DMat2 {
678 (*self).div(rhs)
679 }
680}
681
682impl DivAssign<f64> for DMat2 {
683 #[inline]
684 fn div_assign(&mut self, rhs: f64) {
685 *self = self.div(rhs);
686 }
687}
688
689impl DivAssign<&f64> for DMat2 {
690 #[inline]
691 fn div_assign(&mut self, rhs: &f64) {
692 self.div_assign(*rhs);
693 }
694}
695
696impl Sum<Self> for DMat2 {
697 fn sum<I>(iter: I) -> Self
698 where
699 I: Iterator<Item = Self>,
700 {
701 iter.fold(Self::ZERO, Self::add)
702 }
703}
704
705impl<'a> Sum<&'a Self> for DMat2 {
706 fn sum<I>(iter: I) -> Self
707 where
708 I: Iterator<Item = &'a Self>,
709 {
710 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
711 }
712}
713
714impl Product for DMat2 {
715 fn product<I>(iter: I) -> Self
716 where
717 I: Iterator<Item = Self>,
718 {
719 iter.fold(Self::IDENTITY, Self::mul)
720 }
721}
722
723impl<'a> Product<&'a Self> for DMat2 {
724 fn product<I>(iter: I) -> Self
725 where
726 I: Iterator<Item = &'a Self>,
727 {
728 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
729 }
730}
731
732impl PartialEq for DMat2 {
733 #[inline]
734 fn eq(&self, rhs: &Self) -> bool {
735 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
736 }
737}
738
739impl AsRef<[f64; 4]> for DMat2 {
740 #[inline]
741 fn as_ref(&self) -> &[f64; 4] {
742 unsafe { &*(self as *const Self as *const [f64; 4]) }
743 }
744}
745
746impl AsMut<[f64; 4]> for DMat2 {
747 #[inline]
748 fn as_mut(&mut self) -> &mut [f64; 4] {
749 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
750 }
751}
752
753impl fmt::Debug for DMat2 {
754 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
755 fmt.debug_struct(stringify!(DMat2))
756 .field("x_axis", &self.x_axis)
757 .field("y_axis", &self.y_axis)
758 .finish()
759 }
760}
761
762impl fmt::Display for DMat2 {
763 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764 if let Some(p) = f.precision() {
765 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
766 } else {
767 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
768 }
769 }
770}