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