Skip to main content

glam/f32/neon/
mat4.rs

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