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    euler::{FromEuler, ToEuler},
5    f64::math,
6    swizzles::*,
7    DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3,
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 {
682            Some(m)
683        } else {
684            None
685        }
686    }
687
688    /// Returns the inverse of `self` or `DMat3::ZERO` if the matrix is not
689    /// invertible, or if the inverse is not finite.
690    #[inline]
691    #[must_use]
692    pub fn inverse_or_zero(&self) -> Self {
693        self.inverse_checked::<true>().0
694    }
695
696    /// Transforms the given 2D vector as a point.
697    ///
698    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
699    ///
700    /// This method assumes that `self` contains a valid affine transform.
701    ///
702    /// # Panics
703    ///
704    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
705    #[inline]
706    #[must_use]
707    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
708    pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
709        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
710        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
711    }
712
713    /// Rotates the given 2D vector.
714    ///
715    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
716    ///
717    /// This method assumes that `self` contains a valid affine transform.
718    ///
719    /// # Panics
720    ///
721    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
722    #[inline]
723    #[must_use]
724    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
725    pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
726        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
727        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
728    }
729
730    /// Creates a left-handed view matrix using a facing direction and an up direction.
731    ///
732    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
733    ///
734    /// # Panics
735    ///
736    /// Will panic if `dir` or `up` are not normalized, or if `dir` and `up` are parallel,
737    /// when `glam_assert` is enabled.
738    #[deprecated(
739        since = "0.33.1",
740        note = "use the `glam::dcamera::lh::view::look_to_mat3` function instead"
741    )]
742    #[inline]
743    #[must_use]
744    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
745    pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self {
746        #[allow(deprecated)]
747        Self::look_to_rh(-dir, up)
748    }
749
750    /// Creates a right-handed view matrix using a facing direction and an up direction.
751    ///
752    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
753    ///
754    /// # Panics
755    ///
756    /// Will panic if `dir` or `up` are not normalized, or if `dir` and `up` are parallel,
757    /// when `glam_assert` is enabled.
758    #[deprecated(
759        since = "0.33.1",
760        note = "use the `glam::dcamera::rh::view::look_to_mat3` function instead"
761    )]
762    #[inline]
763    #[must_use]
764    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
765    pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self {
766        glam_assert!(dir.is_normalized());
767        glam_assert!(up.is_normalized());
768        let f = dir;
769        let s = f.cross(up).normalize();
770        let u = s.cross(f);
771
772        Self::from_cols(
773            DVec3::new(s.x, u.x, -f.x),
774            DVec3::new(s.y, u.y, -f.y),
775            DVec3::new(s.z, u.z, -f.z),
776        )
777    }
778
779    /// Creates a left-handed view matrix using a camera position, a focal point and an up
780    /// direction.
781    ///
782    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
783    ///
784    /// # Panics
785    ///
786    /// Will panic if `up` is not normalized, if `center` is equal to `eye`, or if the view
787    /// direction is parallel to `up`, when `glam_assert` is enabled.
788    #[deprecated(
789        since = "0.33.1",
790        note = "use the `glam::dcamera::lh::view::look_at_mat3` function instead"
791    )]
792    #[inline]
793    #[must_use]
794    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
795    pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
796        #[allow(deprecated)]
797        Self::look_to_lh(center.sub(eye).normalize(), up)
798    }
799
800    /// Creates a right-handed view matrix using a camera position, a focal point and an up
801    /// direction.
802    ///
803    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
804    ///
805    /// # Panics
806    ///
807    /// Will panic if `up` is not normalized, if `center` is equal to `eye`, or if the view
808    /// direction is parallel to `up`, when `glam_assert` is enabled.
809    #[deprecated(
810        since = "0.33.1",
811        note = "use the `glam::dcamera::rh::view::look_at_mat3` function instead"
812    )]
813    #[inline]
814    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
815    pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
816        #[allow(deprecated)]
817        Self::look_to_rh(center.sub(eye).normalize(), up)
818    }
819
820    /// Transforms a 3D vector.
821    #[inline]
822    #[must_use]
823    pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
824        let mut res = self.x_axis.mul(rhs.x);
825        res = res.add(self.y_axis.mul(rhs.y));
826        res = res.add(self.z_axis.mul(rhs.z));
827        res
828    }
829
830    /// Transforms a 3D vector by the transpose of `self`.
831    #[inline]
832    #[must_use]
833    pub fn mul_transpose_vec3(&self, rhs: DVec3) -> DVec3 {
834        DVec3::new(
835            self.x_axis.dot(rhs),
836            self.y_axis.dot(rhs),
837            self.z_axis.dot(rhs),
838        )
839    }
840
841    /// Multiplies two 3x3 matrices.
842    #[inline]
843    #[must_use]
844    pub fn mul_mat3(&self, rhs: &Self) -> Self {
845        self.mul(rhs)
846    }
847
848    /// Adds two 3x3 matrices.
849    #[inline]
850    #[must_use]
851    pub fn add_mat3(&self, rhs: &Self) -> Self {
852        self.add(rhs)
853    }
854
855    /// Subtracts two 3x3 matrices.
856    #[inline]
857    #[must_use]
858    pub fn sub_mat3(&self, rhs: &Self) -> Self {
859        self.sub(rhs)
860    }
861
862    /// Multiplies a 3x3 matrix by a scalar.
863    #[inline]
864    #[must_use]
865    pub fn mul_scalar(&self, rhs: f64) -> Self {
866        Self::from_cols(
867            self.x_axis.mul(rhs),
868            self.y_axis.mul(rhs),
869            self.z_axis.mul(rhs),
870        )
871    }
872
873    /// Multiply `self` by a scaling vector `scale`.
874    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
875    /// This operation is commutative.
876    #[inline]
877    #[must_use]
878    pub fn mul_diagonal_scale(&self, scale: DVec3) -> Self {
879        Self::from_cols(
880            self.x_axis * scale.x,
881            self.y_axis * scale.y,
882            self.z_axis * scale.z,
883        )
884    }
885
886    /// Divides a 3x3 matrix by a scalar.
887    #[inline]
888    #[must_use]
889    pub fn div_scalar(&self, rhs: f64) -> Self {
890        let rhs = DVec3::splat(rhs);
891        Self::from_cols(
892            self.x_axis.div(rhs),
893            self.y_axis.div(rhs),
894            self.z_axis.div(rhs),
895        )
896    }
897
898    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
899    #[inline]
900    #[must_use]
901    pub fn recip(&self) -> Self {
902        Self::from_cols(
903            self.x_axis.recip(),
904            self.y_axis.recip(),
905            self.z_axis.recip(),
906        )
907    }
908
909    /// Returns true if the absolute difference of all elements between `self` and `rhs`
910    /// is less than or equal to `max_abs_diff`.
911    ///
912    /// This can be used to compare if two matrices contain similar elements. It works best
913    /// when comparing with a known value. The `max_abs_diff` that should be used used
914    /// depends on the values being compared against.
915    ///
916    /// For more see
917    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
918    #[inline]
919    #[must_use]
920    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
921        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
922            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
923            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
924    }
925
926    /// Takes the absolute value of each element in `self`
927    #[inline]
928    #[must_use]
929    pub fn abs(&self) -> Self {
930        Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
931    }
932
933    #[cfg(feature = "f64")]
934    #[inline]
935    #[must_use]
936    pub fn as_mat3(&self) -> Mat3 {
937        Mat3::from_cols(
938            self.x_axis.as_vec3(),
939            self.y_axis.as_vec3(),
940            self.z_axis.as_vec3(),
941        )
942    }
943}
944
945impl Default for DMat3 {
946    #[inline]
947    fn default() -> Self {
948        Self::IDENTITY
949    }
950}
951
952impl Add for DMat3 {
953    type Output = Self;
954    #[inline]
955    fn add(self, rhs: Self) -> Self {
956        Self::from_cols(
957            self.x_axis.add(rhs.x_axis),
958            self.y_axis.add(rhs.y_axis),
959            self.z_axis.add(rhs.z_axis),
960        )
961    }
962}
963
964impl Add<&Self> for DMat3 {
965    type Output = Self;
966    #[inline]
967    fn add(self, rhs: &Self) -> Self {
968        self.add(*rhs)
969    }
970}
971
972impl Add<&DMat3> for &DMat3 {
973    type Output = DMat3;
974    #[inline]
975    fn add(self, rhs: &DMat3) -> DMat3 {
976        (*self).add(*rhs)
977    }
978}
979
980impl Add<DMat3> for &DMat3 {
981    type Output = DMat3;
982    #[inline]
983    fn add(self, rhs: DMat3) -> DMat3 {
984        (*self).add(rhs)
985    }
986}
987
988impl AddAssign for DMat3 {
989    #[inline]
990    fn add_assign(&mut self, rhs: Self) {
991        *self = self.add(rhs);
992    }
993}
994
995impl AddAssign<&Self> for DMat3 {
996    #[inline]
997    fn add_assign(&mut self, rhs: &Self) {
998        self.add_assign(*rhs);
999    }
1000}
1001
1002impl Sub for DMat3 {
1003    type Output = Self;
1004    #[inline]
1005    fn sub(self, rhs: Self) -> Self {
1006        Self::from_cols(
1007            self.x_axis.sub(rhs.x_axis),
1008            self.y_axis.sub(rhs.y_axis),
1009            self.z_axis.sub(rhs.z_axis),
1010        )
1011    }
1012}
1013
1014impl Sub<&Self> for DMat3 {
1015    type Output = Self;
1016    #[inline]
1017    fn sub(self, rhs: &Self) -> Self {
1018        self.sub(*rhs)
1019    }
1020}
1021
1022impl Sub<&DMat3> for &DMat3 {
1023    type Output = DMat3;
1024    #[inline]
1025    fn sub(self, rhs: &DMat3) -> DMat3 {
1026        (*self).sub(*rhs)
1027    }
1028}
1029
1030impl Sub<DMat3> for &DMat3 {
1031    type Output = DMat3;
1032    #[inline]
1033    fn sub(self, rhs: DMat3) -> DMat3 {
1034        (*self).sub(rhs)
1035    }
1036}
1037
1038impl SubAssign for DMat3 {
1039    #[inline]
1040    fn sub_assign(&mut self, rhs: Self) {
1041        *self = self.sub(rhs);
1042    }
1043}
1044
1045impl SubAssign<&Self> for DMat3 {
1046    #[inline]
1047    fn sub_assign(&mut self, rhs: &Self) {
1048        self.sub_assign(*rhs);
1049    }
1050}
1051
1052impl Neg for DMat3 {
1053    type Output = Self;
1054    #[inline]
1055    fn neg(self) -> Self::Output {
1056        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
1057    }
1058}
1059
1060impl Neg for &DMat3 {
1061    type Output = DMat3;
1062    #[inline]
1063    fn neg(self) -> DMat3 {
1064        (*self).neg()
1065    }
1066}
1067
1068impl Mul for DMat3 {
1069    type Output = Self;
1070    #[inline]
1071    fn mul(self, rhs: Self) -> Self {
1072        Self::from_cols(
1073            self.mul(rhs.x_axis),
1074            self.mul(rhs.y_axis),
1075            self.mul(rhs.z_axis),
1076        )
1077    }
1078}
1079
1080impl Mul<&Self> for DMat3 {
1081    type Output = Self;
1082    #[inline]
1083    fn mul(self, rhs: &Self) -> Self {
1084        self.mul(*rhs)
1085    }
1086}
1087
1088impl Mul<&DMat3> for &DMat3 {
1089    type Output = DMat3;
1090    #[inline]
1091    fn mul(self, rhs: &DMat3) -> DMat3 {
1092        (*self).mul(*rhs)
1093    }
1094}
1095
1096impl Mul<DMat3> for &DMat3 {
1097    type Output = DMat3;
1098    #[inline]
1099    fn mul(self, rhs: DMat3) -> DMat3 {
1100        (*self).mul(rhs)
1101    }
1102}
1103
1104impl MulAssign for DMat3 {
1105    #[inline]
1106    fn mul_assign(&mut self, rhs: Self) {
1107        *self = self.mul(rhs);
1108    }
1109}
1110
1111impl MulAssign<&Self> for DMat3 {
1112    #[inline]
1113    fn mul_assign(&mut self, rhs: &Self) {
1114        self.mul_assign(*rhs);
1115    }
1116}
1117
1118impl Mul<DVec3> for DMat3 {
1119    type Output = DVec3;
1120    #[inline]
1121    fn mul(self, rhs: DVec3) -> Self::Output {
1122        self.mul_vec3(rhs)
1123    }
1124}
1125
1126impl Mul<&DVec3> for DMat3 {
1127    type Output = DVec3;
1128    #[inline]
1129    fn mul(self, rhs: &DVec3) -> DVec3 {
1130        self.mul(*rhs)
1131    }
1132}
1133
1134impl Mul<&DVec3> for &DMat3 {
1135    type Output = DVec3;
1136    #[inline]
1137    fn mul(self, rhs: &DVec3) -> DVec3 {
1138        (*self).mul(*rhs)
1139    }
1140}
1141
1142impl Mul<DVec3> for &DMat3 {
1143    type Output = DVec3;
1144    #[inline]
1145    fn mul(self, rhs: DVec3) -> DVec3 {
1146        (*self).mul(rhs)
1147    }
1148}
1149
1150impl Mul<DMat3> for f64 {
1151    type Output = DMat3;
1152    #[inline]
1153    fn mul(self, rhs: DMat3) -> Self::Output {
1154        rhs.mul_scalar(self)
1155    }
1156}
1157
1158impl Mul<&DMat3> for f64 {
1159    type Output = DMat3;
1160    #[inline]
1161    fn mul(self, rhs: &DMat3) -> DMat3 {
1162        self.mul(*rhs)
1163    }
1164}
1165
1166impl Mul<&DMat3> for &f64 {
1167    type Output = DMat3;
1168    #[inline]
1169    fn mul(self, rhs: &DMat3) -> DMat3 {
1170        (*self).mul(*rhs)
1171    }
1172}
1173
1174impl Mul<DMat3> for &f64 {
1175    type Output = DMat3;
1176    #[inline]
1177    fn mul(self, rhs: DMat3) -> DMat3 {
1178        (*self).mul(rhs)
1179    }
1180}
1181
1182impl Mul<f64> for DMat3 {
1183    type Output = Self;
1184    #[inline]
1185    fn mul(self, rhs: f64) -> Self {
1186        self.mul_scalar(rhs)
1187    }
1188}
1189
1190impl Mul<&f64> for DMat3 {
1191    type Output = Self;
1192    #[inline]
1193    fn mul(self, rhs: &f64) -> Self {
1194        self.mul(*rhs)
1195    }
1196}
1197
1198impl Mul<&f64> for &DMat3 {
1199    type Output = DMat3;
1200    #[inline]
1201    fn mul(self, rhs: &f64) -> DMat3 {
1202        (*self).mul(*rhs)
1203    }
1204}
1205
1206impl Mul<f64> for &DMat3 {
1207    type Output = DMat3;
1208    #[inline]
1209    fn mul(self, rhs: f64) -> DMat3 {
1210        (*self).mul(rhs)
1211    }
1212}
1213
1214impl MulAssign<f64> for DMat3 {
1215    #[inline]
1216    fn mul_assign(&mut self, rhs: f64) {
1217        *self = self.mul(rhs);
1218    }
1219}
1220
1221impl MulAssign<&f64> for DMat3 {
1222    #[inline]
1223    fn mul_assign(&mut self, rhs: &f64) {
1224        self.mul_assign(*rhs);
1225    }
1226}
1227
1228impl Div<DMat3> for f64 {
1229    type Output = DMat3;
1230    #[inline]
1231    fn div(self, rhs: DMat3) -> Self::Output {
1232        DMat3::from_cols(
1233            self.div(rhs.x_axis),
1234            self.div(rhs.y_axis),
1235            self.div(rhs.z_axis),
1236        )
1237    }
1238}
1239
1240impl Div<&DMat3> for f64 {
1241    type Output = DMat3;
1242    #[inline]
1243    fn div(self, rhs: &DMat3) -> DMat3 {
1244        self.div(*rhs)
1245    }
1246}
1247
1248impl Div<&DMat3> for &f64 {
1249    type Output = DMat3;
1250    #[inline]
1251    fn div(self, rhs: &DMat3) -> DMat3 {
1252        (*self).div(*rhs)
1253    }
1254}
1255
1256impl Div<DMat3> for &f64 {
1257    type Output = DMat3;
1258    #[inline]
1259    fn div(self, rhs: DMat3) -> DMat3 {
1260        (*self).div(rhs)
1261    }
1262}
1263
1264impl Div<f64> for DMat3 {
1265    type Output = Self;
1266    #[inline]
1267    fn div(self, rhs: f64) -> Self {
1268        self.div_scalar(rhs)
1269    }
1270}
1271
1272impl Div<&f64> for DMat3 {
1273    type Output = Self;
1274    #[inline]
1275    fn div(self, rhs: &f64) -> Self {
1276        self.div(*rhs)
1277    }
1278}
1279
1280impl Div<&f64> for &DMat3 {
1281    type Output = DMat3;
1282    #[inline]
1283    fn div(self, rhs: &f64) -> DMat3 {
1284        (*self).div(*rhs)
1285    }
1286}
1287
1288impl Div<f64> for &DMat3 {
1289    type Output = DMat3;
1290    #[inline]
1291    fn div(self, rhs: f64) -> DMat3 {
1292        (*self).div(rhs)
1293    }
1294}
1295
1296impl DivAssign<f64> for DMat3 {
1297    #[inline]
1298    fn div_assign(&mut self, rhs: f64) {
1299        *self = self.div(rhs);
1300    }
1301}
1302
1303impl DivAssign<&f64> for DMat3 {
1304    #[inline]
1305    fn div_assign(&mut self, rhs: &f64) {
1306        self.div_assign(*rhs);
1307    }
1308}
1309
1310impl Sum<Self> for DMat3 {
1311    fn sum<I>(iter: I) -> Self
1312    where
1313        I: Iterator<Item = Self>,
1314    {
1315        iter.fold(Self::ZERO, Self::add)
1316    }
1317}
1318
1319impl<'a> Sum<&'a Self> for DMat3 {
1320    fn sum<I>(iter: I) -> Self
1321    where
1322        I: Iterator<Item = &'a Self>,
1323    {
1324        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1325    }
1326}
1327
1328impl Product for DMat3 {
1329    fn product<I>(iter: I) -> Self
1330    where
1331        I: Iterator<Item = Self>,
1332    {
1333        iter.fold(Self::IDENTITY, Self::mul)
1334    }
1335}
1336
1337impl<'a> Product<&'a Self> for DMat3 {
1338    fn product<I>(iter: I) -> Self
1339    where
1340        I: Iterator<Item = &'a Self>,
1341    {
1342        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1343    }
1344}
1345
1346impl PartialEq for DMat3 {
1347    #[inline]
1348    fn eq(&self, rhs: &Self) -> bool {
1349        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
1350    }
1351}
1352
1353impl AsRef<[f64; 9]> for DMat3 {
1354    #[inline]
1355    fn as_ref(&self) -> &[f64; 9] {
1356        unsafe { &*(self as *const Self as *const [f64; 9]) }
1357    }
1358}
1359
1360impl AsMut<[f64; 9]> for DMat3 {
1361    #[inline]
1362    fn as_mut(&mut self) -> &mut [f64; 9] {
1363        unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
1364    }
1365}
1366
1367impl fmt::Debug for DMat3 {
1368    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1369        fmt.debug_struct(stringify!(DMat3))
1370            .field("x_axis", &self.x_axis)
1371            .field("y_axis", &self.y_axis)
1372            .field("z_axis", &self.z_axis)
1373            .finish()
1374    }
1375}
1376
1377impl fmt::Display for DMat3 {
1378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1379        if let Some(p) = f.precision() {
1380            write!(
1381                f,
1382                "[{:.*}, {:.*}, {:.*}]",
1383                p, self.x_axis, p, self.y_axis, p, self.z_axis
1384            )
1385        } else {
1386            write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
1387        }
1388    }
1389}