revier_glam/f32/sse2/
mat3a.rs

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