1use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2};
4#[cfg(not(target_arch = "spirv"))]
5use core::fmt;
6use core::iter::{Product, Sum};
7use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8
9#[inline(always)]
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(feature = "cuda", repr(align(16)))]
18#[repr(C)]
19pub struct DMat2 {
20 pub x_axis: DVec2,
21 pub y_axis: DVec2,
22}
23
24impl DMat2 {
25 pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
27
28 pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
30
31 pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
33
34 #[allow(clippy::too_many_arguments)]
35 #[inline(always)]
36 const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
37 Self {
38 x_axis: DVec2::new(m00, m01),
39 y_axis: DVec2::new(m10, m11),
40 }
41 }
42
43 #[inline(always)]
45 pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
46 Self { x_axis, y_axis }
47 }
48
49 #[inline]
53 pub const fn from_cols_array(m: &[f64; 4]) -> Self {
54 Self::new(m[0], m[1], m[2], m[3])
55 }
56
57 #[inline]
60 pub const fn to_cols_array(&self) -> [f64; 4] {
61 [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
62 }
63
64 #[inline]
68 pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
69 Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
70 }
71
72 #[inline]
75 pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
76 [self.x_axis.to_array(), self.y_axis.to_array()]
77 }
78
79 #[doc(alias = "scale")]
81 #[inline]
82 pub const fn from_diagonal(diagonal: DVec2) -> Self {
83 Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
84 }
85
86 #[inline]
89 pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
90 let (sin, cos) = math::sin_cos(angle);
91 Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
92 }
93
94 #[inline]
96 pub fn from_angle(angle: f64) -> Self {
97 let (sin, cos) = math::sin_cos(angle);
98 Self::new(cos, sin, -sin, cos)
99 }
100
101 #[inline]
103 pub fn from_mat3(m: DMat3) -> Self {
104 Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
105 }
106
107 #[inline]
113 pub const fn from_cols_slice(slice: &[f64]) -> Self {
114 Self::new(slice[0], slice[1], slice[2], slice[3])
115 }
116
117 #[inline]
123 pub fn write_cols_to_slice(self, slice: &mut [f64]) {
124 slice[0] = self.x_axis.x;
125 slice[1] = self.x_axis.y;
126 slice[2] = self.y_axis.x;
127 slice[3] = self.y_axis.y;
128 }
129
130 #[inline]
136 pub fn col(&self, index: usize) -> DVec2 {
137 match index {
138 0 => self.x_axis,
139 1 => self.y_axis,
140 _ => panic!("index out of bounds"),
141 }
142 }
143
144 #[inline]
150 pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
151 match index {
152 0 => &mut self.x_axis,
153 1 => &mut self.y_axis,
154 _ => panic!("index out of bounds"),
155 }
156 }
157
158 #[inline]
164 pub fn row(&self, index: usize) -> DVec2 {
165 match index {
166 0 => DVec2::new(self.x_axis.x, self.y_axis.x),
167 1 => DVec2::new(self.x_axis.y, self.y_axis.y),
168 _ => panic!("index out of bounds"),
169 }
170 }
171
172 #[inline]
175 pub fn is_finite(&self) -> bool {
176 self.x_axis.is_finite() && self.y_axis.is_finite()
177 }
178
179 #[inline]
181 pub fn is_nan(&self) -> bool {
182 self.x_axis.is_nan() || self.y_axis.is_nan()
183 }
184
185 #[must_use]
187 #[inline]
188 pub fn transpose(&self) -> Self {
189 Self {
190 x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
191 y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
192 }
193 }
194
195 #[inline]
197 pub fn determinant(&self) -> f64 {
198 self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
199 }
200
201 #[must_use]
209 #[inline]
210 pub fn inverse(&self) -> Self {
211 let inv_det = {
212 let det = self.determinant();
213 glam_assert!(det != 0.0);
214 det.recip()
215 };
216 Self::new(
217 self.y_axis.y * inv_det,
218 self.x_axis.y * -inv_det,
219 self.y_axis.x * -inv_det,
220 self.x_axis.x * inv_det,
221 )
222 }
223
224 #[inline]
226 pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
227 #[allow(clippy::suspicious_operation_groupings)]
228 DVec2::new(
229 (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
230 (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
231 )
232 }
233
234 #[inline]
236 pub fn mul_mat2(&self, rhs: &Self) -> Self {
237 Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
238 }
239
240 #[inline]
242 pub fn add_mat2(&self, rhs: &Self) -> Self {
243 Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
244 }
245
246 #[inline]
248 pub fn sub_mat2(&self, rhs: &Self) -> Self {
249 Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
250 }
251
252 #[inline]
254 pub fn mul_scalar(&self, rhs: f64) -> Self {
255 Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
256 }
257
258 #[inline]
268 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
269 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
270 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
271 }
272
273 #[inline]
274 pub fn as_mat2(&self) -> Mat2 {
275 Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
276 }
277}
278
279impl Default for DMat2 {
280 #[inline]
281 fn default() -> Self {
282 Self::IDENTITY
283 }
284}
285
286impl Add<DMat2> for DMat2 {
287 type Output = Self;
288 #[inline]
289 fn add(self, rhs: Self) -> Self::Output {
290 self.add_mat2(&rhs)
291 }
292}
293
294impl AddAssign<DMat2> for DMat2 {
295 #[inline]
296 fn add_assign(&mut self, rhs: Self) {
297 *self = self.add_mat2(&rhs);
298 }
299}
300
301impl Sub<DMat2> for DMat2 {
302 type Output = Self;
303 #[inline]
304 fn sub(self, rhs: Self) -> Self::Output {
305 self.sub_mat2(&rhs)
306 }
307}
308
309impl SubAssign<DMat2> for DMat2 {
310 #[inline]
311 fn sub_assign(&mut self, rhs: Self) {
312 *self = self.sub_mat2(&rhs);
313 }
314}
315
316impl Neg for DMat2 {
317 type Output = Self;
318 #[inline]
319 fn neg(self) -> Self::Output {
320 Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
321 }
322}
323
324impl Mul<DMat2> for DMat2 {
325 type Output = Self;
326 #[inline]
327 fn mul(self, rhs: Self) -> Self::Output {
328 self.mul_mat2(&rhs)
329 }
330}
331
332impl MulAssign<DMat2> for DMat2 {
333 #[inline]
334 fn mul_assign(&mut self, rhs: Self) {
335 *self = self.mul_mat2(&rhs);
336 }
337}
338
339impl Mul<DVec2> for DMat2 {
340 type Output = DVec2;
341 #[inline]
342 fn mul(self, rhs: DVec2) -> Self::Output {
343 self.mul_vec2(rhs)
344 }
345}
346
347impl Mul<DMat2> for f64 {
348 type Output = DMat2;
349 #[inline]
350 fn mul(self, rhs: DMat2) -> Self::Output {
351 rhs.mul_scalar(self)
352 }
353}
354
355impl Mul<f64> for DMat2 {
356 type Output = Self;
357 #[inline]
358 fn mul(self, rhs: f64) -> Self::Output {
359 self.mul_scalar(rhs)
360 }
361}
362
363impl MulAssign<f64> for DMat2 {
364 #[inline]
365 fn mul_assign(&mut self, rhs: f64) {
366 *self = self.mul_scalar(rhs);
367 }
368}
369
370impl Sum<Self> for DMat2 {
371 fn sum<I>(iter: I) -> Self
372 where
373 I: Iterator<Item = Self>,
374 {
375 iter.fold(Self::ZERO, Self::add)
376 }
377}
378
379impl<'a> Sum<&'a Self> for DMat2 {
380 fn sum<I>(iter: I) -> Self
381 where
382 I: Iterator<Item = &'a Self>,
383 {
384 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
385 }
386}
387
388impl Product for DMat2 {
389 fn product<I>(iter: I) -> Self
390 where
391 I: Iterator<Item = Self>,
392 {
393 iter.fold(Self::IDENTITY, Self::mul)
394 }
395}
396
397impl<'a> Product<&'a Self> for DMat2 {
398 fn product<I>(iter: I) -> Self
399 where
400 I: Iterator<Item = &'a Self>,
401 {
402 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
403 }
404}
405
406impl PartialEq for DMat2 {
407 #[inline]
408 fn eq(&self, rhs: &Self) -> bool {
409 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
410 }
411}
412
413#[cfg(not(target_arch = "spirv"))]
414impl AsRef<[f64; 4]> for DMat2 {
415 #[inline]
416 fn as_ref(&self) -> &[f64; 4] {
417 unsafe { &*(self as *const Self as *const [f64; 4]) }
418 }
419}
420
421#[cfg(not(target_arch = "spirv"))]
422impl AsMut<[f64; 4]> for DMat2 {
423 #[inline]
424 fn as_mut(&mut self) -> &mut [f64; 4] {
425 unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
426 }
427}
428
429#[cfg(not(target_arch = "spirv"))]
430impl fmt::Debug for DMat2 {
431 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
432 fmt.debug_struct(stringify!(DMat2))
433 .field("x_axis", &self.x_axis)
434 .field("y_axis", &self.y_axis)
435 .finish()
436 }
437}
438
439#[cfg(not(target_arch = "spirv"))]
440impl fmt::Display for DMat2 {
441 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
442 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
443 }
444}