revier_glam/f64/
dmat3.rs

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