glam/f64/
dmat2.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3use 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/// Creates a 2x2 matrix from two column vectors.
9#[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/// A 2x2 column major matrix.
16#[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    /// A 2x2 matrix with all elements set to `0.0`.
26    pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO);
27
28    /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
29    pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y);
30
31    /// All NAN:s.
32    pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN);
33
34    #[allow(clippy::too_many_arguments)]
35    #[inline(always)]
36    #[must_use]
37    const fn new(m00: f64, m01: f64, m10: f64, m11: f64) -> Self {
38        Self {
39            x_axis: DVec2::new(m00, m01),
40            y_axis: DVec2::new(m10, m11),
41        }
42    }
43
44    /// Creates a 2x2 matrix from two column vectors.
45    #[inline(always)]
46    #[must_use]
47    pub const fn from_cols(x_axis: DVec2, y_axis: DVec2) -> Self {
48        Self { x_axis, y_axis }
49    }
50
51    /// Creates a 2x2 matrix from a `[f64; 4]` array stored in column major order.
52    /// If your data is stored in row major you will need to `transpose` the returned
53    /// matrix.
54    #[inline]
55    #[must_use]
56    pub const fn from_cols_array(m: &[f64; 4]) -> Self {
57        Self::new(m[0], m[1], m[2], m[3])
58    }
59
60    /// Creates a `[f64; 4]` array storing data in column major order.
61    /// If you require data in row major order `transpose` the matrix first.
62    #[inline]
63    #[must_use]
64    pub const fn to_cols_array(&self) -> [f64; 4] {
65        [self.x_axis.x, self.x_axis.y, self.y_axis.x, self.y_axis.y]
66    }
67
68    /// Creates a 2x2 matrix from a `[[f64; 2]; 2]` 2D array stored in column major order.
69    /// If your data is in row major order you will need to `transpose` the returned
70    /// matrix.
71    #[inline]
72    #[must_use]
73    pub const fn from_cols_array_2d(m: &[[f64; 2]; 2]) -> Self {
74        Self::from_cols(DVec2::from_array(m[0]), DVec2::from_array(m[1]))
75    }
76
77    /// Creates a `[[f64; 2]; 2]` 2D array storing data in column major order.
78    /// If you require data in row major order `transpose` the matrix first.
79    #[inline]
80    #[must_use]
81    pub const fn to_cols_array_2d(&self) -> [[f64; 2]; 2] {
82        [self.x_axis.to_array(), self.y_axis.to_array()]
83    }
84
85    /// Creates a 2x2 matrix with its diagonal set to `diagonal` and all other entries set to 0.
86    #[doc(alias = "scale")]
87    #[inline]
88    #[must_use]
89    pub const fn from_diagonal(diagonal: DVec2) -> Self {
90        Self::new(diagonal.x, 0.0, 0.0, diagonal.y)
91    }
92
93    /// Creates a 2x2 matrix containing the combining non-uniform `scale` and rotation of
94    /// `angle` (in radians).
95    #[inline]
96    #[must_use]
97    pub fn from_scale_angle(scale: DVec2, angle: f64) -> Self {
98        let (sin, cos) = math::sin_cos(angle);
99        Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y)
100    }
101
102    /// Creates a 2x2 matrix containing a rotation of `angle` (in radians).
103    #[inline]
104    #[must_use]
105    pub fn from_angle(angle: f64) -> Self {
106        let (sin, cos) = math::sin_cos(angle);
107        Self::new(cos, sin, -sin, cos)
108    }
109
110    /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column.
111    #[inline]
112    #[must_use]
113    pub fn from_mat3(m: DMat3) -> Self {
114        Self::from_cols(m.x_axis.xy(), m.y_axis.xy())
115    }
116
117    /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column
118    /// and `j`th row.
119    ///
120    /// # Panics
121    ///
122    /// Panics if `i` or `j` is greater than 2.
123    #[inline]
124    #[must_use]
125    pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self {
126        match (i, j) {
127            (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()),
128            (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()),
129            (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()),
130            (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()),
131            (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()),
132            (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()),
133            (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()),
134            (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()),
135            (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()),
136            _ => panic!("index out of bounds"),
137        }
138    }
139
140    /// Creates a 2x2 matrix from the first 4 values in `slice`.
141    ///
142    /// # Panics
143    ///
144    /// Panics if `slice` is less than 4 elements long.
145    #[inline]
146    #[must_use]
147    pub const fn from_cols_slice(slice: &[f64]) -> Self {
148        Self::new(slice[0], slice[1], slice[2], slice[3])
149    }
150
151    /// Writes the columns of `self` to the first 4 elements in `slice`.
152    ///
153    /// # Panics
154    ///
155    /// Panics if `slice` is less than 4 elements long.
156    #[inline]
157    pub fn write_cols_to_slice(self, slice: &mut [f64]) {
158        slice[0] = self.x_axis.x;
159        slice[1] = self.x_axis.y;
160        slice[2] = self.y_axis.x;
161        slice[3] = self.y_axis.y;
162    }
163
164    /// Returns the matrix column for the given `index`.
165    ///
166    /// # Panics
167    ///
168    /// Panics if `index` is greater than 1.
169    #[inline]
170    #[must_use]
171    pub fn col(&self, index: usize) -> DVec2 {
172        match index {
173            0 => self.x_axis,
174            1 => self.y_axis,
175            _ => panic!("index out of bounds"),
176        }
177    }
178
179    /// Returns a mutable reference to the matrix column for the given `index`.
180    ///
181    /// # Panics
182    ///
183    /// Panics if `index` is greater than 1.
184    #[inline]
185    pub fn col_mut(&mut self, index: usize) -> &mut DVec2 {
186        match index {
187            0 => &mut self.x_axis,
188            1 => &mut self.y_axis,
189            _ => panic!("index out of bounds"),
190        }
191    }
192
193    /// Returns the matrix row for the given `index`.
194    ///
195    /// # Panics
196    ///
197    /// Panics if `index` is greater than 1.
198    #[inline]
199    #[must_use]
200    pub fn row(&self, index: usize) -> DVec2 {
201        match index {
202            0 => DVec2::new(self.x_axis.x, self.y_axis.x),
203            1 => DVec2::new(self.x_axis.y, self.y_axis.y),
204            _ => panic!("index out of bounds"),
205        }
206    }
207
208    /// Returns `true` if, and only if, all elements are finite.
209    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
210    #[inline]
211    #[must_use]
212    pub fn is_finite(&self) -> bool {
213        self.x_axis.is_finite() && self.y_axis.is_finite()
214    }
215
216    /// Returns `true` if any elements are `NaN`.
217    #[inline]
218    #[must_use]
219    pub fn is_nan(&self) -> bool {
220        self.x_axis.is_nan() || self.y_axis.is_nan()
221    }
222
223    /// Returns the transpose of `self`.
224    #[inline]
225    #[must_use]
226    pub fn transpose(&self) -> Self {
227        Self {
228            x_axis: DVec2::new(self.x_axis.x, self.y_axis.x),
229            y_axis: DVec2::new(self.x_axis.y, self.y_axis.y),
230        }
231    }
232
233    /// Returns the determinant of `self`.
234    #[inline]
235    #[must_use]
236    pub fn determinant(&self) -> f64 {
237        self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x
238    }
239
240    /// Returns the inverse of `self`.
241    ///
242    /// If the matrix is not invertible the returned matrix will be invalid.
243    ///
244    /// # Panics
245    ///
246    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
247    #[inline]
248    #[must_use]
249    pub fn inverse(&self) -> Self {
250        let inv_det = {
251            let det = self.determinant();
252            glam_assert!(det != 0.0);
253            det.recip()
254        };
255        Self::new(
256            self.y_axis.y * inv_det,
257            self.x_axis.y * -inv_det,
258            self.y_axis.x * -inv_det,
259            self.x_axis.x * inv_det,
260        )
261    }
262
263    /// Transforms a 2D vector.
264    #[inline]
265    #[must_use]
266    pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 {
267        #[allow(clippy::suspicious_operation_groupings)]
268        DVec2::new(
269            (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y),
270            (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y),
271        )
272    }
273
274    /// Multiplies two 2x2 matrices.
275    #[inline]
276    #[must_use]
277    pub fn mul_mat2(&self, rhs: &Self) -> Self {
278        Self::from_cols(self.mul(rhs.x_axis), self.mul(rhs.y_axis))
279    }
280
281    /// Adds two 2x2 matrices.
282    #[inline]
283    #[must_use]
284    pub fn add_mat2(&self, rhs: &Self) -> Self {
285        Self::from_cols(self.x_axis.add(rhs.x_axis), self.y_axis.add(rhs.y_axis))
286    }
287
288    /// Subtracts two 2x2 matrices.
289    #[inline]
290    #[must_use]
291    pub fn sub_mat2(&self, rhs: &Self) -> Self {
292        Self::from_cols(self.x_axis.sub(rhs.x_axis), self.y_axis.sub(rhs.y_axis))
293    }
294
295    /// Multiplies a 2x2 matrix by a scalar.
296    #[inline]
297    #[must_use]
298    pub fn mul_scalar(&self, rhs: f64) -> Self {
299        Self::from_cols(self.x_axis.mul(rhs), self.y_axis.mul(rhs))
300    }
301
302    /// Divides a 2x2 matrix by a scalar.
303    #[inline]
304    #[must_use]
305    pub fn div_scalar(&self, rhs: f64) -> Self {
306        let rhs = DVec2::splat(rhs);
307        Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs))
308    }
309
310    /// Returns true if the absolute difference of all elements between `self` and `rhs`
311    /// is less than or equal to `max_abs_diff`.
312    ///
313    /// This can be used to compare if two matrices contain similar elements. It works best
314    /// when comparing with a known value. The `max_abs_diff` that should be used used
315    /// depends on the values being compared against.
316    ///
317    /// For more see
318    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
319    #[inline]
320    #[must_use]
321    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
322        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
323            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
324    }
325
326    /// Takes the absolute value of each element in `self`
327    #[inline]
328    #[must_use]
329    pub fn abs(&self) -> Self {
330        Self::from_cols(self.x_axis.abs(), self.y_axis.abs())
331    }
332
333    #[inline]
334    pub fn as_mat2(&self) -> Mat2 {
335        Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2())
336    }
337}
338
339impl Default for DMat2 {
340    #[inline]
341    fn default() -> Self {
342        Self::IDENTITY
343    }
344}
345
346impl Add<DMat2> for DMat2 {
347    type Output = Self;
348    #[inline]
349    fn add(self, rhs: Self) -> Self::Output {
350        self.add_mat2(&rhs)
351    }
352}
353
354impl AddAssign<DMat2> for DMat2 {
355    #[inline]
356    fn add_assign(&mut self, rhs: Self) {
357        *self = self.add_mat2(&rhs);
358    }
359}
360
361impl Sub<DMat2> for DMat2 {
362    type Output = Self;
363    #[inline]
364    fn sub(self, rhs: Self) -> Self::Output {
365        self.sub_mat2(&rhs)
366    }
367}
368
369impl SubAssign<DMat2> for DMat2 {
370    #[inline]
371    fn sub_assign(&mut self, rhs: Self) {
372        *self = self.sub_mat2(&rhs);
373    }
374}
375
376impl Neg for DMat2 {
377    type Output = Self;
378    #[inline]
379    fn neg(self) -> Self::Output {
380        Self::from_cols(self.x_axis.neg(), self.y_axis.neg())
381    }
382}
383
384impl Mul<DMat2> for DMat2 {
385    type Output = Self;
386    #[inline]
387    fn mul(self, rhs: Self) -> Self::Output {
388        self.mul_mat2(&rhs)
389    }
390}
391
392impl MulAssign<DMat2> for DMat2 {
393    #[inline]
394    fn mul_assign(&mut self, rhs: Self) {
395        *self = self.mul_mat2(&rhs);
396    }
397}
398
399impl Mul<DVec2> for DMat2 {
400    type Output = DVec2;
401    #[inline]
402    fn mul(self, rhs: DVec2) -> Self::Output {
403        self.mul_vec2(rhs)
404    }
405}
406
407impl Mul<DMat2> for f64 {
408    type Output = DMat2;
409    #[inline]
410    fn mul(self, rhs: DMat2) -> Self::Output {
411        rhs.mul_scalar(self)
412    }
413}
414
415impl Mul<f64> for DMat2 {
416    type Output = Self;
417    #[inline]
418    fn mul(self, rhs: f64) -> Self::Output {
419        self.mul_scalar(rhs)
420    }
421}
422
423impl MulAssign<f64> for DMat2 {
424    #[inline]
425    fn mul_assign(&mut self, rhs: f64) {
426        *self = self.mul_scalar(rhs);
427    }
428}
429
430impl Div<DMat2> for f64 {
431    type Output = DMat2;
432    #[inline]
433    fn div(self, rhs: DMat2) -> Self::Output {
434        rhs.div_scalar(self)
435    }
436}
437
438impl Div<f64> for DMat2 {
439    type Output = Self;
440    #[inline]
441    fn div(self, rhs: f64) -> Self::Output {
442        self.div_scalar(rhs)
443    }
444}
445
446impl DivAssign<f64> for DMat2 {
447    #[inline]
448    fn div_assign(&mut self, rhs: f64) {
449        *self = self.div_scalar(rhs);
450    }
451}
452
453impl Sum<Self> for DMat2 {
454    fn sum<I>(iter: I) -> Self
455    where
456        I: Iterator<Item = Self>,
457    {
458        iter.fold(Self::ZERO, Self::add)
459    }
460}
461
462impl<'a> Sum<&'a Self> for DMat2 {
463    fn sum<I>(iter: I) -> Self
464    where
465        I: Iterator<Item = &'a Self>,
466    {
467        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
468    }
469}
470
471impl Product for DMat2 {
472    fn product<I>(iter: I) -> Self
473    where
474        I: Iterator<Item = Self>,
475    {
476        iter.fold(Self::IDENTITY, Self::mul)
477    }
478}
479
480impl<'a> Product<&'a Self> for DMat2 {
481    fn product<I>(iter: I) -> Self
482    where
483        I: Iterator<Item = &'a Self>,
484    {
485        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
486    }
487}
488
489impl PartialEq for DMat2 {
490    #[inline]
491    fn eq(&self, rhs: &Self) -> bool {
492        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis)
493    }
494}
495
496#[cfg(not(target_arch = "spirv"))]
497impl AsRef<[f64; 4]> for DMat2 {
498    #[inline]
499    fn as_ref(&self) -> &[f64; 4] {
500        unsafe { &*(self as *const Self as *const [f64; 4]) }
501    }
502}
503
504#[cfg(not(target_arch = "spirv"))]
505impl AsMut<[f64; 4]> for DMat2 {
506    #[inline]
507    fn as_mut(&mut self) -> &mut [f64; 4] {
508        unsafe { &mut *(self as *mut Self as *mut [f64; 4]) }
509    }
510}
511
512impl fmt::Debug for DMat2 {
513    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
514        fmt.debug_struct(stringify!(DMat2))
515            .field("x_axis", &self.x_axis)
516            .field("y_axis", &self.y_axis)
517            .finish()
518    }
519}
520
521impl fmt::Display for DMat2 {
522    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523        if let Some(p) = f.precision() {
524            write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis)
525        } else {
526            write!(f, "[{}, {}]", self.x_axis, self.y_axis)
527        }
528    }
529}