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/// Creates a 3x3 matrix from three column vectors.
14#[inline(always)]
15#[must_use]
16pub const fn dmat3(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> DMat3 {
17    DMat3::from_cols(x_axis, y_axis, z_axis)
18}
19
20/// A 3x3 column major matrix.
21///
22/// This 3x3 matrix type features convenience methods for creating and using linear and
23/// affine transformations. If you are primarily dealing with 2D affine transformations the
24/// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than
25/// using a 3x3 matrix.
26///
27/// Linear transformations including 3D rotation and scale can be created using methods
28/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
29/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
30/// [`Self::from_rotation_z()`].
31///
32/// The resulting matrices can be use to transform 3D vectors using regular vector
33/// multiplication.
34///
35/// Affine transformations including 2D translation, rotation and scale can be created
36/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
37/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
38///
39/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
40/// are provided for performing affine transforms on 2D vectors and points. These multiply
41/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
42/// vectors respectively. These methods assume that `Self` contains a valid affine
43/// transform.
44#[derive(Clone, Copy)]
45#[repr(C)]
46pub struct DMat3 {
47    pub x_axis: DVec3,
48    pub y_axis: DVec3,
49    pub z_axis: DVec3,
50}
51
52impl DMat3 {
53    /// A 3x3 matrix with all elements set to `0.0`.
54    pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO);
55
56    /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
57    pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z);
58
59    /// All NAN:s.
60    pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN);
61
62    #[allow(clippy::too_many_arguments)]
63    #[inline(always)]
64    #[must_use]
65    const fn new(
66        m00: f64,
67        m01: f64,
68        m02: f64,
69        m10: f64,
70        m11: f64,
71        m12: f64,
72        m20: f64,
73        m21: f64,
74        m22: f64,
75    ) -> Self {
76        Self {
77            x_axis: DVec3::new(m00, m01, m02),
78            y_axis: DVec3::new(m10, m11, m12),
79            z_axis: DVec3::new(m20, m21, m22),
80        }
81    }
82
83    /// Creates a 3x3 matrix from three column vectors.
84    #[inline(always)]
85    #[must_use]
86    pub const fn from_cols(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
87        Self {
88            x_axis,
89            y_axis,
90            z_axis,
91        }
92    }
93
94    /// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order.
95    /// If your data is stored in row major you will need to `transpose` the returned
96    /// matrix.
97    #[inline]
98    #[must_use]
99    pub const fn from_cols_array(m: &[f64; 9]) -> Self {
100        Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
101    }
102
103    /// Creates a `[f64; 9]` array storing data in column major order.
104    /// If you require data in row major order `transpose` the matrix first.
105    #[inline]
106    #[must_use]
107    pub const fn to_cols_array(&self) -> [f64; 9] {
108        [
109            self.x_axis.x,
110            self.x_axis.y,
111            self.x_axis.z,
112            self.y_axis.x,
113            self.y_axis.y,
114            self.y_axis.z,
115            self.z_axis.x,
116            self.z_axis.y,
117            self.z_axis.z,
118        ]
119    }
120
121    /// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order.
122    /// If your data is in row major order you will need to `transpose` the returned
123    /// matrix.
124    #[inline]
125    #[must_use]
126    pub const fn from_cols_array_2d(m: &[[f64; 3]; 3]) -> Self {
127        Self::from_cols(
128            DVec3::from_array(m[0]),
129            DVec3::from_array(m[1]),
130            DVec3::from_array(m[2]),
131        )
132    }
133
134    /// Creates a `[[f64; 3]; 3]` 3D array storing data in column major order.
135    /// If you require data in row major order `transpose` the matrix first.
136    #[inline]
137    #[must_use]
138    pub const fn to_cols_array_2d(&self) -> [[f64; 3]; 3] {
139        [
140            self.x_axis.to_array(),
141            self.y_axis.to_array(),
142            self.z_axis.to_array(),
143        ]
144    }
145
146    /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
147    #[doc(alias = "scale")]
148    #[inline]
149    #[must_use]
150    pub const fn from_diagonal(diagonal: DVec3) -> Self {
151        Self::new(
152            diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
153        )
154    }
155
156    /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
157    #[inline]
158    #[must_use]
159    pub fn from_mat4(m: DMat4) -> Self {
160        Self::from_cols(
161            DVec3::from_vec4(m.x_axis),
162            DVec3::from_vec4(m.y_axis),
163            DVec3::from_vec4(m.z_axis),
164        )
165    }
166
167    /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
168    /// and `j`th row.
169    ///
170    /// # Panics
171    ///
172    /// Panics if `i` or `j` is greater than 3.
173    #[inline]
174    #[must_use]
175    pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self {
176        match (i, j) {
177            (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
178            (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
179            (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
180            (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
181            (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()),
182            (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()),
183            (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()),
184            (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()),
185            (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()),
186            (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()),
187            (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()),
188            (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()),
189            (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()),
190            (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()),
191            (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()),
192            (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()),
193            _ => panic!("index out of bounds"),
194        }
195    }
196
197    /// Creates a 3D rotation matrix from the given quaternion.
198    ///
199    /// # Panics
200    ///
201    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
202    #[inline]
203    #[must_use]
204    pub fn from_quat(rotation: DQuat) -> Self {
205        glam_assert!(rotation.is_normalized());
206
207        let x2 = rotation.x + rotation.x;
208        let y2 = rotation.y + rotation.y;
209        let z2 = rotation.z + rotation.z;
210        let xx = rotation.x * x2;
211        let xy = rotation.x * y2;
212        let xz = rotation.x * z2;
213        let yy = rotation.y * y2;
214        let yz = rotation.y * z2;
215        let zz = rotation.z * z2;
216        let wx = rotation.w * x2;
217        let wy = rotation.w * y2;
218        let wz = rotation.w * z2;
219
220        Self::from_cols(
221            DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy),
222            DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx),
223            DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
224        )
225    }
226
227    /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
228    /// radians).
229    ///
230    /// # Panics
231    ///
232    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
233    #[inline]
234    #[must_use]
235    pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
236        glam_assert!(axis.is_normalized());
237
238        let (sin, cos) = math::sin_cos(angle);
239        let (xsin, ysin, zsin) = axis.mul(sin).into();
240        let (x, y, z) = axis.into();
241        let (x2, y2, z2) = axis.mul(axis).into();
242        let omc = 1.0 - cos;
243        let xyomc = x * y * omc;
244        let xzomc = x * z * omc;
245        let yzomc = y * z * omc;
246        Self::from_cols(
247            DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
248            DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
249            DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
250        )
251    }
252
253    /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
254    /// radians).
255    #[inline]
256    #[must_use]
257    pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
258        Self::from_euler_angles(order, a, b, c)
259    }
260
261    /// Extract Euler angles with the given Euler rotation order.
262    ///
263    /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
264    /// the resulting Euler angles will be ill-defined.
265    ///
266    /// # Panics
267    ///
268    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
269    #[inline]
270    #[must_use]
271    pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
272        glam_assert!(
273            self.x_axis.is_normalized()
274                && self.y_axis.is_normalized()
275                && self.z_axis.is_normalized()
276        );
277        self.to_euler_angles(order)
278    }
279
280    /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
281    #[inline]
282    #[must_use]
283    pub fn from_rotation_x(angle: f64) -> Self {
284        let (sina, cosa) = math::sin_cos(angle);
285        Self::from_cols(
286            DVec3::X,
287            DVec3::new(0.0, cosa, sina),
288            DVec3::new(0.0, -sina, cosa),
289        )
290    }
291
292    /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
293    #[inline]
294    #[must_use]
295    pub fn from_rotation_y(angle: f64) -> Self {
296        let (sina, cosa) = math::sin_cos(angle);
297        Self::from_cols(
298            DVec3::new(cosa, 0.0, -sina),
299            DVec3::Y,
300            DVec3::new(sina, 0.0, cosa),
301        )
302    }
303
304    /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
305    #[inline]
306    #[must_use]
307    pub fn from_rotation_z(angle: f64) -> Self {
308        let (sina, cosa) = math::sin_cos(angle);
309        Self::from_cols(
310            DVec3::new(cosa, sina, 0.0),
311            DVec3::new(-sina, cosa, 0.0),
312            DVec3::Z,
313        )
314    }
315
316    /// Creates an affine transformation matrix from the given 2D `translation`.
317    ///
318    /// The resulting matrix can be used to transform 2D points and vectors. See
319    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
320    #[inline]
321    #[must_use]
322    pub fn from_translation(translation: DVec2) -> Self {
323        Self::from_cols(
324            DVec3::X,
325            DVec3::Y,
326            DVec3::new(translation.x, translation.y, 1.0),
327        )
328    }
329
330    /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
331    /// radians).
332    ///
333    /// The resulting matrix can be used to transform 2D points and vectors. See
334    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
335    #[inline]
336    #[must_use]
337    pub fn from_angle(angle: f64) -> Self {
338        let (sin, cos) = math::sin_cos(angle);
339        Self::from_cols(
340            DVec3::new(cos, sin, 0.0),
341            DVec3::new(-sin, cos, 0.0),
342            DVec3::Z,
343        )
344    }
345
346    /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
347    /// radians) and `translation`.
348    ///
349    /// The resulting matrix can be used to transform 2D points and vectors. See
350    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
351    #[inline]
352    #[must_use]
353    pub fn from_scale_angle_translation(scale: DVec2, angle: f64, translation: DVec2) -> Self {
354        let (sin, cos) = math::sin_cos(angle);
355        Self::from_cols(
356            DVec3::new(cos * scale.x, sin * scale.x, 0.0),
357            DVec3::new(-sin * scale.y, cos * scale.y, 0.0),
358            DVec3::new(translation.x, translation.y, 1.0),
359        )
360    }
361
362    /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
363    ///
364    /// The resulting matrix can be used to transform 2D points and vectors. See
365    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
366    ///
367    /// # Panics
368    ///
369    /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
370    #[inline]
371    #[must_use]
372    pub fn from_scale(scale: DVec2) -> Self {
373        // Do not panic as long as any component is non-zero
374        glam_assert!(scale.cmpne(DVec2::ZERO).any());
375
376        Self::from_cols(
377            DVec3::new(scale.x, 0.0, 0.0),
378            DVec3::new(0.0, scale.y, 0.0),
379            DVec3::Z,
380        )
381    }
382
383    /// Creates an affine transformation matrix from the given 2x2 matrix.
384    ///
385    /// The resulting matrix can be used to transform 2D points and vectors. See
386    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
387    #[inline]
388    pub fn from_mat2(m: DMat2) -> Self {
389        Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z)
390    }
391
392    /// Creates a 3x3 matrix from the first 9 values in `slice`.
393    ///
394    /// # Panics
395    ///
396    /// Panics if `slice` is less than 9 elements long.
397    #[inline]
398    #[must_use]
399    pub const fn from_cols_slice(slice: &[f64]) -> Self {
400        Self::new(
401            slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
402            slice[8],
403        )
404    }
405
406    /// Writes the columns of `self` to the first 9 elements in `slice`.
407    ///
408    /// # Panics
409    ///
410    /// Panics if `slice` is less than 9 elements long.
411    #[inline]
412    pub fn write_cols_to_slice(self, slice: &mut [f64]) {
413        slice[0] = self.x_axis.x;
414        slice[1] = self.x_axis.y;
415        slice[2] = self.x_axis.z;
416        slice[3] = self.y_axis.x;
417        slice[4] = self.y_axis.y;
418        slice[5] = self.y_axis.z;
419        slice[6] = self.z_axis.x;
420        slice[7] = self.z_axis.y;
421        slice[8] = self.z_axis.z;
422    }
423
424    /// Returns the matrix column for the given `index`.
425    ///
426    /// # Panics
427    ///
428    /// Panics if `index` is greater than 2.
429    #[inline]
430    #[must_use]
431    pub fn col(&self, index: usize) -> DVec3 {
432        match index {
433            0 => self.x_axis,
434            1 => self.y_axis,
435            2 => self.z_axis,
436            _ => panic!("index out of bounds"),
437        }
438    }
439
440    /// Returns a mutable reference to the matrix column for the given `index`.
441    ///
442    /// # Panics
443    ///
444    /// Panics if `index` is greater than 2.
445    #[inline]
446    pub fn col_mut(&mut self, index: usize) -> &mut DVec3 {
447        match index {
448            0 => &mut self.x_axis,
449            1 => &mut self.y_axis,
450            2 => &mut self.z_axis,
451            _ => panic!("index out of bounds"),
452        }
453    }
454
455    /// Returns the matrix row for the given `index`.
456    ///
457    /// # Panics
458    ///
459    /// Panics if `index` is greater than 2.
460    #[inline]
461    #[must_use]
462    pub fn row(&self, index: usize) -> DVec3 {
463        match index {
464            0 => DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
465            1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
466            2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
467            _ => panic!("index out of bounds"),
468        }
469    }
470
471    /// Returns `true` if, and only if, all elements are finite.
472    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
473    #[inline]
474    #[must_use]
475    pub fn is_finite(&self) -> bool {
476        self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
477    }
478
479    /// Returns `true` if any elements are `NaN`.
480    #[inline]
481    #[must_use]
482    pub fn is_nan(&self) -> bool {
483        self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
484    }
485
486    /// Returns the transpose of `self`.
487    #[inline]
488    #[must_use]
489    pub fn transpose(&self) -> Self {
490        Self {
491            x_axis: DVec3::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
492            y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
493            z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
494        }
495    }
496
497    /// Returns the determinant of `self`.
498    #[inline]
499    #[must_use]
500    pub fn determinant(&self) -> f64 {
501        self.z_axis.dot(self.x_axis.cross(self.y_axis))
502    }
503
504    /// Returns the inverse of `self`.
505    ///
506    /// If the matrix is not invertible the returned matrix will be invalid.
507    ///
508    /// # Panics
509    ///
510    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
511    #[inline]
512    #[must_use]
513    pub fn inverse(&self) -> Self {
514        let tmp0 = self.y_axis.cross(self.z_axis);
515        let tmp1 = self.z_axis.cross(self.x_axis);
516        let tmp2 = self.x_axis.cross(self.y_axis);
517        let det = self.z_axis.dot(tmp2);
518        glam_assert!(det != 0.0);
519        let inv_det = DVec3::splat(det.recip());
520        Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
521    }
522
523    /// Transforms the given 2D vector as a point.
524    ///
525    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
526    ///
527    /// This method assumes that `self` contains a valid affine transform.
528    ///
529    /// # Panics
530    ///
531    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
532    #[inline]
533    #[must_use]
534    pub fn transform_point2(&self, rhs: DVec2) -> DVec2 {
535        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
536        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
537    }
538
539    /// Rotates the given 2D vector.
540    ///
541    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
542    ///
543    /// This method assumes that `self` contains a valid affine transform.
544    ///
545    /// # Panics
546    ///
547    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
548    #[inline]
549    #[must_use]
550    pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 {
551        glam_assert!(self.row(2).abs_diff_eq(DVec3::Z, 1e-6));
552        DMat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
553    }
554
555    /// Transforms a 3D vector.
556    #[inline]
557    #[must_use]
558    pub fn mul_vec3(&self, rhs: DVec3) -> DVec3 {
559        let mut res = self.x_axis.mul(rhs.x);
560        res = res.add(self.y_axis.mul(rhs.y));
561        res = res.add(self.z_axis.mul(rhs.z));
562        res
563    }
564
565    /// Multiplies two 3x3 matrices.
566    #[inline]
567    #[must_use]
568    pub fn mul_mat3(&self, rhs: &Self) -> Self {
569        Self::from_cols(
570            self.mul(rhs.x_axis),
571            self.mul(rhs.y_axis),
572            self.mul(rhs.z_axis),
573        )
574    }
575
576    /// Adds two 3x3 matrices.
577    #[inline]
578    #[must_use]
579    pub fn add_mat3(&self, rhs: &Self) -> Self {
580        Self::from_cols(
581            self.x_axis.add(rhs.x_axis),
582            self.y_axis.add(rhs.y_axis),
583            self.z_axis.add(rhs.z_axis),
584        )
585    }
586
587    /// Subtracts two 3x3 matrices.
588    #[inline]
589    #[must_use]
590    pub fn sub_mat3(&self, rhs: &Self) -> Self {
591        Self::from_cols(
592            self.x_axis.sub(rhs.x_axis),
593            self.y_axis.sub(rhs.y_axis),
594            self.z_axis.sub(rhs.z_axis),
595        )
596    }
597
598    /// Multiplies a 3x3 matrix by a scalar.
599    #[inline]
600    #[must_use]
601    pub fn mul_scalar(&self, rhs: f64) -> Self {
602        Self::from_cols(
603            self.x_axis.mul(rhs),
604            self.y_axis.mul(rhs),
605            self.z_axis.mul(rhs),
606        )
607    }
608
609    /// Divides a 3x3 matrix by a scalar.
610    #[inline]
611    #[must_use]
612    pub fn div_scalar(&self, rhs: f64) -> Self {
613        let rhs = DVec3::splat(rhs);
614        Self::from_cols(
615            self.x_axis.div(rhs),
616            self.y_axis.div(rhs),
617            self.z_axis.div(rhs),
618        )
619    }
620
621    /// Returns true if the absolute difference of all elements between `self` and `rhs`
622    /// is less than or equal to `max_abs_diff`.
623    ///
624    /// This can be used to compare if two matrices contain similar elements. It works best
625    /// when comparing with a known value. The `max_abs_diff` that should be used used
626    /// depends on the values being compared against.
627    ///
628    /// For more see
629    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
630    #[inline]
631    #[must_use]
632    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
633        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
634            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
635            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
636    }
637
638    /// Takes the absolute value of each element in `self`
639    #[inline]
640    #[must_use]
641    pub fn abs(&self) -> Self {
642        Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
643    }
644
645    #[inline]
646    pub fn as_mat3(&self) -> Mat3 {
647        Mat3::from_cols(
648            self.x_axis.as_vec3(),
649            self.y_axis.as_vec3(),
650            self.z_axis.as_vec3(),
651        )
652    }
653}
654
655impl Default for DMat3 {
656    #[inline]
657    fn default() -> Self {
658        Self::IDENTITY
659    }
660}
661
662impl Add<DMat3> for DMat3 {
663    type Output = Self;
664    #[inline]
665    fn add(self, rhs: Self) -> Self::Output {
666        self.add_mat3(&rhs)
667    }
668}
669
670impl AddAssign<DMat3> for DMat3 {
671    #[inline]
672    fn add_assign(&mut self, rhs: Self) {
673        *self = self.add_mat3(&rhs);
674    }
675}
676
677impl Sub<DMat3> for DMat3 {
678    type Output = Self;
679    #[inline]
680    fn sub(self, rhs: Self) -> Self::Output {
681        self.sub_mat3(&rhs)
682    }
683}
684
685impl SubAssign<DMat3> for DMat3 {
686    #[inline]
687    fn sub_assign(&mut self, rhs: Self) {
688        *self = self.sub_mat3(&rhs);
689    }
690}
691
692impl Neg for DMat3 {
693    type Output = Self;
694    #[inline]
695    fn neg(self) -> Self::Output {
696        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
697    }
698}
699
700impl Mul<DMat3> for DMat3 {
701    type Output = Self;
702    #[inline]
703    fn mul(self, rhs: Self) -> Self::Output {
704        self.mul_mat3(&rhs)
705    }
706}
707
708impl MulAssign<DMat3> for DMat3 {
709    #[inline]
710    fn mul_assign(&mut self, rhs: Self) {
711        *self = self.mul_mat3(&rhs);
712    }
713}
714
715impl Mul<DVec3> for DMat3 {
716    type Output = DVec3;
717    #[inline]
718    fn mul(self, rhs: DVec3) -> Self::Output {
719        self.mul_vec3(rhs)
720    }
721}
722
723impl Mul<DMat3> for f64 {
724    type Output = DMat3;
725    #[inline]
726    fn mul(self, rhs: DMat3) -> Self::Output {
727        rhs.mul_scalar(self)
728    }
729}
730
731impl Mul<f64> for DMat3 {
732    type Output = Self;
733    #[inline]
734    fn mul(self, rhs: f64) -> Self::Output {
735        self.mul_scalar(rhs)
736    }
737}
738
739impl MulAssign<f64> for DMat3 {
740    #[inline]
741    fn mul_assign(&mut self, rhs: f64) {
742        *self = self.mul_scalar(rhs);
743    }
744}
745
746impl Div<DMat3> for f64 {
747    type Output = DMat3;
748    #[inline]
749    fn div(self, rhs: DMat3) -> Self::Output {
750        rhs.div_scalar(self)
751    }
752}
753
754impl Div<f64> for DMat3 {
755    type Output = Self;
756    #[inline]
757    fn div(self, rhs: f64) -> Self::Output {
758        self.div_scalar(rhs)
759    }
760}
761
762impl DivAssign<f64> for DMat3 {
763    #[inline]
764    fn div_assign(&mut self, rhs: f64) {
765        *self = self.div_scalar(rhs);
766    }
767}
768
769impl Sum<Self> for DMat3 {
770    fn sum<I>(iter: I) -> Self
771    where
772        I: Iterator<Item = Self>,
773    {
774        iter.fold(Self::ZERO, Self::add)
775    }
776}
777
778impl<'a> Sum<&'a Self> for DMat3 {
779    fn sum<I>(iter: I) -> Self
780    where
781        I: Iterator<Item = &'a Self>,
782    {
783        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
784    }
785}
786
787impl Product for DMat3 {
788    fn product<I>(iter: I) -> Self
789    where
790        I: Iterator<Item = Self>,
791    {
792        iter.fold(Self::IDENTITY, Self::mul)
793    }
794}
795
796impl<'a> Product<&'a Self> for DMat3 {
797    fn product<I>(iter: I) -> Self
798    where
799        I: Iterator<Item = &'a Self>,
800    {
801        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
802    }
803}
804
805impl PartialEq for DMat3 {
806    #[inline]
807    fn eq(&self, rhs: &Self) -> bool {
808        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
809    }
810}
811
812#[cfg(not(target_arch = "spirv"))]
813impl AsRef<[f64; 9]> for DMat3 {
814    #[inline]
815    fn as_ref(&self) -> &[f64; 9] {
816        unsafe { &*(self as *const Self as *const [f64; 9]) }
817    }
818}
819
820#[cfg(not(target_arch = "spirv"))]
821impl AsMut<[f64; 9]> for DMat3 {
822    #[inline]
823    fn as_mut(&mut self) -> &mut [f64; 9] {
824        unsafe { &mut *(self as *mut Self as *mut [f64; 9]) }
825    }
826}
827
828impl fmt::Debug for DMat3 {
829    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
830        fmt.debug_struct(stringify!(DMat3))
831            .field("x_axis", &self.x_axis)
832            .field("y_axis", &self.y_axis)
833            .field("z_axis", &self.z_axis)
834            .finish()
835    }
836}
837
838impl fmt::Display for DMat3 {
839    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
840        if let Some(p) = f.precision() {
841            write!(
842                f,
843                "[{:.*}, {:.*}, {:.*}]",
844                p, self.x_axis, p, self.y_axis, p, self.z_axis
845            )
846        } else {
847            write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
848        }
849    }
850}