Skip to main content

glam/f32/sse2/
mat3a.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3#[cfg(feature = "f64")]
4use crate::DMat3;
5
6use crate::{
7    euler::{FromEuler, ToEuler},
8    f32::math,
9    swizzles::*,
10    EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
11};
12use core::fmt;
13use core::iter::{Product, Sum};
14use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
15
16#[cfg(target_arch = "x86")]
17use core::arch::x86::*;
18#[cfg(target_arch = "x86_64")]
19use core::arch::x86_64::*;
20
21#[cfg(feature = "zerocopy-08")]
22use zerocopy_derive_08::*;
23
24/// Creates a 3x3 matrix from three column vectors.
25#[inline(always)]
26#[must_use]
27pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
28    Mat3A::from_cols(x_axis, y_axis, z_axis)
29}
30
31/// A 3x3 column major matrix.
32///
33/// This 3x3 matrix type features convenience methods for creating and using linear and
34/// affine transformations. If you are primarily dealing with 2D affine transformations the
35/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
36/// using a 3x3 matrix.
37///
38/// Linear transformations including 3D rotation and scale can be created using methods
39/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
40/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
41/// [`Self::from_rotation_z()`].
42///
43/// The resulting matrices can be use to transform 3D vectors using regular vector
44/// multiplication.
45///
46/// Affine transformations including 2D translation, rotation and scale can be created
47/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
48/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
49///
50/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
51/// are provided for performing affine transforms on 2D vectors and points. These multiply
52/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
53/// vectors respectively. These methods assume that `Self` contains a valid affine
54/// transform.
55///
56/// SIMD vector types are used for storage on supported platforms.
57///
58/// This type is 16 byte aligned.
59#[derive(Clone, Copy)]
60#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
61#[cfg_attr(
62    feature = "zerocopy-08",
63    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
64)]
65#[repr(C)]
66pub struct Mat3A {
67    pub x_axis: Vec3A,
68    pub y_axis: Vec3A,
69    pub z_axis: Vec3A,
70}
71
72impl Mat3A {
73    /// A 3x3 matrix with all elements set to `0.0`.
74    pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
75
76    /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
77    pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
78
79    /// All NAN:s.
80    pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
81
82    #[allow(clippy::too_many_arguments)]
83    #[inline(always)]
84    #[must_use]
85    const fn new(
86        m00: f32,
87        m01: f32,
88        m02: f32,
89        m10: f32,
90        m11: f32,
91        m12: f32,
92        m20: f32,
93        m21: f32,
94        m22: f32,
95    ) -> Self {
96        Self {
97            x_axis: Vec3A::new(m00, m01, m02),
98            y_axis: Vec3A::new(m10, m11, m12),
99            z_axis: Vec3A::new(m20, m21, m22),
100        }
101    }
102
103    /// Creates a 3x3 matrix from three column vectors.
104    ///
105    /// See also [`Self::from_rows`] when the data is in row major order.
106    #[inline(always)]
107    #[must_use]
108    pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
109        Self {
110            x_axis,
111            y_axis,
112            z_axis,
113        }
114    }
115
116    /// Creates a 3x3 matrix from three row vectors.
117    ///
118    /// Matrices are stored in column major order, so the given rows are permuted into
119    /// the matrix layout. Use [`Self::from_cols`] instead when the data is already in
120    /// column major order.
121    #[inline(always)]
122    #[must_use]
123    pub const fn from_rows(row0: Vec3A, row1: Vec3A, row2: Vec3A) -> Self {
124        let [m00, m01, m02] = row0.to_array();
125        let [m10, m11, m12] = row1.to_array();
126        let [m20, m21, m22] = row2.to_array();
127        Self::new(m00, m10, m20, m01, m11, m21, m02, m12, m22)
128    }
129
130    /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
131    ///
132    /// If the data is in row major order use [`Self::from_rows_array`] instead.
133    #[inline]
134    #[must_use]
135    pub const fn from_cols_array(m: &[f32; 9]) -> Self {
136        Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
137    }
138
139    /// Creates a `[f32; 9]` array storing data in column major order.
140    ///
141    /// If you require the data in row major order use [`Self::to_rows_array`] instead.
142    #[inline]
143    #[must_use]
144    pub const fn to_cols_array(&self) -> [f32; 9] {
145        let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
146        let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
147        let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
148
149        [
150            x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
151            z_axis_z,
152        ]
153    }
154
155    /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
156    ///
157    /// If the data is in row major order `transpose` the returned matrix.
158    #[inline]
159    #[must_use]
160    pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
161        Self::from_cols(
162            Vec3A::from_array(m[0]),
163            Vec3A::from_array(m[1]),
164            Vec3A::from_array(m[2]),
165        )
166    }
167
168    /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
169    ///
170    /// If you require row major order `transpose` the matrix first.
171    #[inline]
172    #[must_use]
173    pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
174        [
175            self.x_axis.to_array(),
176            self.y_axis.to_array(),
177            self.z_axis.to_array(),
178        ]
179    }
180
181    /// Creates a 3x3 matrix from a `[f32; 9]` array stored in row major order.
182    ///
183    /// Matrices are stored in column major order, so the array is permuted into the
184    /// matrix layout. Use [`Self::from_cols_array`] instead when the data is already in
185    /// column major order.
186    #[inline]
187    #[must_use]
188    pub const fn from_rows_array(m: &[f32; 9]) -> Self {
189        Self::new(m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8])
190    }
191
192    /// Creates a `[f32; 9]` array storing data in row major order.
193    ///
194    /// Matrices are stored in column major order, so the array is permuted out of the
195    /// column major storage. Use [`Self::to_cols_array`] instead when you want data in
196    /// column major order.
197    #[inline]
198    #[must_use]
199    pub const fn to_rows_array(&self) -> [f32; 9] {
200        let m = self.to_cols_array();
201        [m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]]
202    }
203
204    /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
205    #[doc(alias = "scale")]
206    #[inline]
207    #[must_use]
208    pub const fn from_diagonal(diagonal: Vec3) -> Self {
209        Self::new(
210            diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
211        )
212    }
213
214    /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
215    #[inline]
216    #[must_use]
217    pub fn from_mat4(m: Mat4) -> Self {
218        Self::from_cols(
219            Vec3A::from_vec4(m.x_axis),
220            Vec3A::from_vec4(m.y_axis),
221            Vec3A::from_vec4(m.z_axis),
222        )
223    }
224
225    /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
226    /// and `j`th row.
227    ///
228    /// # Panics
229    ///
230    /// Panics if `i` or `j` is greater than 3.
231    #[inline]
232    #[must_use]
233    #[track_caller]
234    pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
235        match (i, j) {
236            (0, 0) => Self::from_cols(
237                Vec3A::from_vec4(m.y_axis.yzww()),
238                Vec3A::from_vec4(m.z_axis.yzww()),
239                Vec3A::from_vec4(m.w_axis.yzww()),
240            ),
241            (0, 1) => Self::from_cols(
242                Vec3A::from_vec4(m.y_axis.xzww()),
243                Vec3A::from_vec4(m.z_axis.xzww()),
244                Vec3A::from_vec4(m.w_axis.xzww()),
245            ),
246            (0, 2) => Self::from_cols(
247                Vec3A::from_vec4(m.y_axis.xyww()),
248                Vec3A::from_vec4(m.z_axis.xyww()),
249                Vec3A::from_vec4(m.w_axis.xyww()),
250            ),
251            (0, 3) => Self::from_cols(
252                Vec3A::from_vec4(m.y_axis.xyzw()),
253                Vec3A::from_vec4(m.z_axis.xyzw()),
254                Vec3A::from_vec4(m.w_axis.xyzw()),
255            ),
256            (1, 0) => Self::from_cols(
257                Vec3A::from_vec4(m.x_axis.yzww()),
258                Vec3A::from_vec4(m.z_axis.yzww()),
259                Vec3A::from_vec4(m.w_axis.yzww()),
260            ),
261            (1, 1) => Self::from_cols(
262                Vec3A::from_vec4(m.x_axis.xzww()),
263                Vec3A::from_vec4(m.z_axis.xzww()),
264                Vec3A::from_vec4(m.w_axis.xzww()),
265            ),
266            (1, 2) => Self::from_cols(
267                Vec3A::from_vec4(m.x_axis.xyww()),
268                Vec3A::from_vec4(m.z_axis.xyww()),
269                Vec3A::from_vec4(m.w_axis.xyww()),
270            ),
271            (1, 3) => Self::from_cols(
272                Vec3A::from_vec4(m.x_axis.xyzw()),
273                Vec3A::from_vec4(m.z_axis.xyzw()),
274                Vec3A::from_vec4(m.w_axis.xyzw()),
275            ),
276            (2, 0) => Self::from_cols(
277                Vec3A::from_vec4(m.x_axis.yzww()),
278                Vec3A::from_vec4(m.y_axis.yzww()),
279                Vec3A::from_vec4(m.w_axis.yzww()),
280            ),
281            (2, 1) => Self::from_cols(
282                Vec3A::from_vec4(m.x_axis.xzww()),
283                Vec3A::from_vec4(m.y_axis.xzww()),
284                Vec3A::from_vec4(m.w_axis.xzww()),
285            ),
286            (2, 2) => Self::from_cols(
287                Vec3A::from_vec4(m.x_axis.xyww()),
288                Vec3A::from_vec4(m.y_axis.xyww()),
289                Vec3A::from_vec4(m.w_axis.xyww()),
290            ),
291            (2, 3) => Self::from_cols(
292                Vec3A::from_vec4(m.x_axis.xyzw()),
293                Vec3A::from_vec4(m.y_axis.xyzw()),
294                Vec3A::from_vec4(m.w_axis.xyzw()),
295            ),
296            (3, 0) => Self::from_cols(
297                Vec3A::from_vec4(m.x_axis.yzww()),
298                Vec3A::from_vec4(m.y_axis.yzww()),
299                Vec3A::from_vec4(m.z_axis.yzww()),
300            ),
301            (3, 1) => Self::from_cols(
302                Vec3A::from_vec4(m.x_axis.xzww()),
303                Vec3A::from_vec4(m.y_axis.xzww()),
304                Vec3A::from_vec4(m.z_axis.xzww()),
305            ),
306            (3, 2) => Self::from_cols(
307                Vec3A::from_vec4(m.x_axis.xyww()),
308                Vec3A::from_vec4(m.y_axis.xyww()),
309                Vec3A::from_vec4(m.z_axis.xyww()),
310            ),
311            (3, 3) => Self::from_cols(
312                Vec3A::from_vec4(m.x_axis.xyzw()),
313                Vec3A::from_vec4(m.y_axis.xyzw()),
314                Vec3A::from_vec4(m.z_axis.xyzw()),
315            ),
316            _ => panic!("index out of bounds"),
317        }
318    }
319
320    /// Creates a 3D rotation matrix from the given quaternion.
321    ///
322    /// # Panics
323    ///
324    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
325    #[inline]
326    #[must_use]
327    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
328    pub fn from_quat(rotation: Quat) -> Self {
329        glam_assert!(rotation.is_normalized());
330
331        let x2 = rotation.x + rotation.x;
332        let y2 = rotation.y + rotation.y;
333        let z2 = rotation.z + rotation.z;
334        let xx = rotation.x * x2;
335        let xy = rotation.x * y2;
336        let xz = rotation.x * z2;
337        let yy = rotation.y * y2;
338        let yz = rotation.y * z2;
339        let zz = rotation.z * z2;
340        let wx = rotation.w * x2;
341        let wy = rotation.w * y2;
342        let wz = rotation.w * z2;
343
344        Self::from_cols(
345            Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
346            Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
347            Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
348        )
349    }
350
351    /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
352    /// radians).
353    ///
354    /// # Panics
355    ///
356    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
357    #[inline]
358    #[must_use]
359    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
360    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
361        glam_assert!(axis.is_normalized());
362
363        let (sin, cos) = math::sin_cos(angle);
364        let (xsin, ysin, zsin) = axis.mul(sin).into();
365        let (x, y, z) = axis.into();
366        let (x2, y2, z2) = axis.mul(axis).into();
367        let omc = 1.0 - cos;
368        let xyomc = x * y * omc;
369        let xzomc = x * z * omc;
370        let yzomc = y * z * omc;
371        Self::from_cols(
372            Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
373            Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
374            Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
375        )
376    }
377
378    /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
379    /// radians).
380    #[inline]
381    #[must_use]
382    pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
383        Self::from_euler_angles(order, a, b, c)
384    }
385
386    /// Extract Euler angles with the given Euler rotation order.
387    ///
388    /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
389    /// the resulting Euler angles will be ill-defined.
390    ///
391    /// # Panics
392    ///
393    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
394    #[inline]
395    #[must_use]
396    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
397    pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
398        glam_assert!(
399            self.x_axis.is_normalized()
400                && self.y_axis.is_normalized()
401                && self.z_axis.is_normalized()
402        );
403        self.to_euler_angles(order)
404    }
405
406    /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
407    #[inline]
408    #[must_use]
409    pub fn from_rotation_x(angle: f32) -> Self {
410        let (sina, cosa) = math::sin_cos(angle);
411        Self::from_cols(
412            Vec3A::X,
413            Vec3A::new(0.0, cosa, sina),
414            Vec3A::new(0.0, -sina, cosa),
415        )
416    }
417
418    /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
419    #[inline]
420    #[must_use]
421    pub fn from_rotation_y(angle: f32) -> Self {
422        let (sina, cosa) = math::sin_cos(angle);
423        Self::from_cols(
424            Vec3A::new(cosa, 0.0, -sina),
425            Vec3A::Y,
426            Vec3A::new(sina, 0.0, cosa),
427        )
428    }
429
430    /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
431    #[inline]
432    #[must_use]
433    pub fn from_rotation_z(angle: f32) -> Self {
434        let (sina, cosa) = math::sin_cos(angle);
435        Self::from_cols(
436            Vec3A::new(cosa, sina, 0.0),
437            Vec3A::new(-sina, cosa, 0.0),
438            Vec3A::Z,
439        )
440    }
441
442    /// Creates an affine transformation matrix from the given 2D `translation`.
443    ///
444    /// The resulting matrix can be used to transform 2D points and vectors. See
445    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
446    #[inline]
447    #[must_use]
448    pub fn from_translation(translation: Vec2) -> Self {
449        Self::from_cols(
450            Vec3A::X,
451            Vec3A::Y,
452            Vec3A::new(translation.x, translation.y, 1.0),
453        )
454    }
455
456    /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
457    /// radians).
458    ///
459    /// The resulting matrix can be used to transform 2D points and vectors. See
460    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
461    #[inline]
462    #[must_use]
463    pub fn from_angle(angle: f32) -> Self {
464        let (sin, cos) = math::sin_cos(angle);
465        Self::from_cols(
466            Vec3A::new(cos, sin, 0.0),
467            Vec3A::new(-sin, cos, 0.0),
468            Vec3A::Z,
469        )
470    }
471
472    /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
473    /// radians) and `translation`.
474    ///
475    /// The resulting matrix can be used to transform 2D points and vectors. See
476    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
477    #[inline]
478    #[must_use]
479    pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
480        let (sin, cos) = math::sin_cos(angle);
481        Self::from_cols(
482            Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
483            Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
484            Vec3A::new(translation.x, translation.y, 1.0),
485        )
486    }
487
488    /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
489    ///
490    /// The resulting matrix can be used to transform 2D points and vectors. See
491    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
492    ///
493    /// # Panics
494    ///
495    /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
496    #[inline]
497    #[must_use]
498    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
499    pub fn from_scale(scale: Vec2) -> Self {
500        // Do not panic as long as any component is non-zero
501        glam_assert!(scale.cmpne(Vec2::ZERO).any());
502
503        Self::from_cols(
504            Vec3A::new(scale.x, 0.0, 0.0),
505            Vec3A::new(0.0, scale.y, 0.0),
506            Vec3A::Z,
507        )
508    }
509
510    /// Creates an affine transformation matrix from the given 2x2 matrix.
511    ///
512    /// The resulting matrix can be used to transform 2D points and vectors. See
513    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
514    #[inline]
515    pub fn from_mat2(m: Mat2) -> Self {
516        Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
517    }
518
519    /// Creates a 3x3 matrix from the first 9 values in `slice`.
520    ///
521    /// See also [`Self::from_rows_slice`] when the slice is in row major order.
522    ///
523    /// # Panics
524    ///
525    /// Panics if `slice` is less than 9 elements long.
526    #[inline]
527    #[must_use]
528    #[track_caller]
529    pub const fn from_cols_slice(slice: &[f32]) -> Self {
530        Self::new(
531            slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
532            slice[8],
533        )
534    }
535
536    /// Writes the columns of `self` to the first 9 elements in `slice`.
537    ///
538    /// # Panics
539    ///
540    /// Panics if `slice` is less than 9 elements long.
541    #[inline]
542    #[track_caller]
543    pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
544        slice[0] = self.x_axis.x;
545        slice[1] = self.x_axis.y;
546        slice[2] = self.x_axis.z;
547        slice[3] = self.y_axis.x;
548        slice[4] = self.y_axis.y;
549        slice[5] = self.y_axis.z;
550        slice[6] = self.z_axis.x;
551        slice[7] = self.z_axis.y;
552        slice[8] = self.z_axis.z;
553    }
554
555    /// Creates a 3x3 matrix from the first 9 values in `slice`, stored in row
556    /// major order.
557    ///
558    /// Matrices are stored in column major order, so the slice is permuted into the
559    /// matrix layout. Use [`Self::from_cols_slice`] instead when the slice is already in
560    /// column major order.
561    ///
562    /// # Panics
563    ///
564    /// Panics if `slice` is less than 9 elements long.
565    #[inline]
566    #[must_use]
567    #[track_caller]
568    pub const fn from_rows_slice(slice: &[f32]) -> Self {
569        Self::new(
570            slice[0], slice[3], slice[6], slice[1], slice[4], slice[7], slice[2], slice[5],
571            slice[8],
572        )
573    }
574
575    /// Returns the matrix column for the given `index`.
576    ///
577    /// # Panics
578    ///
579    /// Panics if `index` is greater than 2.
580    #[inline]
581    #[must_use]
582    #[track_caller]
583    pub fn col(&self, index: usize) -> Vec3A {
584        match index {
585            0 => self.x_axis,
586            1 => self.y_axis,
587            2 => self.z_axis,
588            _ => panic!("index out of bounds"),
589        }
590    }
591
592    /// Returns a mutable reference to the matrix column for the given `index`.
593    ///
594    /// # Panics
595    ///
596    /// Panics if `index` is greater than 2.
597    #[inline]
598    #[track_caller]
599    pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
600        match index {
601            0 => &mut self.x_axis,
602            1 => &mut self.y_axis,
603            2 => &mut self.z_axis,
604            _ => panic!("index out of bounds"),
605        }
606    }
607
608    /// Returns the matrix row for the given `index`.
609    ///
610    /// See also [`Self::set_row`] when you need to change the row.
611    ///
612    /// # Panics
613    ///
614    /// Panics if `index` is greater than 2.
615    #[inline]
616    #[must_use]
617    #[track_caller]
618    pub fn row(&self, index: usize) -> Vec3A {
619        match index {
620            0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
621            1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
622            2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
623            _ => panic!("index out of bounds"),
624        }
625    }
626
627    /// Sets the matrix row for the given `index`.
628    ///
629    /// Matrices are stored in column major order, so the row is spread across all
630    /// 3 columns and writing it touches every column. Use [`Self::col_mut`]
631    /// instead when you can work with columns. See also [`Self::row`].
632    ///
633    /// # Panics
634    ///
635    /// Panics if `index` is greater than 2.
636    #[inline]
637    #[track_caller]
638    pub fn set_row(&mut self, index: usize, row: Vec3A) {
639        match index {
640            0 => {
641                self.x_axis.x = row.x;
642                self.y_axis.x = row.y;
643                self.z_axis.x = row.z;
644            }
645            1 => {
646                self.x_axis.y = row.x;
647                self.y_axis.y = row.y;
648                self.z_axis.y = row.z;
649            }
650            2 => {
651                self.x_axis.z = row.x;
652                self.y_axis.z = row.y;
653                self.z_axis.z = row.z;
654            }
655            _ => panic!("index out of bounds"),
656        }
657    }
658
659    /// Returns `true` if, and only if, all elements are finite.
660    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
661    #[inline]
662    #[must_use]
663    pub fn is_finite(&self) -> bool {
664        self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
665    }
666
667    /// Returns `true` if any elements are `NaN`.
668    #[inline]
669    #[must_use]
670    pub fn is_nan(&self) -> bool {
671        self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
672    }
673
674    /// Returns the transpose of `self`.
675    #[inline]
676    #[must_use]
677    pub fn transpose(&self) -> Self {
678        unsafe {
679            let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
680            let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
681
682            Self {
683                x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)),
684                y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)),
685                z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)),
686            }
687        }
688    }
689
690    /// Returns the diagonal of `self`.
691    #[inline]
692    #[must_use]
693    pub fn diagonal(&self) -> Vec3A {
694        Vec3A::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
695    }
696
697    /// Returns the determinant of `self`.
698    #[inline]
699    #[must_use]
700    pub fn determinant(&self) -> f32 {
701        self.x_axis.dot(self.y_axis.cross(self.z_axis))
702    }
703
704    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
705    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
706    /// inverted matrix and true is returned.
707    ///
708    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
709    /// inverted matrix will be invalid. Will panic if the resulting inverted matrix is not finite
710    /// when `glam_assert` is enabled.
711    ///
712    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
713    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
714    /// matrix is aligned.
715    #[inline(always)]
716    #[must_use]
717    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
718    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
719        let tmp0 = self.y_axis.cross(self.z_axis);
720        let tmp1 = self.z_axis.cross(self.x_axis);
721        let tmp2 = self.x_axis.cross(self.y_axis);
722        let inv_det = Vec3A::splat(1.0 / self.x_axis.dot(tmp0));
723        let m =
724            Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose();
725        if CHECKED {
726            if !m.is_finite() {
727                return (Self::ZERO, false);
728            }
729        } else {
730            glam_assert!(m.is_finite());
731        }
732        (m, true)
733    }
734
735    /// Returns the inverse of `self`.
736    ///
737    /// If the matrix is not invertible the returned matrix will be invalid. The
738    /// returned matrix will also be invalid if the inverse is not finite, which can
739    /// happen when `self` contains very large or very small values. Use
740    /// [`Self::try_inverse`] or [`Self::inverse_or_zero`] to detect these cases.
741    ///
742    /// # Panics
743    ///
744    /// Will panic if the resulting inverted matrix is not finite when `glam_assert`
745    /// is enabled.
746    #[inline]
747    #[must_use]
748    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
749    pub fn inverse(&self) -> Self {
750        self.inverse_checked::<false>().0
751    }
752
753    /// Returns the inverse of `self` or `None` if the matrix is not invertible, or if
754    /// the inverse is not finite.
755    #[inline]
756    #[must_use]
757    pub fn try_inverse(&self) -> Option<Self> {
758        let (m, is_valid) = self.inverse_checked::<true>();
759        if is_valid {
760            Some(m)
761        } else {
762            None
763        }
764    }
765
766    /// Returns the inverse of `self` or `Mat3A::ZERO` if the matrix is not
767    /// invertible, or if the inverse is not finite.
768    #[inline]
769    #[must_use]
770    pub fn inverse_or_zero(&self) -> Self {
771        self.inverse_checked::<true>().0
772    }
773
774    /// Transforms the given 2D vector as a point.
775    ///
776    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
777    ///
778    /// This method assumes that `self` contains a valid affine transform.
779    ///
780    /// # Panics
781    ///
782    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
783    #[inline]
784    #[must_use]
785    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
786    pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
787        glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
788        Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
789    }
790
791    /// Rotates the given 2D vector.
792    ///
793    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
794    ///
795    /// This method assumes that `self` contains a valid affine transform.
796    ///
797    /// # Panics
798    ///
799    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
800    #[inline]
801    #[must_use]
802    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
803    pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
804        glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
805        Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
806    }
807
808    /// Creates a left-handed view matrix using a facing direction and an up direction.
809    ///
810    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
811    ///
812    /// # Panics
813    ///
814    /// Will panic if `dir` or `up` are not normalized, or if `dir` and `up` are parallel,
815    /// when `glam_assert` is enabled.
816    #[deprecated(
817        since = "0.33.1",
818        note = "use the `glam::camera::lh::view::look_to_mat3` function instead"
819    )]
820    #[inline]
821    #[must_use]
822    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
823    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
824        #[allow(deprecated)]
825        Self::look_to_rh(-dir, up)
826    }
827
828    /// Creates a right-handed view matrix using a facing direction and an up direction.
829    ///
830    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
831    ///
832    /// # Panics
833    ///
834    /// Will panic if `dir` or `up` are not normalized, or if `dir` and `up` are parallel,
835    /// when `glam_assert` is enabled.
836    #[deprecated(
837        since = "0.33.1",
838        note = "use the `glam::camera::rh::view::look_to_mat3` function instead"
839    )]
840    #[inline]
841    #[must_use]
842    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
843    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
844        glam_assert!(dir.is_normalized());
845        glam_assert!(up.is_normalized());
846        let f = dir;
847        let s = f.cross(up).normalize();
848        let u = s.cross(f);
849
850        Self::from_cols(
851            Vec3A::new(s.x, u.x, -f.x),
852            Vec3A::new(s.y, u.y, -f.y),
853            Vec3A::new(s.z, u.z, -f.z),
854        )
855    }
856
857    /// Creates a left-handed view matrix using a camera position, a focal point and an up
858    /// direction.
859    ///
860    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
861    ///
862    /// # Panics
863    ///
864    /// Will panic if `up` is not normalized, if `center` is equal to `eye`, or if the view
865    /// direction is parallel to `up`, when `glam_assert` is enabled.
866    #[deprecated(
867        since = "0.33.1",
868        note = "use the `glam::camera::lh::view::look_at_mat3` function instead"
869    )]
870    #[inline]
871    #[must_use]
872    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
873    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
874        #[allow(deprecated)]
875        Self::look_to_lh(center.sub(eye).normalize(), up)
876    }
877
878    /// Creates a right-handed view matrix using a camera position, a focal point and an up
879    /// direction.
880    ///
881    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
882    ///
883    /// # Panics
884    ///
885    /// Will panic if `up` is not normalized, if `center` is equal to `eye`, or if the view
886    /// direction is parallel to `up`, when `glam_assert` is enabled.
887    #[deprecated(
888        since = "0.33.1",
889        note = "use the `glam::camera::rh::view::look_at_mat3` function instead"
890    )]
891    #[inline]
892    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
893    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
894        #[allow(deprecated)]
895        Self::look_to_rh(center.sub(eye).normalize(), up)
896    }
897
898    /// Transforms a 3D vector.
899    #[inline]
900    #[must_use]
901    pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
902        self.mul_vec3a(rhs.into()).into()
903    }
904
905    /// Transforms a [`Vec3A`].
906    #[inline]
907    #[must_use]
908    pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
909        let mut res = self.x_axis.mul(rhs.xxx());
910        res = res.add(self.y_axis.mul(rhs.yyy()));
911        res = res.add(self.z_axis.mul(rhs.zzz()));
912        res
913    }
914
915    /// Transforms a 3D vector by the transpose of `self`.
916    #[inline]
917    #[must_use]
918    pub fn mul_transpose_vec3(&self, rhs: Vec3) -> Vec3 {
919        self.mul_transpose_vec3a(rhs.into()).into()
920    }
921
922    /// Transforms a [`Vec3A`] by the transpose of `self`.
923    #[inline]
924    #[must_use]
925    pub fn mul_transpose_vec3a(&self, rhs: Vec3A) -> Vec3A {
926        Vec3A::new(
927            self.x_axis.dot(rhs),
928            self.y_axis.dot(rhs),
929            self.z_axis.dot(rhs),
930        )
931    }
932
933    /// Multiplies two 3x3 matrices.
934    #[inline]
935    #[must_use]
936    pub fn mul_mat3(&self, rhs: &Self) -> Self {
937        self.mul(rhs)
938    }
939
940    /// Adds two 3x3 matrices.
941    #[inline]
942    #[must_use]
943    pub fn add_mat3(&self, rhs: &Self) -> Self {
944        self.add(rhs)
945    }
946
947    /// Subtracts two 3x3 matrices.
948    #[inline]
949    #[must_use]
950    pub fn sub_mat3(&self, rhs: &Self) -> Self {
951        self.sub(rhs)
952    }
953
954    /// Multiplies a 3x3 matrix by a scalar.
955    #[inline]
956    #[must_use]
957    pub fn mul_scalar(&self, rhs: f32) -> Self {
958        Self::from_cols(
959            self.x_axis.mul(rhs),
960            self.y_axis.mul(rhs),
961            self.z_axis.mul(rhs),
962        )
963    }
964
965    /// Multiply `self` by a scaling vector `scale`.
966    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
967    /// This operation is commutative.
968    #[inline]
969    #[must_use]
970    pub fn mul_diagonal_scale(&self, scale: Vec3) -> Self {
971        Self::from_cols(
972            self.x_axis * scale.x,
973            self.y_axis * scale.y,
974            self.z_axis * scale.z,
975        )
976    }
977
978    /// Divides a 3x3 matrix by a scalar.
979    #[inline]
980    #[must_use]
981    pub fn div_scalar(&self, rhs: f32) -> Self {
982        let rhs = Vec3A::splat(rhs);
983        Self::from_cols(
984            self.x_axis.div(rhs),
985            self.y_axis.div(rhs),
986            self.z_axis.div(rhs),
987        )
988    }
989
990    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
991    #[inline]
992    #[must_use]
993    pub fn recip(&self) -> Self {
994        Self::from_cols(
995            self.x_axis.recip(),
996            self.y_axis.recip(),
997            self.z_axis.recip(),
998        )
999    }
1000
1001    /// Returns true if the absolute difference of all elements between `self` and `rhs`
1002    /// is less than or equal to `max_abs_diff`.
1003    ///
1004    /// This can be used to compare if two matrices contain similar elements. It works best
1005    /// when comparing with a known value. The `max_abs_diff` that should be used used
1006    /// depends on the values being compared against.
1007    ///
1008    /// For more see
1009    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1010    #[inline]
1011    #[must_use]
1012    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1013        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1014            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1015            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1016    }
1017
1018    /// Takes the absolute value of each element in `self`
1019    #[inline]
1020    #[must_use]
1021    pub fn abs(&self) -> Self {
1022        Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
1023    }
1024
1025    #[cfg(feature = "f64")]
1026    #[inline]
1027    #[must_use]
1028    pub fn as_dmat3(&self) -> DMat3 {
1029        DMat3::from_cols(
1030            self.x_axis.as_dvec3(),
1031            self.y_axis.as_dvec3(),
1032            self.z_axis.as_dvec3(),
1033        )
1034    }
1035}
1036
1037impl Default for Mat3A {
1038    #[inline]
1039    fn default() -> Self {
1040        Self::IDENTITY
1041    }
1042}
1043
1044impl Add for Mat3A {
1045    type Output = Self;
1046    #[inline]
1047    fn add(self, rhs: Self) -> Self {
1048        Self::from_cols(
1049            self.x_axis.add(rhs.x_axis),
1050            self.y_axis.add(rhs.y_axis),
1051            self.z_axis.add(rhs.z_axis),
1052        )
1053    }
1054}
1055
1056impl Add<&Self> for Mat3A {
1057    type Output = Self;
1058    #[inline]
1059    fn add(self, rhs: &Self) -> Self {
1060        self.add(*rhs)
1061    }
1062}
1063
1064impl Add<&Mat3A> for &Mat3A {
1065    type Output = Mat3A;
1066    #[inline]
1067    fn add(self, rhs: &Mat3A) -> Mat3A {
1068        (*self).add(*rhs)
1069    }
1070}
1071
1072impl Add<Mat3A> for &Mat3A {
1073    type Output = Mat3A;
1074    #[inline]
1075    fn add(self, rhs: Mat3A) -> Mat3A {
1076        (*self).add(rhs)
1077    }
1078}
1079
1080impl AddAssign for Mat3A {
1081    #[inline]
1082    fn add_assign(&mut self, rhs: Self) {
1083        *self = self.add(rhs);
1084    }
1085}
1086
1087impl AddAssign<&Self> for Mat3A {
1088    #[inline]
1089    fn add_assign(&mut self, rhs: &Self) {
1090        self.add_assign(*rhs);
1091    }
1092}
1093
1094impl Sub for Mat3A {
1095    type Output = Self;
1096    #[inline]
1097    fn sub(self, rhs: Self) -> Self {
1098        Self::from_cols(
1099            self.x_axis.sub(rhs.x_axis),
1100            self.y_axis.sub(rhs.y_axis),
1101            self.z_axis.sub(rhs.z_axis),
1102        )
1103    }
1104}
1105
1106impl Sub<&Self> for Mat3A {
1107    type Output = Self;
1108    #[inline]
1109    fn sub(self, rhs: &Self) -> Self {
1110        self.sub(*rhs)
1111    }
1112}
1113
1114impl Sub<&Mat3A> for &Mat3A {
1115    type Output = Mat3A;
1116    #[inline]
1117    fn sub(self, rhs: &Mat3A) -> Mat3A {
1118        (*self).sub(*rhs)
1119    }
1120}
1121
1122impl Sub<Mat3A> for &Mat3A {
1123    type Output = Mat3A;
1124    #[inline]
1125    fn sub(self, rhs: Mat3A) -> Mat3A {
1126        (*self).sub(rhs)
1127    }
1128}
1129
1130impl SubAssign for Mat3A {
1131    #[inline]
1132    fn sub_assign(&mut self, rhs: Self) {
1133        *self = self.sub(rhs);
1134    }
1135}
1136
1137impl SubAssign<&Self> for Mat3A {
1138    #[inline]
1139    fn sub_assign(&mut self, rhs: &Self) {
1140        self.sub_assign(*rhs);
1141    }
1142}
1143
1144impl Neg for Mat3A {
1145    type Output = Self;
1146    #[inline]
1147    fn neg(self) -> Self::Output {
1148        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
1149    }
1150}
1151
1152impl Neg for &Mat3A {
1153    type Output = Mat3A;
1154    #[inline]
1155    fn neg(self) -> Mat3A {
1156        (*self).neg()
1157    }
1158}
1159
1160impl Mul for Mat3A {
1161    type Output = Self;
1162    #[inline]
1163    fn mul(self, rhs: Self) -> Self {
1164        Self::from_cols(
1165            self.mul(rhs.x_axis),
1166            self.mul(rhs.y_axis),
1167            self.mul(rhs.z_axis),
1168        )
1169    }
1170}
1171
1172impl Mul<&Self> for Mat3A {
1173    type Output = Self;
1174    #[inline]
1175    fn mul(self, rhs: &Self) -> Self {
1176        self.mul(*rhs)
1177    }
1178}
1179
1180impl Mul<&Mat3A> for &Mat3A {
1181    type Output = Mat3A;
1182    #[inline]
1183    fn mul(self, rhs: &Mat3A) -> Mat3A {
1184        (*self).mul(*rhs)
1185    }
1186}
1187
1188impl Mul<Mat3A> for &Mat3A {
1189    type Output = Mat3A;
1190    #[inline]
1191    fn mul(self, rhs: Mat3A) -> Mat3A {
1192        (*self).mul(rhs)
1193    }
1194}
1195
1196impl MulAssign for Mat3A {
1197    #[inline]
1198    fn mul_assign(&mut self, rhs: Self) {
1199        *self = self.mul(rhs);
1200    }
1201}
1202
1203impl MulAssign<&Self> for Mat3A {
1204    #[inline]
1205    fn mul_assign(&mut self, rhs: &Self) {
1206        self.mul_assign(*rhs);
1207    }
1208}
1209
1210impl Mul<Vec3A> for Mat3A {
1211    type Output = Vec3A;
1212    #[inline]
1213    fn mul(self, rhs: Vec3A) -> Self::Output {
1214        self.mul_vec3a(rhs)
1215    }
1216}
1217
1218impl Mul<&Vec3A> for Mat3A {
1219    type Output = Vec3A;
1220    #[inline]
1221    fn mul(self, rhs: &Vec3A) -> Vec3A {
1222        self.mul(*rhs)
1223    }
1224}
1225
1226impl Mul<&Vec3A> for &Mat3A {
1227    type Output = Vec3A;
1228    #[inline]
1229    fn mul(self, rhs: &Vec3A) -> Vec3A {
1230        (*self).mul(*rhs)
1231    }
1232}
1233
1234impl Mul<Vec3A> for &Mat3A {
1235    type Output = Vec3A;
1236    #[inline]
1237    fn mul(self, rhs: Vec3A) -> Vec3A {
1238        (*self).mul(rhs)
1239    }
1240}
1241
1242impl Mul<Mat3A> for f32 {
1243    type Output = Mat3A;
1244    #[inline]
1245    fn mul(self, rhs: Mat3A) -> Self::Output {
1246        rhs.mul_scalar(self)
1247    }
1248}
1249
1250impl Mul<&Mat3A> for f32 {
1251    type Output = Mat3A;
1252    #[inline]
1253    fn mul(self, rhs: &Mat3A) -> Mat3A {
1254        self.mul(*rhs)
1255    }
1256}
1257
1258impl Mul<&Mat3A> for &f32 {
1259    type Output = Mat3A;
1260    #[inline]
1261    fn mul(self, rhs: &Mat3A) -> Mat3A {
1262        (*self).mul(*rhs)
1263    }
1264}
1265
1266impl Mul<Mat3A> for &f32 {
1267    type Output = Mat3A;
1268    #[inline]
1269    fn mul(self, rhs: Mat3A) -> Mat3A {
1270        (*self).mul(rhs)
1271    }
1272}
1273
1274impl Mul<f32> for Mat3A {
1275    type Output = Self;
1276    #[inline]
1277    fn mul(self, rhs: f32) -> Self {
1278        self.mul_scalar(rhs)
1279    }
1280}
1281
1282impl Mul<&f32> for Mat3A {
1283    type Output = Self;
1284    #[inline]
1285    fn mul(self, rhs: &f32) -> Self {
1286        self.mul(*rhs)
1287    }
1288}
1289
1290impl Mul<&f32> for &Mat3A {
1291    type Output = Mat3A;
1292    #[inline]
1293    fn mul(self, rhs: &f32) -> Mat3A {
1294        (*self).mul(*rhs)
1295    }
1296}
1297
1298impl Mul<f32> for &Mat3A {
1299    type Output = Mat3A;
1300    #[inline]
1301    fn mul(self, rhs: f32) -> Mat3A {
1302        (*self).mul(rhs)
1303    }
1304}
1305
1306impl MulAssign<f32> for Mat3A {
1307    #[inline]
1308    fn mul_assign(&mut self, rhs: f32) {
1309        *self = self.mul(rhs);
1310    }
1311}
1312
1313impl MulAssign<&f32> for Mat3A {
1314    #[inline]
1315    fn mul_assign(&mut self, rhs: &f32) {
1316        self.mul_assign(*rhs);
1317    }
1318}
1319
1320impl Div<Mat3A> for f32 {
1321    type Output = Mat3A;
1322    #[inline]
1323    fn div(self, rhs: Mat3A) -> Self::Output {
1324        Mat3A::from_cols(
1325            self.div(rhs.x_axis),
1326            self.div(rhs.y_axis),
1327            self.div(rhs.z_axis),
1328        )
1329    }
1330}
1331
1332impl Div<&Mat3A> for f32 {
1333    type Output = Mat3A;
1334    #[inline]
1335    fn div(self, rhs: &Mat3A) -> Mat3A {
1336        self.div(*rhs)
1337    }
1338}
1339
1340impl Div<&Mat3A> for &f32 {
1341    type Output = Mat3A;
1342    #[inline]
1343    fn div(self, rhs: &Mat3A) -> Mat3A {
1344        (*self).div(*rhs)
1345    }
1346}
1347
1348impl Div<Mat3A> for &f32 {
1349    type Output = Mat3A;
1350    #[inline]
1351    fn div(self, rhs: Mat3A) -> Mat3A {
1352        (*self).div(rhs)
1353    }
1354}
1355
1356impl Div<f32> for Mat3A {
1357    type Output = Self;
1358    #[inline]
1359    fn div(self, rhs: f32) -> Self {
1360        self.div_scalar(rhs)
1361    }
1362}
1363
1364impl Div<&f32> for Mat3A {
1365    type Output = Self;
1366    #[inline]
1367    fn div(self, rhs: &f32) -> Self {
1368        self.div(*rhs)
1369    }
1370}
1371
1372impl Div<&f32> for &Mat3A {
1373    type Output = Mat3A;
1374    #[inline]
1375    fn div(self, rhs: &f32) -> Mat3A {
1376        (*self).div(*rhs)
1377    }
1378}
1379
1380impl Div<f32> for &Mat3A {
1381    type Output = Mat3A;
1382    #[inline]
1383    fn div(self, rhs: f32) -> Mat3A {
1384        (*self).div(rhs)
1385    }
1386}
1387
1388impl DivAssign<f32> for Mat3A {
1389    #[inline]
1390    fn div_assign(&mut self, rhs: f32) {
1391        *self = self.div(rhs);
1392    }
1393}
1394
1395impl DivAssign<&f32> for Mat3A {
1396    #[inline]
1397    fn div_assign(&mut self, rhs: &f32) {
1398        self.div_assign(*rhs);
1399    }
1400}
1401
1402impl Mul<Vec3> for Mat3A {
1403    type Output = Vec3;
1404    #[inline]
1405    fn mul(self, rhs: Vec3) -> Vec3 {
1406        self.mul_vec3a(rhs.into()).into()
1407    }
1408}
1409
1410impl Mul<&Vec3> for Mat3A {
1411    type Output = Vec3;
1412    #[inline]
1413    fn mul(self, rhs: &Vec3) -> Vec3 {
1414        self.mul(*rhs)
1415    }
1416}
1417
1418impl Mul<&Vec3> for &Mat3A {
1419    type Output = Vec3;
1420    #[inline]
1421    fn mul(self, rhs: &Vec3) -> Vec3 {
1422        (*self).mul(*rhs)
1423    }
1424}
1425
1426impl Mul<Vec3> for &Mat3A {
1427    type Output = Vec3;
1428    #[inline]
1429    fn mul(self, rhs: Vec3) -> Vec3 {
1430        (*self).mul(rhs)
1431    }
1432}
1433
1434impl From<Mat3> for Mat3A {
1435    #[inline]
1436    fn from(m: Mat3) -> Self {
1437        Self {
1438            x_axis: m.x_axis.into(),
1439            y_axis: m.y_axis.into(),
1440            z_axis: m.z_axis.into(),
1441        }
1442    }
1443}
1444
1445impl Sum<Self> for Mat3A {
1446    fn sum<I>(iter: I) -> Self
1447    where
1448        I: Iterator<Item = Self>,
1449    {
1450        iter.fold(Self::ZERO, Self::add)
1451    }
1452}
1453
1454impl<'a> Sum<&'a Self> for Mat3A {
1455    fn sum<I>(iter: I) -> Self
1456    where
1457        I: Iterator<Item = &'a Self>,
1458    {
1459        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1460    }
1461}
1462
1463impl Product for Mat3A {
1464    fn product<I>(iter: I) -> Self
1465    where
1466        I: Iterator<Item = Self>,
1467    {
1468        iter.fold(Self::IDENTITY, Self::mul)
1469    }
1470}
1471
1472impl<'a> Product<&'a Self> for Mat3A {
1473    fn product<I>(iter: I) -> Self
1474    where
1475        I: Iterator<Item = &'a Self>,
1476    {
1477        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1478    }
1479}
1480
1481impl PartialEq for Mat3A {
1482    #[inline]
1483    fn eq(&self, rhs: &Self) -> bool {
1484        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
1485    }
1486}
1487
1488impl fmt::Debug for Mat3A {
1489    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1490        fmt.debug_struct(stringify!(Mat3A))
1491            .field("x_axis", &self.x_axis)
1492            .field("y_axis", &self.y_axis)
1493            .field("z_axis", &self.z_axis)
1494            .finish()
1495    }
1496}
1497
1498impl fmt::Display for Mat3A {
1499    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1500        if let Some(p) = f.precision() {
1501            write!(
1502                f,
1503                "[{:.*}, {:.*}, {:.*}]",
1504                p, self.x_axis, p, self.y_axis, p, self.z_axis
1505            )
1506        } else {
1507            write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
1508        }
1509    }
1510}