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