Skip to main content

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