glam/f32/sse2/
mat4.rs

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