Skip to main content

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