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#[inline(always)]
10#[must_use]
11pub const fn dmat2(x_axis: DVec2, y_axis: DVec2) -> DMat2 {
12 DMat2::from_cols(x_axis, y_axis)
13}
14
15#[derive(Clone, Copy)]
17#[cfg_attr(
18 all(feature = "bytemuck", not(target_arch = "spirv")),
19 derive(bytemuck::Pod, bytemuck::Zeroable)
20)]
21#[cfg_attr(feature = "cuda", repr(align(16)))]
22#[repr(C)]
23pub struct DMat2 {
24 pub x_axis: DVec2,
25 pub y_axis: DVec2,
26}
27
28impl DMat2 {
29 pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
31
32 pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
34
35 pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
37
38 #[allow(clippy::too_many_arguments)]
39 #[inline(always)]
40 #[must_use]
41 const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
42 Self {
43 x_axis: DVec2::new(m00, m01),
44 y_axis: DVec2::new(m10, m11),
45 }
46 }
47
48 #[inline(always)]
50 #[must_use]
51 pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
52 Self { x_axis, y_axis }
53 }
54
55 #[inline]
59 #[must_use]
60 pub const fn from_cols_array(m: &[f64; 4]) -> Self {
61 Self::new(m[0], m[1], m[2], m[3])
62 }
63
64 #[inline]
67 #[must_use]
68 pub const fn to_cols_array(&self) -> [f64; 4] {
69 [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
70 }
71
72 #[inline]
76 #[must_use]
77 pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
78 Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
79 }
80
81 #[inline]
84 #[must_use]
85 pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
86 [self.x_axis.to_array(), self.y_axis.to_array()]
87 }
88
89 #[doc(alias = "scale")]
91 #[inline]
92 #[must_use]
93 pub const fn from_diagonal(diagonal: DVec2) -> Self {
94 Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
95 }
96
97 #[inline]
100 #[must_use]
101 pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
102 let (sin, cos) = math::sin_cos(angle);
103 Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
104 }
105
106 #[inline]
108 #[must_use]
109 pub fn from_angle(angle: f64) -> Self {
110 let (sin, cos) = math::sin_cos(angle);
111 Self::new(cos, sin, -sin, cos)
112 }
113
114 #[inline]
116 #[must_use]
117 pub fn from_mat3(m: DMat3) -> Self {
118 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
119 }
120
121 #[inline]
128 #[must_use]
129 pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
130 match (i, j) {
131 (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
132 (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
133 (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
134 (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
135 (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
136 (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
137 (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
138 (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
139 (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
140 _ => panic!("index out of bounds"),
141 }
142 }
143
144 #[inline]
150 #[must_use]
151 pub const fn from_cols_slice(slice: &[f64]) -> Self {
152 Self::new(slice[0], slice[1], slice[2], slice[3])
153 }
154
155 #[inline]
161 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
162 slice[0] = self.x_axis.x;
163 slice[1] = self.x_axis.y;
164 slice[2] = self.y_axis.x;
165 slice[3] = self.y_axis.y;
166 }
167
168 #[inline]
174 #[must_use]
175 pub fn col(&self, index: usize) -> DVec2 {
176 match index {
177 0 => self.x_axis,
178 1 => self.y_axis,
179 _ => panic!("index out of bounds"),
180 }
181 }
182
183 #[inline]
189 pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
190 match index {
191 0 => &mut self.x_axis,
192 1 => &mut self.y_axis,
193 _ => panic!("index out of bounds"),
194 }
195 }
196
197 #[inline]
203 #[must_use]
204 pub fn row(&self, index: usize) -> DVec2 {
205 match index {
206 0 => DVec2::new(self.x_axis.x, self.y_axis.x),
207 1 => DVec2::new(self.x_axis.y, self.y_axis.y),
208 _ => panic!("index out of bounds"),
209 }
210 }
211
212 #[inline]
215 #[must_use]
216 pub fn is_finite(&self) -> bool {
217 self.x_axis.is_finite() && self.y_axis.is_finite()
218 }
219
220 #[inline]
222 #[must_use]
223 pub fn is_nan(&self) -> bool {
224 self.x_axis.is_nan() || self.y_axis.is_nan()
225 }
226
227 #[inline]
229 #[must_use]
230 pub fn transpose(&self) -> Self {
231 Self {
232 x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
233 y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
234 }
235 }
236
237 #[inline]
239 #[must_use]
240 pub fn determinant(&self) -> f64 {
241 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
242 }
243
244 #[inline]
252 #[must_use]
253 pub fn inverse(&self) -> Self {
254 let inv_det = {
255 let det = self.determinant();
256 glam_assert!(det != 0.0);
257 det.recip()
258 };
259 Self::new(
260 self.y_axis.y * inv_det,
261 self.x_axis.y * -inv_det,
262 self.y_axis.x * -inv_det,
263 self.x_axis.x * inv_det,
264 )
265 }
266
267 #[inline]
269 #[must_use]
270 pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
271 #[allow(clippy::suspicious_operation_groupings)]
272 DVec2::new(
273 (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
274 (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
275 )
276 }
277
278 #[inline]
280 #[must_use]
281 pub fn mul_mat2(&self, rhs: &Self) -> Self {
282 self.mul(rhs)
283 }
284
285 #[inline]
287 #[must_use]
288 pub fn add_mat2(&self, rhs: &Self) -> Self {
289 self.add(rhs)
290 }
291
292 #[inline]
294 #[must_use]
295 pub fn sub_mat2(&self, rhs: &Self) -> Self {
296 self.sub(rhs)
297 }
298
299 #[inline]
301 #[must_use]
302 pub fn mul_scalar(&self, rhs: f64) -> Self {
303 Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
304 }
305
306 #[inline]
308 #[must_use]
309 pub fn div_scalar(&self, rhs: f64) -> Self {
310 let rhs = DVec2::splat(rhs);
311 Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
312 }
313
314 #[inline]
324 #[must_use]
325 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
326 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
327 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
328 }
329
330 #[inline]
332 #[must_use]
333 pub fn abs(&self) -> Self {
334 Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
335 }
336
337 #[inline]
338 pub fn as_mat2(&self) -> Mat2 {
339 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
340 }
341}
342
343impl Default for DMat2 {
344 #[inline]
345 fn default() -> Self {
346 Self::IDENTITY
347 }
348}
349
350impl Add for DMat2 {
351 type Output = Self;
352 #[inline]
353 fn add(self, rhs: Self) -> Self {
354 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
355 }
356}
357
358impl Add<&Self> for DMat2 {
359 type Output = Self;
360 #[inline]
361 fn add(self, rhs: &Self) -> Self {
362 self.add(*rhs)
363 }
364}
365
366impl Add<&DMat2> for &DMat2 {
367 type Output = DMat2;
368 #[inline]
369 fn add(self, rhs: &DMat2) -> DMat2 {
370 (*self).add(*rhs)
371 }
372}
373
374impl Add<DMat2> for &DMat2 {
375 type Output = DMat2;
376 #[inline]
377 fn add(self, rhs: DMat2) -> DMat2 {
378 (*self).add(rhs)
379 }
380}
381
382impl AddAssign for DMat2 {
383 #[inline]
384 fn add_assign(&mut self, rhs: Self) {
385 *self = self.add(rhs);
386 }
387}
388
389impl AddAssign<&Self> for DMat2 {
390 #[inline]
391 fn add_assign(&mut self, rhs: &Self) {
392 self.add_assign(*rhs);
393 }
394}
395
396impl Sub for DMat2 {
397 type Output = Self;
398 #[inline]
399 fn sub(self, rhs: Self) -> Self {
400 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
401 }
402}
403
404impl Sub<&Self> for DMat2 {
405 type Output = Self;
406 #[inline]
407 fn sub(self, rhs: &Self) -> Self {
408 self.sub(*rhs)
409 }
410}
411
412impl Sub<&DMat2> for &DMat2 {
413 type Output = DMat2;
414 #[inline]
415 fn sub(self, rhs: &DMat2) -> DMat2 {
416 (*self).sub(*rhs)
417 }
418}
419
420impl Sub<DMat2> for &DMat2 {
421 type Output = DMat2;
422 #[inline]
423 fn sub(self, rhs: DMat2) -> DMat2 {
424 (*self).sub(rhs)
425 }
426}
427
428impl SubAssign for DMat2 {
429 #[inline]
430 fn sub_assign(&mut self, rhs: Self) {
431 *self = self.sub(rhs);
432 }
433}
434
435impl SubAssign<&Self> for DMat2 {
436 #[inline]
437 fn sub_assign(&mut self, rhs: &Self) {
438 self.sub_assign(*rhs);
439 }
440}
441
442impl Neg for DMat2 {
443 type Output = Self;
444 #[inline]
445 fn neg(self) -> Self::Output {
446 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
447 }
448}
449
450impl Neg for &DMat2 {
451 type Output = DMat2;
452 #[inline]
453 fn neg(self) -> DMat2 {
454 (*self).neg()
455 }
456}
457
458impl Mul for DMat2 {
459 type Output = Self;
460 #[inline]
461 fn mul(self, rhs: Self) -> Self {
462 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
463 }
464}
465
466impl Mul<&Self> for DMat2 {
467 type Output = Self;
468 #[inline]
469 fn mul(self, rhs: &Self) -> Self {
470 self.mul(*rhs)
471 }
472}
473
474impl Mul<&DMat2> for &DMat2 {
475 type Output = DMat2;
476 #[inline]
477 fn mul(self, rhs: &DMat2) -> DMat2 {
478 (*self).mul(*rhs)
479 }
480}
481
482impl Mul<DMat2> for &DMat2 {
483 type Output = DMat2;
484 #[inline]
485 fn mul(self, rhs: DMat2) -> DMat2 {
486 (*self).mul(rhs)
487 }
488}
489
490impl MulAssign for DMat2 {
491 #[inline]
492 fn mul_assign(&mut self, rhs: Self) {
493 *self = self.mul(rhs);
494 }
495}
496
497impl MulAssign<&Self> for DMat2 {
498 #[inline]
499 fn mul_assign(&mut self, rhs: &Self) {
500 self.mul_assign(*rhs);
501 }
502}
503
504impl Mul<DVec2> for DMat2 {
505 type Output = DVec2;
506 #[inline]
507 fn mul(self, rhs: DVec2) -> Self::Output {
508 self.mul_vec2(rhs)
509 }
510}
511
512impl Mul<&DVec2> for DMat2 {
513 type Output = DVec2;
514 #[inline]
515 fn mul(self, rhs: &DVec2) -> DVec2 {
516 self.mul(*rhs)
517 }
518}
519
520impl Mul<&DVec2> for &DMat2 {
521 type Output = DVec2;
522 #[inline]
523 fn mul(self, rhs: &DVec2) -> DVec2 {
524 (*self).mul(*rhs)
525 }
526}
527
528impl Mul<DVec2> for &DMat2 {
529 type Output = DVec2;
530 #[inline]
531 fn mul(self, rhs: DVec2) -> DVec2 {
532 (*self).mul(rhs)
533 }
534}
535
536impl Mul<DMat2> for f64 {
537 type Output = DMat2;
538 #[inline]
539 fn mul(self, rhs: DMat2) -> Self::Output {
540 rhs.mul_scalar(self)
541 }
542}
543
544impl Mul<&DMat2> for f64 {
545 type Output = DMat2;
546 #[inline]
547 fn mul(self, rhs: &DMat2) -> DMat2 {
548 self.mul(*rhs)
549 }
550}
551
552impl Mul<&DMat2> for &f64 {
553 type Output = DMat2;
554 #[inline]
555 fn mul(self, rhs: &DMat2) -> DMat2 {
556 (*self).mul(*rhs)
557 }
558}
559
560impl Mul<DMat2> for &f64 {
561 type Output = DMat2;
562 #[inline]
563 fn mul(self, rhs: DMat2) -> DMat2 {
564 (*self).mul(rhs)
565 }
566}
567
568impl Mul<f64> for DMat2 {
569 type Output = Self;
570 #[inline]
571 fn mul(self, rhs: f64) -> Self {
572 self.mul_scalar(rhs)
573 }
574}
575
576impl Mul<&f64> for DMat2 {
577 type Output = Self;
578 #[inline]
579 fn mul(self, rhs: &f64) -> Self {
580 self.mul(*rhs)
581 }
582}
583
584impl Mul<&f64> for &DMat2 {
585 type Output = DMat2;
586 #[inline]
587 fn mul(self, rhs: &f64) -> DMat2 {
588 (*self).mul(*rhs)
589 }
590}
591
592impl Mul<f64> for &DMat2 {
593 type Output = DMat2;
594 #[inline]
595 fn mul(self, rhs: f64) -> DMat2 {
596 (*self).mul(rhs)
597 }
598}
599
600impl MulAssign<f64> for DMat2 {
601 #[inline]
602 fn mul_assign(&mut self, rhs: f64) {
603 *self = self.mul(rhs);
604 }
605}
606
607impl MulAssign<&f64> for DMat2 {
608 #[inline]
609 fn mul_assign(&mut self, rhs: &f64) {
610 self.mul_assign(*rhs);
611 }
612}
613
614impl Div<DMat2> for f64 {
615 type Output = DMat2;
616 #[inline]
617 fn div(self, rhs: DMat2) -> Self::Output {
618 rhs.div_scalar(self)
619 }
620}
621
622impl Div<&DMat2> for f64 {
623 type Output = DMat2;
624 #[inline]
625 fn div(self, rhs: &DMat2) -> DMat2 {
626 self.div(*rhs)
627 }
628}
629
630impl Div<&DMat2> for &f64 {
631 type Output = DMat2;
632 #[inline]
633 fn div(self, rhs: &DMat2) -> DMat2 {
634 (*self).div(*rhs)
635 }
636}
637
638impl Div<DMat2> for &f64 {
639 type Output = DMat2;
640 #[inline]
641 fn div(self, rhs: DMat2) -> DMat2 {
642 (*self).div(rhs)
643 }
644}
645
646impl Div<f64> for DMat2 {
647 type Output = Self;
648 #[inline]
649 fn div(self, rhs: f64) -> Self {
650 self.div_scalar(rhs)
651 }
652}
653
654impl Div<&f64> for DMat2 {
655 type Output = Self;
656 #[inline]
657 fn div(self, rhs: &f64) -> Self {
658 self.div(*rhs)
659 }
660}
661
662impl Div<&f64> for &DMat2 {
663 type Output = DMat2;
664 #[inline]
665 fn div(self, rhs: &f64) -> DMat2 {
666 (*self).div(*rhs)
667 }
668}
669
670impl Div<f64> for &DMat2 {
671 type Output = DMat2;
672 #[inline]
673 fn div(self, rhs: f64) -> DMat2 {
674 (*self).div(rhs)
675 }
676}
677
678impl DivAssign<f64> for DMat2 {
679 #[inline]
680 fn div_assign(&mut self, rhs: f64) {
681 *self = self.div(rhs);
682 }
683}
684
685impl DivAssign<&f64> for DMat2 {
686 #[inline]
687 fn div_assign(&mut self, rhs: &f64) {
688 self.div_assign(*rhs);
689 }
690}
691
692impl Sum<Self> for DMat2 {
693 fn sum<I>(iter: I) -> Self
694 where
695 I: Iterator<Item = Self>,
696 {
697 iter.fold(Self::ZERO, Self::add)
698 }
699}
700
701impl<'a> Sum<&'a Self> for DMat2 {
702 fn sum<I>(iter: I) -> Self
703 where
704 I: Iterator<Item = &'a Self>,
705 {
706 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
707 }
708}
709
710impl Product for DMat2 {
711 fn product<I>(iter: I) -> Self
712 where
713 I: Iterator<Item = Self>,
714 {
715 iter.fold(Self::IDENTITY, Self::mul)
716 }
717}
718
719impl<'a> Product<&'a Self> for DMat2 {
720 fn product<I>(iter: I) -> Self
721 where
722 I: Iterator<Item = &'a Self>,
723 {
724 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
725 }
726}
727
728impl PartialEq for DMat2 {
729 #[inline]
730 fn eq(&self, rhs: &Self) -> bool {
731 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
732 }
733}
734
735#[cfg(not(target_arch = "spirv"))]
736impl AsRef<[f64; 4]> for DMat2 {
737 #[inline]
738 fn as_ref(&self) -> &[f64; 4] {
739 unsafe { &*(self as *const Self as *const [f64; 4]) }
740 }
741}
742
743#[cfg(not(target_arch = "spirv"))]
744impl AsMut<[f64; 4]> for DMat2 {
745 #[inline]
746 fn as_mut(&mut self) -> &mut [f64; 4] {
747 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
748 }
749}
750
751impl fmt::Debug for DMat2 {
752 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
753 fmt.debug_struct(stringify!(DMat2))
754 .field("x_axis", &self.x_axis)
755 .field("y_axis", &self.y_axis)
756 .finish()
757 }
758}
759
760impl fmt::Display for DMat2 {
761 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762 if let Some(p) = f.precision() {
763 write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
764 } else {
765 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
766 }
767 }
768}