Skip to main content

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