Skip to main content

glam/f64/
dmat3.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3,
5    euler::{FromEuler, ToEuler},
6    f64::math,
7    swizzles::*,
8};
9use core::fmt;
10use core::iter::{Product, Sum};
11use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12
13#[cfg(feature = "zerocopy-08")]
14use zerocopy_derive_08::*;
15
16/// Creates a 3x3 matrix from three column vectors.
17#[inline(always)]
18#[must_use]
19pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
20    DMat3::from_cols(x_axis, y_axis, z_axis)
21}
22
23/// A 3x3 column major matrix.
24///
25/// This 3x3 matrix type features convenience methods for creating and using linear and
26/// affine transformations. If you are primarily dealing with 2D affine transformations the
27/// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than
28/// using a 3x3 matrix.
29///
30/// Linear transformations including 3D rotation and scale can be created using methods
31/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
32/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
33/// [`Self::from_rotation_z()`].
34///
35/// The resulting matrices can be use to transform 3D vectors using regular vector
36/// multiplication.
37///
38/// Affine transformations including 2D translation, rotation and scale can be created
39/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
40/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
41///
42/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
43/// are provided for performing affine transforms on 2D vectors and points. These multiply
44/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
45/// vectors respectively. These methods assume that `Self` contains a valid affine
46/// transform.
47#[derive(Clone, Copy)]
48#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
49#[cfg_attr(
50    feature = "zerocopy-08",
51    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
52)]
53#[repr(C)]
54pub struct DMat3 {
55    pub x_axis: DVec3,
56    pub y_axis: DVec3,
57    pub z_axis: DVec3,
58}
59
60impl DMat3 {
61    /// A 3x3 matrix with all elements set to `0.0`.
62    pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
63
64    /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
65    pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
66
67    /// All NAN:s.
68    pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
69
70    #[allow(clippy::too_many_arguments)]
71    #[inline(always)]
72    #[must_use]
73    const fn new(
74        m00: f64,
75        m01: f64,
76        m02: f64,
77        m10: f64,
78        m11: f64,
79        m12: f64,
80        m20: f64,
81        m21: f64,
82        m22: f64,
83    ) -> Self {
84        Self {
85            x_axis: DVec3::new(m00, m01, m02),
86            y_axis: DVec3::new(m10, m11, m12),
87            z_axis: DVec3::new(m20, m21, m22),
88        }
89    }
90
91    /// Creates a 3x3 matrix from three column vectors.
92    ///
93    /// See also [`Self::from_rows`] when the data is in row major order.
94    #[inline(always)]
95    #[must_use]
96    pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
97        Self {
98            x_axis,
99            y_axis,
100            z_axis,
101        }
102    }
103
104    /// Creates a 3x3 matrix from three row vectors.
105    ///
106    /// Matrices are stored in column major order, so the given rows are permuted into
107    /// the matrix layout. Use [`Self::from_cols`] instead when the data is already in
108    /// column major order.
109    #[inline(always)]
110    #[must_use]
111    pub const fn from_rows(row0: DVec3, row1: DVec3, row2: DVec3) -> Self {
112        let [m00, m01, m02] = row0.to_array();
113        let [m10, m11, m12] = row1.to_array();
114        let [m20, m21, m22] = row2.to_array();
115        Self::new(m00, m10, m20, m01, m11, m21, m02, m12, m22)
116    }
117
118    /// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order.
119    ///
120    /// If the data is in row major order use [`Self::from_rows_array`] instead.
121    #[inline]
122    #[must_use]
123    pub const fn from_cols_array(m: &[f64; 9]) -> Self {
124        Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
125    }
126
127    /// Creates a `[f64; 9]` array storing data in column major order.
128    ///
129    /// If you require the data in row major order use [`Self::to_rows_array`] instead.
130    #[inline]
131    #[must_use]
132    pub const fn to_cols_array(&self) -> [f64; 9] {
133        [
134            self.x_axis.x,
135            self.x_axis.y,
136            self.x_axis.z,
137            self.y_axis.x,
138            self.y_axis.y,
139            self.y_axis.z,
140            self.z_axis.x,
141            self.z_axis.y,
142            self.z_axis.z,
143        ]
144    }
145
146    /// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order.
147    ///
148    /// If the data is in row major order `transpose` the returned matrix.
149    #[inline]
150    #[must_use]
151    pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
152        Self::from_cols(
153            DVec3::from_array(m[0]),
154            DVec3::from_array(m[1]),
155            DVec3::from_array(m[2]),
156        )
157    }
158
159    /// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
160    ///
161    /// If you require row major order `transpose` the matrix first.
162    #[inline]
163    #[must_use]
164    pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
165        [
166            self.x_axis.to_array(),
167            self.y_axis.to_array(),
168            self.z_axis.to_array(),
169        ]
170    }
171
172    /// Creates a 3x3 matrix from a `[f64; 9]` array stored in row major order.
173    ///
174    /// Matrices are stored in column major order, so the array is permuted into the
175    /// matrix layout. Use [`Self::from_cols_array`] instead when the data is already in
176    /// column major order.
177    #[inline]
178    #[must_use]
179    pub const fn from_rows_array(m: &[f64; 9]) -> Self {
180        Self::new(m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8])
181    }
182
183    /// Creates a `[f64; 9]` array storing data in row major order.
184    ///
185    /// Matrices are stored in column major order, so the array is permuted out of the
186    /// column major storage. Use [`Self::to_cols_array`] instead when you want data in
187    /// column major order.
188    #[inline]
189    #[must_use]
190    pub const fn to_rows_array(&self) -> [f64; 9] {
191        let m = self.to_cols_array();
192        [m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]]
193    }
194
195    /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
196    #[doc(alias = "scale")]
197    #[inline]
198    #[must_use]
199    pub const fn from_diagonal(diagonal: DVec3) -> Self {
200        Self::new(
201            diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
202        )
203    }
204
205    /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
206    #[inline]
207    #[must_use]
208    pub fn from_mat4(m: DMat4) -> Self {
209        Self::from_cols(
210            DVec3::from_vec4(m.x_axis),
211            DVec3::from_vec4(m.y_axis),
212            DVec3::from_vec4(m.z_axis),
213        )
214    }
215
216    /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
217    /// and `j`th row.
218    ///
219    /// # Panics
220    ///
221    /// Panics if `i` or `j` is greater than 3.
222    #[inline]
223    #[must_use]
224    #[track_caller]
225    pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self {
226        match (i, j) {
227            (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
228            (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
229            (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
230            (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
231            (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
232            (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
233            (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
234            (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
235            (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
236            (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
237            (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
238            (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
239            (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
240            (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
241            (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
242            (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
243            _ => panic!("index out of bounds"),
244        }
245    }
246
247    /// Creates a 3D rotation matrix from the given quaternion.
248    ///
249    /// # Panics
250    ///
251    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
252    #[inline]
253    #[must_use]
254    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
255    pub fn from_quat(rotation: DQuat) -> Self {
256        glam_assert!(rotation.is_normalized());
257
258        let x2 = rotation.x + rotation.x;
259        let y2 = rotation.y + rotation.y;
260        let z2 = rotation.z + rotation.z;
261        let xx = rotation.x * x2;
262        let xy = rotation.x * y2;
263        let xz = rotation.x * z2;
264        let yy = rotation.y * y2;
265        let yz = rotation.y * z2;
266        let zz = rotation.z * z2;
267        let wx = rotation.w * x2;
268        let wy = rotation.w * y2;
269        let wz = rotation.w * z2;
270
271        Self::from_cols(
272            DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
273            DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
274            DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
275        )
276    }
277
278    /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
279    /// radians).
280    ///
281    /// # Panics
282    ///
283    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
284    #[inline]
285    #[must_use]
286    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
287    pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
288        glam_assert!(axis.is_normalized());
289
290        let (sin, cos) = math::sin_cos(angle);
291        let (xsin, ysin, zsin) = axis.mul(sin).into();
292        let (x, y, z) = axis.into();
293        let (x2, y2, z2) = axis.mul(axis).into();
294        let omc = 1.0 - cos;
295        let xyomc = x * y * omc;
296        let xzomc = x * z * omc;
297        let yzomc = y * z * omc;
298        Self::from_cols(
299            DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
300            DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
301            DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
302        )
303    }
304
305    /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
306    /// radians).
307    #[inline]
308    #[must_use]
309    pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
310        Self::from_euler_angles(order, a, b, c)
311    }
312
313    /// Extract Euler angles with the given Euler rotation order.
314    ///
315    /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
316    /// the resulting Euler angles will be ill-defined.
317    ///
318    /// # Panics
319    ///
320    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
321    #[inline]
322    #[must_use]
323    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
324    pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
325        glam_assert!(
326            self.x_axis.is_normalized()
327                && self.y_axis.is_normalized()
328                && self.z_axis.is_normalized()
329        );
330        self.to_euler_angles(order)
331    }
332
333    /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
334    #[inline]
335    #[must_use]
336    pub fn from_rotation_x(angle: f64) -> Self {
337        let (sina, cosa) = math::sin_cos(angle);
338        Self::from_cols(
339            DVec3::X,
340            DVec3::new(0.0, cosa, sina),
341            DVec3::new(0.0, -sina, cosa),
342        )
343    }
344
345    /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
346    #[inline]
347    #[must_use]
348    pub fn from_rotation_y(angle: f64) -> Self {
349        let (sina, cosa) = math::sin_cos(angle);
350        Self::from_cols(
351            DVec3::new(cosa, 0.0, -sina),
352            DVec3::Y,
353            DVec3::new(sina, 0.0, cosa),
354        )
355    }
356
357    /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
358    #[inline]
359    #[must_use]
360    pub fn from_rotation_z(angle: f64) -> Self {
361        let (sina, cosa) = math::sin_cos(angle);
362        Self::from_cols(
363            DVec3::new(cosa, sina, 0.0),
364            DVec3::new(-sina, cosa, 0.0),
365            DVec3::Z,
366        )
367    }
368
369    /// Creates an affine transformation matrix from the given 2D `translation`.
370    ///
371    /// The resulting matrix can be used to transform 2D points and vectors. See
372    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
373    #[inline]
374    #[must_use]
375    pub fn from_translation(translation: DVec2) -> Self {
376        Self::from_cols(
377            DVec3::X,
378            DVec3::Y,
379            DVec3::new(translation.x, translation.y, 1.0),
380        )
381    }
382
383    /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
384    /// radians).
385    ///
386    /// The resulting matrix can be used to transform 2D points and vectors. See
387    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
388    #[inline]
389    #[must_use]
390    pub fn from_angle(angle: f64) -> Self {
391        let (sin, cos) = math::sin_cos(angle);
392        Self::from_cols(
393            DVec3::new(cos, sin, 0.0),
394            DVec3::new(-sin, cos, 0.0),
395            DVec3::Z,
396        )
397    }
398
399    /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
400    /// radians) and `translation`.
401    ///
402    /// The resulting matrix can be used to transform 2D points and vectors. See
403    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
404    #[inline]
405    #[must_use]
406    pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
407        let (sin, cos) = math::sin_cos(angle);
408        Self::from_cols(
409            DVec3::new(cos * scale.x, sin * scale.x, 0.0),
410            DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
411            DVec3::new(translation.x, translation.y, 1.0),
412        )
413    }
414
415    /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
416    ///
417    /// The resulting matrix can be used to transform 2D points and vectors. See
418    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
419    ///
420    /// # Panics
421    ///
422    /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
423    #[inline]
424    #[must_use]
425    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
426    pub fn from_scale(scale: DVec2) -> Self {
427        // Do not panic as long as any component is non-zero
428        glam_assert!(scale.cmpne(DVec2::ZERO).any());
429
430        Self::from_cols(
431            DVec3::new(scale.x, 0.0, 0.0),
432            DVec3::new(0.0, scale.y, 0.0),
433            DVec3::Z,
434        )
435    }
436
437    /// Creates an affine transformation matrix from the given 2x2 matrix.
438    ///
439    /// The resulting matrix can be used to transform 2D points and vectors. See
440    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
441    #[inline]
442    pub fn from_mat2(m: DMat2) -> Self {
443        Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
444    }
445
446    /// Creates a 3x3 matrix from the first 9 values in `slice`.
447    ///
448    /// See also [`Self::from_rows_slice`] when the slice is in row major order.
449    ///
450    /// # Panics
451    ///
452    /// Panics if `slice` is less than 9 elements long.
453    #[inline]
454    #[must_use]
455    #[track_caller]
456    pub const fn from_cols_slice(slice: &[f64]) -> Self {
457        Self::new(
458            slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
459            slice[8],
460        )
461    }
462
463    /// Writes the columns of `self` to the first 9 elements in `slice`.
464    ///
465    /// # Panics
466    ///
467    /// Panics if `slice` is less than 9 elements long.
468    #[inline]
469    #[track_caller]
470    pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
471        slice[0] = self.x_axis.x;
472        slice[1] = self.x_axis.y;
473        slice[2] = self.x_axis.z;
474        slice[3] = self.y_axis.x;
475        slice[4] = self.y_axis.y;
476        slice[5] = self.y_axis.z;
477        slice[6] = self.z_axis.x;
478        slice[7] = self.z_axis.y;
479        slice[8] = self.z_axis.z;
480    }
481
482    /// Creates a 3x3 matrix from the first 9 values in `slice`, stored in row
483    /// major order.
484    ///
485    /// Matrices are stored in column major order, so the slice is permuted into the
486    /// matrix layout. Use [`Self::from_cols_slice`] instead when the slice is already in
487    /// column major order.
488    ///
489    /// # Panics
490    ///
491    /// Panics if `slice` is less than 9 elements long.
492    #[inline]
493    #[must_use]
494    #[track_caller]
495    pub const fn from_rows_slice(slice: &[f64]) -> Self {
496        Self::new(
497            slice[0], slice[3], slice[6], slice[1], slice[4], slice[7], slice[2], slice[5],
498            slice[8],
499        )
500    }
501
502    /// Returns the matrix column for the given `index`.
503    ///
504    /// # Panics
505    ///
506    /// Panics if `index` is greater than 2.
507    #[inline]
508    #[must_use]
509    #[track_caller]
510    pub fn col(&self, index: usize) -> DVec3 {
511        match index {
512            0 => self.x_axis,
513            1 => self.y_axis,
514            2 => self.z_axis,
515            _ => panic!("index out of bounds"),
516        }
517    }
518
519    /// Returns a mutable reference to the matrix column for the given `index`.
520    ///
521    /// # Panics
522    ///
523    /// Panics if `index` is greater than 2.
524    #[inline]
525    #[track_caller]
526    pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
527        match index {
528            0 => &mut self.x_axis,
529            1 => &mut self.y_axis,
530            2 => &mut self.z_axis,
531            _ => panic!("index out of bounds"),
532        }
533    }
534
535    /// Returns the matrix row for the given `index`.
536    ///
537    /// See also [`Self::set_row`] when you need to change the row.
538    ///
539    /// # Panics
540    ///
541    /// Panics if `index` is greater than 2.
542    #[inline]
543    #[must_use]
544    #[track_caller]
545    pub fn row(&self, index: usize) -> DVec3 {
546        match index {
547            0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
548            1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
549            2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
550            _ => panic!("index out of bounds"),
551        }
552    }
553
554    /// Sets the matrix row for the given `index`.
555    ///
556    /// Matrices are stored in column major order, so the row is spread across all
557    /// 3 columns and writing it touches every column. Use [`Self::col_mut`]
558    /// instead when you can work with columns. See also [`Self::row`].
559    ///
560    /// # Panics
561    ///
562    /// Panics if `index` is greater than 2.
563    #[inline]
564    #[track_caller]
565    pub fn set_row(&mut self, index: usize, row: DVec3) {
566        match index {
567            0 => {
568                self.x_axis.x = row.x;
569                self.y_axis.x = row.y;
570                self.z_axis.x = row.z;
571            }
572            1 => {
573                self.x_axis.y = row.x;
574                self.y_axis.y = row.y;
575                self.z_axis.y = row.z;
576            }
577            2 => {
578                self.x_axis.z = row.x;
579                self.y_axis.z = row.y;
580                self.z_axis.z = row.z;
581            }
582            _ => panic!("index out of bounds"),
583        }
584    }
585
586    /// Returns `true` if, and only if, all elements are finite.
587    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
588    #[inline]
589    #[must_use]
590    pub fn is_finite(&self) -> bool {
591        self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
592    }
593
594    /// Returns `true` if any elements are `NaN`.
595    #[inline]
596    #[must_use]
597    pub fn is_nan(&self) -> bool {
598        self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
599    }
600
601    /// Returns the transpose of `self`.
602    #[inline]
603    #[must_use]
604    pub fn transpose(&self) -> Self {
605        Self {
606            x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
607            y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
608            z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
609        }
610    }
611
612    /// Returns the diagonal of `self`.
613    #[inline]
614    #[must_use]
615    pub fn diagonal(&self) -> DVec3 {
616        DVec3::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
617    }
618
619    /// Returns the determinant of `self`.
620    #[inline]
621    #[must_use]
622    pub fn determinant(&self) -> f64 {
623        self.x_axis.dot(self.y_axis.cross(self.z_axis))
624    }
625
626    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
627    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
628    /// inverted matrix and true is returned.
629    ///
630    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
631    /// inverted matrix will be invalid. Will panic if the resulting inverted matrix is not finite
632    /// when `glam_assert` is enabled.
633    ///
634    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
635    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
636    /// matrix is aligned.
637    #[inline(always)]
638    #[must_use]
639    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
640    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
641        let tmp0 = self.y_axis.cross(self.z_axis);
642        let tmp1 = self.z_axis.cross(self.x_axis);
643        let tmp2 = self.x_axis.cross(self.y_axis);
644        let inv_det = DVec3::splat(1.0 / self.x_axis.dot(tmp0));
645        let m =
646            Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose();
647        if CHECKED {
648            if !m.is_finite() {
649                return (Self::ZERO, false);
650            }
651        } else {
652            glam_assert!(m.is_finite());
653        }
654        (m, true)
655    }
656
657    /// Returns the inverse of `self`.
658    ///
659    /// If the matrix is not invertible the returned matrix will be invalid. The
660    /// returned matrix will also be invalid if the inverse is not finite, which can
661    /// happen when `self` contains very large or very small values. Use
662    /// [`Self::try_inverse`] or [`Self::inverse_or_zero`] to detect these cases.
663    ///
664    /// # Panics
665    ///
666    /// Will panic if the resulting inverted matrix is not finite when `glam_assert`
667    /// is enabled.
668    #[inline]
669    #[must_use]
670    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
671    pub fn inverse(&self) -> Self {
672        self.inverse_checked::<false>().0
673    }
674
675    /// Returns the inverse of `self` or `None` if the matrix is not invertible, or if
676    /// the inverse is not finite.
677    #[inline]
678    #[must_use]
679    pub fn try_inverse(&self) -> Option<Self> {
680        let (m, is_valid) = self.inverse_checked::<true>();
681        if is_valid { Some(m) } else { None }
682    }
683
684    /// Returns the inverse of `self` or `DMat3::ZERO` if the matrix is not
685    /// invertible, or if the inverse is not finite.
686    #[inline]
687    #[must_use]
688    pub fn inverse_or_zero(&self) -> Self {
689        self.inverse_checked::<true>().0
690    }
691
692    /// Transforms the given 2D vector as a point.
693    ///
694    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
695    ///
696    /// This method assumes that `self` contains a valid affine transform.
697    ///
698    /// # Panics
699    ///
700    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
701    #[inline]
702    #[must_use]
703    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
704    pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
705        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
706        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
707    }
708
709    /// Rotates the given 2D vector.
710    ///
711    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
712    ///
713    /// This method assumes that `self` contains a valid affine transform.
714    ///
715    /// # Panics
716    ///
717    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
718    #[inline]
719    #[must_use]
720    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
721    pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
722        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
723        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
724    }
725
726    /// Transforms a 3D vector.
727    #[inline]
728    #[must_use]
729    pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
730        let mut res = self.x_axis.mul(rhs.x);
731        res = res.add(self.y_axis.mul(rhs.y));
732        res = res.add(self.z_axis.mul(rhs.z));
733        res
734    }
735
736    /// Transforms a 3D vector by the transpose of `self`.
737    #[inline]
738    #[must_use]
739    pub fn transpose_mul_vec3(&self, rhs: DVec3) -> DVec3 {
740        DVec3::new(
741            self.x_axis.dot(rhs),
742            self.y_axis.dot(rhs),
743            self.z_axis.dot(rhs),
744        )
745    }
746
747    /// Transforms a 3D vector by the transpose of `self`.
748    #[inline]
749    #[must_use]
750    #[deprecated(
751        since = "0.34.2",
752        note = "Use `transpose_mul_vec3` instead, whose word order matches its order of operations and is consistent with `transpose().mul_vec3`."
753    )]
754    pub fn mul_transpose_vec3(&self, rhs: DVec3) -> DVec3 {
755        self.transpose_mul_vec3(rhs)
756    }
757
758    /// Multiplies two 3x3 matrices.
759    #[inline]
760    #[must_use]
761    pub fn mul_mat3(&self, rhs: &Self) -> Self {
762        self.mul(rhs)
763    }
764
765    /// Adds two 3x3 matrices.
766    #[inline]
767    #[must_use]
768    pub fn add_mat3(&self, rhs: &Self) -> Self {
769        self.add(rhs)
770    }
771
772    /// Subtracts two 3x3 matrices.
773    #[inline]
774    #[must_use]
775    pub fn sub_mat3(&self, rhs: &Self) -> Self {
776        self.sub(rhs)
777    }
778
779    /// Multiplies a 3x3 matrix by a scalar.
780    #[inline]
781    #[must_use]
782    pub fn mul_scalar(&self, rhs: f64) -> Self {
783        Self::from_cols(
784            self.x_axis.mul(rhs),
785            self.y_axis.mul(rhs),
786            self.z_axis.mul(rhs),
787        )
788    }
789
790    /// Multiply `self` by a scaling vector `scale`.
791    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
792    /// This operation is commutative.
793    #[inline]
794    #[must_use]
795    pub fn mul_diagonal_scale(&self, scale: DVec3) -> Self {
796        Self::from_cols(
797            self.x_axis * scale.x,
798            self.y_axis * scale.y,
799            self.z_axis * scale.z,
800        )
801    }
802
803    /// Divides a 3x3 matrix by a scalar.
804    #[inline]
805    #[must_use]
806    pub fn div_scalar(&self, rhs: f64) -> Self {
807        let rhs = DVec3::splat(rhs);
808        Self::from_cols(
809            self.x_axis.div(rhs),
810            self.y_axis.div(rhs),
811            self.z_axis.div(rhs),
812        )
813    }
814
815    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
816    #[inline]
817    #[must_use]
818    pub fn recip(&self) -> Self {
819        Self::from_cols(
820            self.x_axis.recip(),
821            self.y_axis.recip(),
822            self.z_axis.recip(),
823        )
824    }
825
826    /// Returns true if the absolute difference of all elements between `self` and `rhs`
827    /// is less than or equal to `max_abs_diff`.
828    ///
829    /// This can be used to compare if two matrices contain similar elements. It works best
830    /// when comparing with a known value. The `max_abs_diff` that should be used used
831    /// depends on the values being compared against.
832    ///
833    /// For more see
834    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
835    #[inline]
836    #[must_use]
837    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
838        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
839            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
840            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
841    }
842
843    /// Takes the absolute value of each element in `self`
844    #[inline]
845    #[must_use]
846    pub fn abs(&self) -> Self {
847        Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
848    }
849
850    #[cfg(feature = "f64")]
851    #[inline]
852    #[must_use]
853    pub fn as_mat3(&self) -> Mat3 {
854        Mat3::from_cols(
855            self.x_axis.as_vec3(),
856            self.y_axis.as_vec3(),
857            self.z_axis.as_vec3(),
858        )
859    }
860}
861
862impl Default for DMat3 {
863    #[inline]
864    fn default() -> Self {
865        Self::IDENTITY
866    }
867}
868
869impl Add for DMat3 {
870    type Output = Self;
871    #[inline]
872    fn add(self, rhs: Self) -> Self {
873        Self::from_cols(
874            self.x_axis.add(rhs.x_axis),
875            self.y_axis.add(rhs.y_axis),
876            self.z_axis.add(rhs.z_axis),
877        )
878    }
879}
880
881impl Add<&Self> for DMat3 {
882    type Output = Self;
883    #[inline]
884    fn add(self, rhs: &Self) -> Self {
885        self.add(*rhs)
886    }
887}
888
889impl Add<&DMat3> for &DMat3 {
890    type Output = DMat3;
891    #[inline]
892    fn add(self, rhs: &DMat3) -> DMat3 {
893        (*self).add(*rhs)
894    }
895}
896
897impl Add<DMat3> for &DMat3 {
898    type Output = DMat3;
899    #[inline]
900    fn add(self, rhs: DMat3) -> DMat3 {
901        (*self).add(rhs)
902    }
903}
904
905impl AddAssign for DMat3 {
906    #[inline]
907    fn add_assign(&mut self, rhs: Self) {
908        *self = self.add(rhs);
909    }
910}
911
912impl AddAssign<&Self> for DMat3 {
913    #[inline]
914    fn add_assign(&mut self, rhs: &Self) {
915        self.add_assign(*rhs);
916    }
917}
918
919impl Sub for DMat3 {
920    type Output = Self;
921    #[inline]
922    fn sub(self, rhs: Self) -> Self {
923        Self::from_cols(
924            self.x_axis.sub(rhs.x_axis),
925            self.y_axis.sub(rhs.y_axis),
926            self.z_axis.sub(rhs.z_axis),
927        )
928    }
929}
930
931impl Sub<&Self> for DMat3 {
932    type Output = Self;
933    #[inline]
934    fn sub(self, rhs: &Self) -> Self {
935        self.sub(*rhs)
936    }
937}
938
939impl Sub<&DMat3> for &DMat3 {
940    type Output = DMat3;
941    #[inline]
942    fn sub(self, rhs: &DMat3) -> DMat3 {
943        (*self).sub(*rhs)
944    }
945}
946
947impl Sub<DMat3> for &DMat3 {
948    type Output = DMat3;
949    #[inline]
950    fn sub(self, rhs: DMat3) -> DMat3 {
951        (*self).sub(rhs)
952    }
953}
954
955impl SubAssign for DMat3 {
956    #[inline]
957    fn sub_assign(&mut self, rhs: Self) {
958        *self = self.sub(rhs);
959    }
960}
961
962impl SubAssign<&Self> for DMat3 {
963    #[inline]
964    fn sub_assign(&mut self, rhs: &Self) {
965        self.sub_assign(*rhs);
966    }
967}
968
969impl Neg for DMat3 {
970    type Output = Self;
971    #[inline]
972    fn neg(self) -> Self::Output {
973        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
974    }
975}
976
977impl Neg for &DMat3 {
978    type Output = DMat3;
979    #[inline]
980    fn neg(self) -> DMat3 {
981        (*self).neg()
982    }
983}
984
985impl Mul for DMat3 {
986    type Output = Self;
987    #[inline]
988    fn mul(self, rhs: Self) -> Self {
989        Self::from_cols(
990            self.mul(rhs.x_axis),
991            self.mul(rhs.y_axis),
992            self.mul(rhs.z_axis),
993        )
994    }
995}
996
997impl Mul<&Self> for DMat3 {
998    type Output = Self;
999    #[inline]
1000    fn mul(self, rhs: &Self) -> Self {
1001        self.mul(*rhs)
1002    }
1003}
1004
1005impl Mul<&DMat3> for &DMat3 {
1006    type Output = DMat3;
1007    #[inline]
1008    fn mul(self, rhs: &DMat3) -> DMat3 {
1009        (*self).mul(*rhs)
1010    }
1011}
1012
1013impl Mul<DMat3> for &DMat3 {
1014    type Output = DMat3;
1015    #[inline]
1016    fn mul(self, rhs: DMat3) -> DMat3 {
1017        (*self).mul(rhs)
1018    }
1019}
1020
1021impl MulAssign for DMat3 {
1022    #[inline]
1023    fn mul_assign(&mut self, rhs: Self) {
1024        *self = self.mul(rhs);
1025    }
1026}
1027
1028impl MulAssign<&Self> for DMat3 {
1029    #[inline]
1030    fn mul_assign(&mut self, rhs: &Self) {
1031        self.mul_assign(*rhs);
1032    }
1033}
1034
1035impl Mul<DVec3> for DMat3 {
1036    type Output = DVec3;
1037    #[inline]
1038    fn mul(self, rhs: DVec3) -> Self::Output {
1039        self.mul_vec3(rhs)
1040    }
1041}
1042
1043impl Mul<&DVec3> for DMat3 {
1044    type Output = DVec3;
1045    #[inline]
1046    fn mul(self, rhs: &DVec3) -> DVec3 {
1047        self.mul(*rhs)
1048    }
1049}
1050
1051impl Mul<&DVec3> for &DMat3 {
1052    type Output = DVec3;
1053    #[inline]
1054    fn mul(self, rhs: &DVec3) -> DVec3 {
1055        (*self).mul(*rhs)
1056    }
1057}
1058
1059impl Mul<DVec3> for &DMat3 {
1060    type Output = DVec3;
1061    #[inline]
1062    fn mul(self, rhs: DVec3) -> DVec3 {
1063        (*self).mul(rhs)
1064    }
1065}
1066
1067impl Mul<DMat3> for f64 {
1068    type Output = DMat3;
1069    #[inline]
1070    fn mul(self, rhs: DMat3) -> Self::Output {
1071        rhs.mul_scalar(self)
1072    }
1073}
1074
1075impl Mul<&DMat3> for f64 {
1076    type Output = DMat3;
1077    #[inline]
1078    fn mul(self, rhs: &DMat3) -> DMat3 {
1079        self.mul(*rhs)
1080    }
1081}
1082
1083impl Mul<&DMat3> for &f64 {
1084    type Output = DMat3;
1085    #[inline]
1086    fn mul(self, rhs: &DMat3) -> DMat3 {
1087        (*self).mul(*rhs)
1088    }
1089}
1090
1091impl Mul<DMat3> for &f64 {
1092    type Output = DMat3;
1093    #[inline]
1094    fn mul(self, rhs: DMat3) -> DMat3 {
1095        (*self).mul(rhs)
1096    }
1097}
1098
1099impl Mul<f64> for DMat3 {
1100    type Output = Self;
1101    #[inline]
1102    fn mul(self, rhs: f64) -> Self {
1103        self.mul_scalar(rhs)
1104    }
1105}
1106
1107impl Mul<&f64> for DMat3 {
1108    type Output = Self;
1109    #[inline]
1110    fn mul(self, rhs: &f64) -> Self {
1111        self.mul(*rhs)
1112    }
1113}
1114
1115impl Mul<&f64> for &DMat3 {
1116    type Output = DMat3;
1117    #[inline]
1118    fn mul(self, rhs: &f64) -> DMat3 {
1119        (*self).mul(*rhs)
1120    }
1121}
1122
1123impl Mul<f64> for &DMat3 {
1124    type Output = DMat3;
1125    #[inline]
1126    fn mul(self, rhs: f64) -> DMat3 {
1127        (*self).mul(rhs)
1128    }
1129}
1130
1131impl MulAssign<f64> for DMat3 {
1132    #[inline]
1133    fn mul_assign(&mut self, rhs: f64) {
1134        *self = self.mul(rhs);
1135    }
1136}
1137
1138impl MulAssign<&f64> for DMat3 {
1139    #[inline]
1140    fn mul_assign(&mut self, rhs: &f64) {
1141        self.mul_assign(*rhs);
1142    }
1143}
1144
1145impl Div<DMat3> for f64 {
1146    type Output = DMat3;
1147    #[inline]
1148    fn div(self, rhs: DMat3) -> Self::Output {
1149        DMat3::from_cols(
1150            self.div(rhs.x_axis),
1151            self.div(rhs.y_axis),
1152            self.div(rhs.z_axis),
1153        )
1154    }
1155}
1156
1157impl Div<&DMat3> for f64 {
1158    type Output = DMat3;
1159    #[inline]
1160    fn div(self, rhs: &DMat3) -> DMat3 {
1161        self.div(*rhs)
1162    }
1163}
1164
1165impl Div<&DMat3> for &f64 {
1166    type Output = DMat3;
1167    #[inline]
1168    fn div(self, rhs: &DMat3) -> DMat3 {
1169        (*self).div(*rhs)
1170    }
1171}
1172
1173impl Div<DMat3> for &f64 {
1174    type Output = DMat3;
1175    #[inline]
1176    fn div(self, rhs: DMat3) -> DMat3 {
1177        (*self).div(rhs)
1178    }
1179}
1180
1181impl Div<f64> for DMat3 {
1182    type Output = Self;
1183    #[inline]
1184    fn div(self, rhs: f64) -> Self {
1185        self.div_scalar(rhs)
1186    }
1187}
1188
1189impl Div<&f64> for DMat3 {
1190    type Output = Self;
1191    #[inline]
1192    fn div(self, rhs: &f64) -> Self {
1193        self.div(*rhs)
1194    }
1195}
1196
1197impl Div<&f64> for &DMat3 {
1198    type Output = DMat3;
1199    #[inline]
1200    fn div(self, rhs: &f64) -> DMat3 {
1201        (*self).div(*rhs)
1202    }
1203}
1204
1205impl Div<f64> for &DMat3 {
1206    type Output = DMat3;
1207    #[inline]
1208    fn div(self, rhs: f64) -> DMat3 {
1209        (*self).div(rhs)
1210    }
1211}
1212
1213impl DivAssign<f64> for DMat3 {
1214    #[inline]
1215    fn div_assign(&mut self, rhs: f64) {
1216        *self = self.div(rhs);
1217    }
1218}
1219
1220impl DivAssign<&f64> for DMat3 {
1221    #[inline]
1222    fn div_assign(&mut self, rhs: &f64) {
1223        self.div_assign(*rhs);
1224    }
1225}
1226
1227impl Sum<Self> for DMat3 {
1228    fn sum<I>(iter: I) -> Self
1229    where
1230        I: Iterator<Item = Self>,
1231    {
1232        iter.fold(Self::ZERO, Self::add)
1233    }
1234}
1235
1236impl<'a> Sum<&'a Self> for DMat3 {
1237    fn sum<I>(iter: I) -> Self
1238    where
1239        I: Iterator<Item = &'a Self>,
1240    {
1241        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1242    }
1243}
1244
1245impl Product for DMat3 {
1246    fn product<I>(iter: I) -> Self
1247    where
1248        I: Iterator<Item = Self>,
1249    {
1250        iter.fold(Self::IDENTITY, Self::mul)
1251    }
1252}
1253
1254impl<'a> Product<&'a Self> for DMat3 {
1255    fn product<I>(iter: I) -> Self
1256    where
1257        I: Iterator<Item = &'a Self>,
1258    {
1259        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1260    }
1261}
1262
1263impl PartialEq for DMat3 {
1264    #[inline]
1265    fn eq(&self, rhs: &Self) -> bool {
1266        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
1267    }
1268}
1269
1270impl AsRef<[f64; 9]> for DMat3 {
1271    #[inline]
1272    fn as_ref(&self) -> &[f64; 9] {
1273        unsafe { &*(self as *const Self as *const [f64; 9]) }
1274    }
1275}
1276
1277impl AsMut<[f64; 9]> for DMat3 {
1278    #[inline]
1279    fn as_mut(&mut self) -> &mut [f64; 9] {
1280        unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
1281    }
1282}
1283
1284impl fmt::Debug for DMat3 {
1285    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1286        fmt.debug_struct(stringify!(DMat3))
1287            .field("x_axis", &self.x_axis)
1288            .field("y_axis", &self.y_axis)
1289            .field("z_axis", &self.z_axis)
1290            .finish()
1291    }
1292}
1293
1294impl fmt::Display for DMat3 {
1295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1296        if let Some(p) = f.precision() {
1297            write!(
1298                f,
1299                "[{:.*}, {:.*}, {:.*}]",
1300                p, self.x_axis, p, self.y_axis, p, self.z_axis
1301            )
1302        } else {
1303            write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
1304        }
1305    }
1306}