1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{f64::math, swizzles::*, DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4};
4 #[cfg(not(target_arch = "spirv"))]
5 use core::fmt;
6 use core::iter::{Product, Sum};
7 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8 
9 /// Creates a 4x4 matrix from four column vectors.
10 #[inline(always)]
11 #[must_use]
dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat412 pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
13     DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
14 }
15 
16 /// A 4x4 column major matrix.
17 ///
18 /// This 4x4 matrix type features convenience methods for creating and using affine transforms and
19 /// perspective projections. If you are primarily dealing with 3D affine transformations
20 /// considering using [`DAffine3`](crate::DAffine3) which is faster than a 4x4 matrix
21 /// for some affine operations.
22 ///
23 /// Affine transformations including 3D translation, rotation and scale can be created
24 /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`],
25 /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`].
26 ///
27 /// Orthographic projections can be created using the methods [`Self::orthographic_lh()`] for
28 /// left-handed coordinate systems and [`Self::orthographic_rh()`] for right-handed
29 /// systems. The resulting matrix is also an affine transformation.
30 ///
31 /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods
32 /// are provided for performing affine transformations on 3D vectors and points. These
33 /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0`
34 /// for vectors respectively. These methods assume that `Self` contains a valid affine
35 /// transform.
36 ///
37 /// Perspective projections can be created using methods such as
38 /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and
39 /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and
40 /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and
41 /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems.
42 ///
43 /// The resulting perspective project can be use to transform 3D vectors as points with
44 /// perspective correction using the [`Self::project_point3()`] convenience method.
45 #[derive(Clone, Copy)]
46 #[cfg_attr(feature = "cuda", repr(align(16)))]
47 #[repr(C)]
48 pub struct DMat4 {
49     pub x_axis: DVec4,
50     pub y_axis: DVec4,
51     pub z_axis: DVec4,
52     pub w_axis: DVec4,
53 }
54 
55 impl DMat4 {
56     /// A 4x4 matrix with all elements set to `0.0`.
57     pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
58 
59     /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
60     pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
61 
62     /// All NAN:s.
63     pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
64 
65     #[allow(clippy::too_many_arguments)]
66     #[inline(always)]
67     #[must_use]
new( m00: f64, m01: f64, m02: f64, m03: f64, m10: f64, m11: f64, m12: f64, m13: f64, m20: f64, m21: f64, m22: f64, m23: f64, m30: f64, m31: f64, m32: f64, m33: f64, ) -> Self68     const fn new(
69         m00: f64,
70         m01: f64,
71         m02: f64,
72         m03: f64,
73         m10: f64,
74         m11: f64,
75         m12: f64,
76         m13: f64,
77         m20: f64,
78         m21: f64,
79         m22: f64,
80         m23: f64,
81         m30: f64,
82         m31: f64,
83         m32: f64,
84         m33: f64,
85     ) -> Self {
86         Self {
87             x_axis: DVec4::new(m00, m01, m02, m03),
88             y_axis: DVec4::new(m10, m11, m12, m13),
89             z_axis: DVec4::new(m20, m21, m22, m23),
90             w_axis: DVec4::new(m30, m31, m32, m33),
91         }
92     }
93 
94     /// Creates a 4x4 matrix from four column vectors.
95     #[inline(always)]
96     #[must_use]
from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self97     pub const fn from_cols(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> Self {
98         Self {
99             x_axis,
100             y_axis,
101             z_axis,
102             w_axis,
103         }
104     }
105 
106     /// Creates a 4x4 matrix from a `[f64; 16]` array stored in column major order.
107     /// If your data is stored in row major you will need to `transpose` the returned
108     /// matrix.
109     #[inline]
110     #[must_use]
from_cols_array(m: &[f64; 16]) -> Self111     pub const fn from_cols_array(m: &[f64; 16]) -> Self {
112         Self::new(
113             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],
114             m[14], m[15],
115         )
116     }
117 
118     /// Creates a `[f64; 16]` array storing data in column major order.
119     /// If you require data in row major order `transpose` the matrix first.
120     #[inline]
121     #[must_use]
to_cols_array(&self) -> [f64; 16]122     pub const fn to_cols_array(&self) -> [f64; 16] {
123         [
124             self.x_axis.x,
125             self.x_axis.y,
126             self.x_axis.z,
127             self.x_axis.w,
128             self.y_axis.x,
129             self.y_axis.y,
130             self.y_axis.z,
131             self.y_axis.w,
132             self.z_axis.x,
133             self.z_axis.y,
134             self.z_axis.z,
135             self.z_axis.w,
136             self.w_axis.x,
137             self.w_axis.y,
138             self.w_axis.z,
139             self.w_axis.w,
140         ]
141     }
142 
143     /// Creates a 4x4 matrix from a `[[f64; 4]; 4]` 4D array stored in column major order.
144     /// If your data is in row major order you will need to `transpose` the returned
145     /// matrix.
146     #[inline]
147     #[must_use]
from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self148     pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
149         Self::from_cols(
150             DVec4::from_array(m[0]),
151             DVec4::from_array(m[1]),
152             DVec4::from_array(m[2]),
153             DVec4::from_array(m[3]),
154         )
155     }
156 
157     /// Creates a `[[f64; 4]; 4]` 4D array storing data in column major order.
158     /// If you require data in row major order `transpose` the matrix first.
159     #[inline]
160     #[must_use]
to_cols_array_2d(&self) -> [[f64; 4]; 4]161     pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
162         [
163             self.x_axis.to_array(),
164             self.y_axis.to_array(),
165             self.z_axis.to_array(),
166             self.w_axis.to_array(),
167         ]
168     }
169 
170     /// Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries set to 0.
171     #[doc(alias = "scale")]
172     #[inline]
173     #[must_use]
from_diagonal(diagonal: DVec4) -> Self174     pub const fn from_diagonal(diagonal: DVec4) -> Self {
175         Self::new(
176             diagonal.x, 0.0, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, 0.0, diagonal.z, 0.0, 0.0,
177             0.0, 0.0, diagonal.w,
178         )
179     }
180 
181     #[inline]
182     #[must_use]
quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4)183     fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
184         glam_assert!(rotation.is_normalized());
185 
186         let (x, y, z, w) = rotation.into();
187         let x2 = x + x;
188         let y2 = y + y;
189         let z2 = z + z;
190         let xx = x * x2;
191         let xy = x * y2;
192         let xz = x * z2;
193         let yy = y * y2;
194         let yz = y * z2;
195         let zz = z * z2;
196         let wx = w * x2;
197         let wy = w * y2;
198         let wz = w * z2;
199 
200         let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
201         let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
202         let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
203         (x_axis, y_axis, z_axis)
204     }
205 
206     /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and
207     /// `translation`.
208     ///
209     /// The resulting matrix can be used to transform 3D points and vectors. See
210     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
211     ///
212     /// # Panics
213     ///
214     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
215     #[inline]
216     #[must_use]
from_scale_rotation_translation( scale: DVec3, rotation: DQuat, translation: DVec3, ) -> Self217     pub fn from_scale_rotation_translation(
218         scale: DVec3,
219         rotation: DQuat,
220         translation: DVec3,
221     ) -> Self {
222         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
223         Self::from_cols(
224             x_axis.mul(scale.x),
225             y_axis.mul(scale.y),
226             z_axis.mul(scale.z),
227             DVec4::from((translation, 1.0)),
228         )
229     }
230 
231     /// Creates an affine transformation matrix from the given 3D `translation`.
232     ///
233     /// The resulting matrix can be used to transform 3D points and vectors. See
234     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
235     ///
236     /// # Panics
237     ///
238     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
239     #[inline]
240     #[must_use]
from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self241     pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
242         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
243         Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
244     }
245 
246     /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is
247     /// expected to be a 3D affine transformation matrix otherwise the output will be invalid.
248     ///
249     /// # Panics
250     ///
251     /// Will panic if the determinant of `self` is zero or if the resulting scale vector
252     /// contains any zero elements when `glam_assert` is enabled.
253     #[inline]
254     #[must_use]
to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3)255     pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
256         let det = self.determinant();
257         glam_assert!(det != 0.0);
258 
259         let scale = DVec3::new(
260             self.x_axis.length() * math::signum(det),
261             self.y_axis.length(),
262             self.z_axis.length(),
263         );
264 
265         glam_assert!(scale.cmpne(DVec3::ZERO).all());
266 
267         let inv_scale = scale.recip();
268 
269         let rotation = DQuat::from_rotation_axes(
270             self.x_axis.mul(inv_scale.x).xyz(),
271             self.y_axis.mul(inv_scale.y).xyz(),
272             self.z_axis.mul(inv_scale.z).xyz(),
273         );
274 
275         let translation = self.w_axis.xyz();
276 
277         (scale, rotation, translation)
278     }
279 
280     /// Creates an affine transformation matrix from the given `rotation` quaternion.
281     ///
282     /// The resulting matrix can be used to transform 3D points and vectors. See
283     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
284     ///
285     /// # Panics
286     ///
287     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
288     #[inline]
289     #[must_use]
from_quat(rotation: DQuat) -> Self290     pub fn from_quat(rotation: DQuat) -> Self {
291         let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
292         Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
293     }
294 
295     /// Creates an affine transformation matrix from the given 3x3 linear transformation
296     /// matrix.
297     ///
298     /// The resulting matrix can be used to transform 3D points and vectors. See
299     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
300     #[inline]
301     #[must_use]
from_mat3(m: DMat3) -> Self302     pub fn from_mat3(m: DMat3) -> Self {
303         Self::from_cols(
304             DVec4::from((m.x_axis, 0.0)),
305             DVec4::from((m.y_axis, 0.0)),
306             DVec4::from((m.z_axis, 0.0)),
307             DVec4::W,
308         )
309     }
310 
311     /// Creates an affine transformation matrix from the given 3D `translation`.
312     ///
313     /// The resulting matrix can be used to transform 3D points and vectors. See
314     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
315     #[inline]
316     #[must_use]
from_translation(translation: DVec3) -> Self317     pub fn from_translation(translation: DVec3) -> Self {
318         Self::from_cols(
319             DVec4::X,
320             DVec4::Y,
321             DVec4::Z,
322             DVec4::new(translation.x, translation.y, translation.z, 1.0),
323         )
324     }
325 
326     /// Creates an affine transformation matrix containing a 3D rotation around a normalized
327     /// rotation `axis` of `angle` (in radians).
328     ///
329     /// The resulting matrix can be used to transform 3D points and vectors. See
330     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
331     ///
332     /// # Panics
333     ///
334     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
335     #[inline]
336     #[must_use]
from_axis_angle(axis: DVec3, angle: f64) -> Self337     pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
338         glam_assert!(axis.is_normalized());
339 
340         let (sin, cos) = math::sin_cos(angle);
341         let axis_sin = axis.mul(sin);
342         let axis_sq = axis.mul(axis);
343         let omc = 1.0 - cos;
344         let xyomc = axis.x * axis.y * omc;
345         let xzomc = axis.x * axis.z * omc;
346         let yzomc = axis.y * axis.z * omc;
347         Self::from_cols(
348             DVec4::new(
349                 axis_sq.x * omc + cos,
350                 xyomc + axis_sin.z,
351                 xzomc - axis_sin.y,
352                 0.0,
353             ),
354             DVec4::new(
355                 xyomc - axis_sin.z,
356                 axis_sq.y * omc + cos,
357                 yzomc + axis_sin.x,
358                 0.0,
359             ),
360             DVec4::new(
361                 xzomc + axis_sin.y,
362                 yzomc - axis_sin.x,
363                 axis_sq.z * omc + cos,
364                 0.0,
365             ),
366             DVec4::W,
367         )
368     }
369 
370     /// Creates a affine transformation matrix containing a rotation from the given euler
371     /// rotation sequence and angles (in radians).
372     ///
373     /// The resulting matrix can be used to transform 3D points and vectors. See
374     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
375     #[inline]
376     #[must_use]
from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self377     pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
378         let quat = DQuat::from_euler(order, a, b, c);
379         Self::from_quat(quat)
380     }
381 
382     /// Creates an affine transformation matrix containing a 3D rotation around the x axis of
383     /// `angle` (in radians).
384     ///
385     /// The resulting matrix can be used to transform 3D points and vectors. See
386     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
387     #[inline]
388     #[must_use]
from_rotation_x(angle: f64) -> Self389     pub fn from_rotation_x(angle: f64) -> Self {
390         let (sina, cosa) = math::sin_cos(angle);
391         Self::from_cols(
392             DVec4::X,
393             DVec4::new(0.0, cosa, sina, 0.0),
394             DVec4::new(0.0, -sina, cosa, 0.0),
395             DVec4::W,
396         )
397     }
398 
399     /// Creates an affine transformation matrix containing a 3D rotation around the y axis of
400     /// `angle` (in radians).
401     ///
402     /// The resulting matrix can be used to transform 3D points and vectors. See
403     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
404     #[inline]
405     #[must_use]
from_rotation_y(angle: f64) -> Self406     pub fn from_rotation_y(angle: f64) -> Self {
407         let (sina, cosa) = math::sin_cos(angle);
408         Self::from_cols(
409             DVec4::new(cosa, 0.0, -sina, 0.0),
410             DVec4::Y,
411             DVec4::new(sina, 0.0, cosa, 0.0),
412             DVec4::W,
413         )
414     }
415 
416     /// Creates an affine transformation matrix containing a 3D rotation around the z axis of
417     /// `angle` (in radians).
418     ///
419     /// The resulting matrix can be used to transform 3D points and vectors. See
420     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
421     #[inline]
422     #[must_use]
from_rotation_z(angle: f64) -> Self423     pub fn from_rotation_z(angle: f64) -> Self {
424         let (sina, cosa) = math::sin_cos(angle);
425         Self::from_cols(
426             DVec4::new(cosa, sina, 0.0, 0.0),
427             DVec4::new(-sina, cosa, 0.0, 0.0),
428             DVec4::Z,
429             DVec4::W,
430         )
431     }
432 
433     /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`.
434     ///
435     /// The resulting matrix can be used to transform 3D points and vectors. See
436     /// [`Self::transform_point3()`] and [`Self::transform_vector3()`].
437     ///
438     /// # Panics
439     ///
440     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
441     #[inline]
442     #[must_use]
from_scale(scale: DVec3) -> Self443     pub fn from_scale(scale: DVec3) -> Self {
444         // Do not panic as long as any component is non-zero
445         glam_assert!(scale.cmpne(DVec3::ZERO).any());
446 
447         Self::from_cols(
448             DVec4::new(scale.x, 0.0, 0.0, 0.0),
449             DVec4::new(0.0, scale.y, 0.0, 0.0),
450             DVec4::new(0.0, 0.0, scale.z, 0.0),
451             DVec4::W,
452         )
453     }
454 
455     /// Creates a 4x4 matrix from the first 16 values in `slice`.
456     ///
457     /// # Panics
458     ///
459     /// Panics if `slice` is less than 16 elements long.
460     #[inline]
461     #[must_use]
from_cols_slice(slice: &[f64]) -> Self462     pub const fn from_cols_slice(slice: &[f64]) -> Self {
463         Self::new(
464             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
465             slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
466         )
467     }
468 
469     /// Writes the columns of `self` to the first 16 elements in `slice`.
470     ///
471     /// # Panics
472     ///
473     /// Panics if `slice` is less than 16 elements long.
474     #[inline]
write_cols_to_slice(self, slice: &mut [f64])475     pub fn write_cols_to_slice(self, slice: &mut [f64]) {
476         slice[0] = self.x_axis.x;
477         slice[1] = self.x_axis.y;
478         slice[2] = self.x_axis.z;
479         slice[3] = self.x_axis.w;
480         slice[4] = self.y_axis.x;
481         slice[5] = self.y_axis.y;
482         slice[6] = self.y_axis.z;
483         slice[7] = self.y_axis.w;
484         slice[8] = self.z_axis.x;
485         slice[9] = self.z_axis.y;
486         slice[10] = self.z_axis.z;
487         slice[11] = self.z_axis.w;
488         slice[12] = self.w_axis.x;
489         slice[13] = self.w_axis.y;
490         slice[14] = self.w_axis.z;
491         slice[15] = self.w_axis.w;
492     }
493 
494     /// Returns the matrix column for the given `index`.
495     ///
496     /// # Panics
497     ///
498     /// Panics if `index` is greater than 3.
499     #[inline]
500     #[must_use]
col(&self, index: usize) -> DVec4501     pub fn col(&self, index: usize) -> DVec4 {
502         match index {
503             0 => self.x_axis,
504             1 => self.y_axis,
505             2 => self.z_axis,
506             3 => self.w_axis,
507             _ => panic!("index out of bounds"),
508         }
509     }
510 
511     /// Returns a mutable reference to the matrix column for the given `index`.
512     ///
513     /// # Panics
514     ///
515     /// Panics if `index` is greater than 3.
516     #[inline]
col_mut(&mut self, index: usize) -> &mut DVec4517     pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
518         match index {
519             0 => &mut self.x_axis,
520             1 => &mut self.y_axis,
521             2 => &mut self.z_axis,
522             3 => &mut self.w_axis,
523             _ => panic!("index out of bounds"),
524         }
525     }
526 
527     /// Returns the matrix row for the given `index`.
528     ///
529     /// # Panics
530     ///
531     /// Panics if `index` is greater than 3.
532     #[inline]
533     #[must_use]
row(&self, index: usize) -> DVec4534     pub fn row(&self, index: usize) -> DVec4 {
535         match index {
536             0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
537             1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
538             2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
539             3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
540             _ => panic!("index out of bounds"),
541         }
542     }
543 
544     /// Returns `true` if, and only if, all elements are finite.
545     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
546     #[inline]
547     #[must_use]
is_finite(&self) -> bool548     pub fn is_finite(&self) -> bool {
549         self.x_axis.is_finite()
550             && self.y_axis.is_finite()
551             && self.z_axis.is_finite()
552             && self.w_axis.is_finite()
553     }
554 
555     /// Returns `true` if any elements are `NaN`.
556     #[inline]
557     #[must_use]
is_nan(&self) -> bool558     pub fn is_nan(&self) -> bool {
559         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
560     }
561 
562     /// Returns the transpose of `self`.
563     #[inline]
564     #[must_use]
transpose(&self) -> Self565     pub fn transpose(&self) -> Self {
566         Self {
567             x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
568             y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
569             z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
570             w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
571         }
572     }
573 
574     /// Returns the determinant of `self`.
575     #[must_use]
determinant(&self) -> f64576     pub fn determinant(&self) -> f64 {
577         let (m00, m01, m02, m03) = self.x_axis.into();
578         let (m10, m11, m12, m13) = self.y_axis.into();
579         let (m20, m21, m22, m23) = self.z_axis.into();
580         let (m30, m31, m32, m33) = self.w_axis.into();
581 
582         let a2323 = m22 * m33 - m23 * m32;
583         let a1323 = m21 * m33 - m23 * m31;
584         let a1223 = m21 * m32 - m22 * m31;
585         let a0323 = m20 * m33 - m23 * m30;
586         let a0223 = m20 * m32 - m22 * m30;
587         let a0123 = m20 * m31 - m21 * m30;
588 
589         m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
590             - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
591             + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
592             - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
593     }
594 
595     /// Returns the inverse of `self`.
596     ///
597     /// If the matrix is not invertible the returned matrix will be invalid.
598     ///
599     /// # Panics
600     ///
601     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
602     #[must_use]
inverse(&self) -> Self603     pub fn inverse(&self) -> Self {
604         let (m00, m01, m02, m03) = self.x_axis.into();
605         let (m10, m11, m12, m13) = self.y_axis.into();
606         let (m20, m21, m22, m23) = self.z_axis.into();
607         let (m30, m31, m32, m33) = self.w_axis.into();
608 
609         let coef00 = m22 * m33 - m32 * m23;
610         let coef02 = m12 * m33 - m32 * m13;
611         let coef03 = m12 * m23 - m22 * m13;
612 
613         let coef04 = m21 * m33 - m31 * m23;
614         let coef06 = m11 * m33 - m31 * m13;
615         let coef07 = m11 * m23 - m21 * m13;
616 
617         let coef08 = m21 * m32 - m31 * m22;
618         let coef10 = m11 * m32 - m31 * m12;
619         let coef11 = m11 * m22 - m21 * m12;
620 
621         let coef12 = m20 * m33 - m30 * m23;
622         let coef14 = m10 * m33 - m30 * m13;
623         let coef15 = m10 * m23 - m20 * m13;
624 
625         let coef16 = m20 * m32 - m30 * m22;
626         let coef18 = m10 * m32 - m30 * m12;
627         let coef19 = m10 * m22 - m20 * m12;
628 
629         let coef20 = m20 * m31 - m30 * m21;
630         let coef22 = m10 * m31 - m30 * m11;
631         let coef23 = m10 * m21 - m20 * m11;
632 
633         let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
634         let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
635         let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
636         let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
637         let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
638         let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
639 
640         let vec0 = DVec4::new(m10, m00, m00, m00);
641         let vec1 = DVec4::new(m11, m01, m01, m01);
642         let vec2 = DVec4::new(m12, m02, m02, m02);
643         let vec3 = DVec4::new(m13, m03, m03, m03);
644 
645         let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
646         let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
647         let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
648         let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
649 
650         let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
651         let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
652 
653         let inverse = Self::from_cols(
654             inv0.mul(sign_a),
655             inv1.mul(sign_b),
656             inv2.mul(sign_a),
657             inv3.mul(sign_b),
658         );
659 
660         let col0 = DVec4::new(
661             inverse.x_axis.x,
662             inverse.y_axis.x,
663             inverse.z_axis.x,
664             inverse.w_axis.x,
665         );
666 
667         let dot0 = self.x_axis.mul(col0);
668         let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
669 
670         glam_assert!(dot1 != 0.0);
671 
672         let rcp_det = dot1.recip();
673         inverse.mul(rcp_det)
674     }
675 
676     /// Creates a left-handed view matrix using a camera position, an up direction, and a facing
677     /// direction.
678     ///
679     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
680     #[inline]
681     #[must_use]
look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self682     pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
683         Self::look_to_rh(eye, -dir, up)
684     }
685 
686     /// Creates a right-handed view matrix using a camera position, an up direction, and a facing
687     /// direction.
688     ///
689     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
690     #[inline]
691     #[must_use]
look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self692     pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
693         let f = dir.normalize();
694         let s = f.cross(up).normalize();
695         let u = s.cross(f);
696 
697         Self::from_cols(
698             DVec4::new(s.x, u.x, -f.x, 0.0),
699             DVec4::new(s.y, u.y, -f.y, 0.0),
700             DVec4::new(s.z, u.z, -f.z, 0.0),
701             DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
702         )
703     }
704 
705     /// Creates a left-handed view matrix using a camera position, an up direction, and a focal
706     /// point.
707     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
708     ///
709     /// # Panics
710     ///
711     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
712     #[inline]
713     #[must_use]
look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self714     pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
715         glam_assert!(up.is_normalized());
716         Self::look_to_lh(eye, center.sub(eye), up)
717     }
718 
719     /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
720     /// point.
721     /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
722     ///
723     /// # Panics
724     ///
725     /// Will panic if `up` is not normalized when `glam_assert` is enabled.
726     #[inline]
look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self727     pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
728         glam_assert!(up.is_normalized());
729         Self::look_to_rh(eye, center.sub(eye), up)
730     }
731 
732     /// Creates a right-handed perspective projection matrix with [-1,1] depth range.
733     /// This is the same as the OpenGL `gluPerspective` function.
734     /// See <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluPerspective.xml>
735     #[inline]
736     #[must_use]
perspective_rh_gl( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64, ) -> Self737     pub fn perspective_rh_gl(
738         fov_y_radians: f64,
739         aspect_ratio: f64,
740         z_near: f64,
741         z_far: f64,
742     ) -> Self {
743         let inv_length = 1.0 / (z_near - z_far);
744         let f = 1.0 / math::tan(0.5 * fov_y_radians);
745         let a = f / aspect_ratio;
746         let b = (z_near + z_far) * inv_length;
747         let c = (2.0 * z_near * z_far) * inv_length;
748         Self::from_cols(
749             DVec4::new(a, 0.0, 0.0, 0.0),
750             DVec4::new(0.0, f, 0.0, 0.0),
751             DVec4::new(0.0, 0.0, b, -1.0),
752             DVec4::new(0.0, 0.0, c, 0.0),
753         )
754     }
755 
756     /// Creates a left-handed perspective projection matrix with `[0,1]` depth range.
757     ///
758     /// # Panics
759     ///
760     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
761     /// enabled.
762     #[inline]
763     #[must_use]
perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self764     pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
765         glam_assert!(z_near > 0.0 && z_far > 0.0);
766         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
767         let h = cos_fov / sin_fov;
768         let w = h / aspect_ratio;
769         let r = z_far / (z_far - z_near);
770         Self::from_cols(
771             DVec4::new(w, 0.0, 0.0, 0.0),
772             DVec4::new(0.0, h, 0.0, 0.0),
773             DVec4::new(0.0, 0.0, r, 1.0),
774             DVec4::new(0.0, 0.0, -r * z_near, 0.0),
775         )
776     }
777 
778     /// Creates a right-handed perspective projection matrix with `[0,1]` depth range.
779     ///
780     /// # Panics
781     ///
782     /// Will panic if `z_near` or `z_far` are less than or equal to zero when `glam_assert` is
783     /// enabled.
784     #[inline]
785     #[must_use]
perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self786     pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
787         glam_assert!(z_near > 0.0 && z_far > 0.0);
788         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
789         let h = cos_fov / sin_fov;
790         let w = h / aspect_ratio;
791         let r = z_far / (z_near - z_far);
792         Self::from_cols(
793             DVec4::new(w, 0.0, 0.0, 0.0),
794             DVec4::new(0.0, h, 0.0, 0.0),
795             DVec4::new(0.0, 0.0, r, -1.0),
796             DVec4::new(0.0, 0.0, r * z_near, 0.0),
797         )
798     }
799 
800     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
801     ///
802     /// # Panics
803     ///
804     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
805     #[inline]
806     #[must_use]
perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self807     pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
808         glam_assert!(z_near > 0.0);
809         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
810         let h = cos_fov / sin_fov;
811         let w = h / aspect_ratio;
812         Self::from_cols(
813             DVec4::new(w, 0.0, 0.0, 0.0),
814             DVec4::new(0.0, h, 0.0, 0.0),
815             DVec4::new(0.0, 0.0, 1.0, 1.0),
816             DVec4::new(0.0, 0.0, -z_near, 0.0),
817         )
818     }
819 
820     /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range.
821     ///
822     /// # Panics
823     ///
824     /// Will panic if `z_near` is less than or equal to zero when `glam_assert` is enabled.
825     #[inline]
826     #[must_use]
perspective_infinite_reverse_lh( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, ) -> Self827     pub fn perspective_infinite_reverse_lh(
828         fov_y_radians: f64,
829         aspect_ratio: f64,
830         z_near: f64,
831     ) -> Self {
832         glam_assert!(z_near > 0.0);
833         let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
834         let h = cos_fov / sin_fov;
835         let w = h / aspect_ratio;
836         Self::from_cols(
837             DVec4::new(w, 0.0, 0.0, 0.0),
838             DVec4::new(0.0, h, 0.0, 0.0),
839             DVec4::new(0.0, 0.0, 0.0, 1.0),
840             DVec4::new(0.0, 0.0, z_near, 0.0),
841         )
842     }
843 
844     /// Creates an infinite right-handed perspective projection matrix with
845     /// `[0,1]` depth range.
846     #[inline]
847     #[must_use]
perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self848     pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
849         glam_assert!(z_near > 0.0);
850         let f = 1.0 / math::tan(0.5 * fov_y_radians);
851         Self::from_cols(
852             DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
853             DVec4::new(0.0, f, 0.0, 0.0),
854             DVec4::new(0.0, 0.0, -1.0, -1.0),
855             DVec4::new(0.0, 0.0, -z_near, 0.0),
856         )
857     }
858 
859     /// Creates an infinite reverse right-handed perspective projection matrix
860     /// with `[0,1]` depth range.
861     #[inline]
862     #[must_use]
perspective_infinite_reverse_rh( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, ) -> Self863     pub fn perspective_infinite_reverse_rh(
864         fov_y_radians: f64,
865         aspect_ratio: f64,
866         z_near: f64,
867     ) -> Self {
868         glam_assert!(z_near > 0.0);
869         let f = 1.0 / math::tan(0.5 * fov_y_radians);
870         Self::from_cols(
871             DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
872             DVec4::new(0.0, f, 0.0, 0.0),
873             DVec4::new(0.0, 0.0, 0.0, -1.0),
874             DVec4::new(0.0, 0.0, z_near, 0.0),
875         )
876     }
877 
878     /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth
879     /// range.  This is the same as the OpenGL `glOrtho` function in OpenGL.
880     /// See
881     /// <https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glOrtho.xml>
882     #[inline]
883     #[must_use]
orthographic_rh_gl( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self884     pub fn orthographic_rh_gl(
885         left: f64,
886         right: f64,
887         bottom: f64,
888         top: f64,
889         near: f64,
890         far: f64,
891     ) -> Self {
892         let a = 2.0 / (right - left);
893         let b = 2.0 / (top - bottom);
894         let c = -2.0 / (far - near);
895         let tx = -(right + left) / (right - left);
896         let ty = -(top + bottom) / (top - bottom);
897         let tz = -(far + near) / (far - near);
898 
899         Self::from_cols(
900             DVec4::new(a, 0.0, 0.0, 0.0),
901             DVec4::new(0.0, b, 0.0, 0.0),
902             DVec4::new(0.0, 0.0, c, 0.0),
903             DVec4::new(tx, ty, tz, 1.0),
904         )
905     }
906 
907     /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range.
908     #[inline]
909     #[must_use]
orthographic_lh( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self910     pub fn orthographic_lh(
911         left: f64,
912         right: f64,
913         bottom: f64,
914         top: f64,
915         near: f64,
916         far: f64,
917     ) -> Self {
918         let rcp_width = 1.0 / (right - left);
919         let rcp_height = 1.0 / (top - bottom);
920         let r = 1.0 / (far - near);
921         Self::from_cols(
922             DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
923             DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
924             DVec4::new(0.0, 0.0, r, 0.0),
925             DVec4::new(
926                 -(left + right) * rcp_width,
927                 -(top + bottom) * rcp_height,
928                 -r * near,
929                 1.0,
930             ),
931         )
932     }
933 
934     /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range.
935     #[inline]
936     #[must_use]
orthographic_rh( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self937     pub fn orthographic_rh(
938         left: f64,
939         right: f64,
940         bottom: f64,
941         top: f64,
942         near: f64,
943         far: f64,
944     ) -> Self {
945         let rcp_width = 1.0 / (right - left);
946         let rcp_height = 1.0 / (top - bottom);
947         let r = 1.0 / (near - far);
948         Self::from_cols(
949             DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
950             DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
951             DVec4::new(0.0, 0.0, r, 0.0),
952             DVec4::new(
953                 -(left + right) * rcp_width,
954                 -(top + bottom) * rcp_height,
955                 r * near,
956                 1.0,
957             ),
958         )
959     }
960 
961     /// Transforms the given 3D vector as a point, applying perspective correction.
962     ///
963     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`.
964     /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`.
965     ///
966     /// This method assumes that `self` contains a projective transform.
967     #[inline]
968     #[must_use]
project_point3(&self, rhs: DVec3) -> DVec3969     pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
970         let mut res = self.x_axis.mul(rhs.x);
971         res = self.y_axis.mul(rhs.y).add(res);
972         res = self.z_axis.mul(rhs.z).add(res);
973         res = self.w_axis.add(res);
974         res = res.mul(res.wwww().recip());
975         res.xyz()
976     }
977 
978     /// Transforms the given 3D vector as a point.
979     ///
980     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
981     /// `1.0`.
982     ///
983     /// This method assumes that `self` contains a valid affine transform. It does not perform
984     /// a persective divide, if `self` contains a perspective transform, or if you are unsure,
985     /// the [`Self::project_point3()`] method should be used instead.
986     ///
987     /// # Panics
988     ///
989     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
990     #[inline]
991     #[must_use]
transform_point3(&self, rhs: DVec3) -> DVec3992     pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
993         glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
994         let mut res = self.x_axis.mul(rhs.x);
995         res = self.y_axis.mul(rhs.y).add(res);
996         res = self.z_axis.mul(rhs.z).add(res);
997         res = self.w_axis.add(res);
998         res.xyz()
999     }
1000 
1001     /// Transforms the give 3D vector as a direction.
1002     ///
1003     /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is
1004     /// `0.0`.
1005     ///
1006     /// This method assumes that `self` contains a valid affine transform.
1007     ///
1008     /// # Panics
1009     ///
1010     /// Will panic if the 3rd row of `self` is not `(0, 0, 0, 1)` when `glam_assert` is enabled.
1011     #[inline]
1012     #[must_use]
transform_vector3(&self, rhs: DVec3) -> DVec31013     pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1014         glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1015         let mut res = self.x_axis.mul(rhs.x);
1016         res = self.y_axis.mul(rhs.y).add(res);
1017         res = self.z_axis.mul(rhs.z).add(res);
1018         res.xyz()
1019     }
1020 
1021     /// Transforms a 4D vector.
1022     #[inline]
1023     #[must_use]
mul_vec4(&self, rhs: DVec4) -> DVec41024     pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1025         let mut res = self.x_axis.mul(rhs.x);
1026         res = res.add(self.y_axis.mul(rhs.y));
1027         res = res.add(self.z_axis.mul(rhs.z));
1028         res = res.add(self.w_axis.mul(rhs.w));
1029         res
1030     }
1031 
1032     /// Multiplies two 4x4 matrices.
1033     #[inline]
1034     #[must_use]
mul_mat4(&self, rhs: &Self) -> Self1035     pub fn mul_mat4(&self, rhs: &Self) -> Self {
1036         Self::from_cols(
1037             self.mul(rhs.x_axis),
1038             self.mul(rhs.y_axis),
1039             self.mul(rhs.z_axis),
1040             self.mul(rhs.w_axis),
1041         )
1042     }
1043 
1044     /// Adds two 4x4 matrices.
1045     #[inline]
1046     #[must_use]
add_mat4(&self, rhs: &Self) -> Self1047     pub fn add_mat4(&self, rhs: &Self) -> Self {
1048         Self::from_cols(
1049             self.x_axis.add(rhs.x_axis),
1050             self.y_axis.add(rhs.y_axis),
1051             self.z_axis.add(rhs.z_axis),
1052             self.w_axis.add(rhs.w_axis),
1053         )
1054     }
1055 
1056     /// Subtracts two 4x4 matrices.
1057     #[inline]
1058     #[must_use]
sub_mat4(&self, rhs: &Self) -> Self1059     pub fn sub_mat4(&self, rhs: &Self) -> Self {
1060         Self::from_cols(
1061             self.x_axis.sub(rhs.x_axis),
1062             self.y_axis.sub(rhs.y_axis),
1063             self.z_axis.sub(rhs.z_axis),
1064             self.w_axis.sub(rhs.w_axis),
1065         )
1066     }
1067 
1068     /// Multiplies a 4x4 matrix by a scalar.
1069     #[inline]
1070     #[must_use]
mul_scalar(&self, rhs: f64) -> Self1071     pub fn mul_scalar(&self, rhs: f64) -> Self {
1072         Self::from_cols(
1073             self.x_axis.mul(rhs),
1074             self.y_axis.mul(rhs),
1075             self.z_axis.mul(rhs),
1076             self.w_axis.mul(rhs),
1077         )
1078     }
1079 
1080     /// Returns true if the absolute difference of all elements between `self` and `rhs`
1081     /// is less than or equal to `max_abs_diff`.
1082     ///
1083     /// This can be used to compare if two matrices contain similar elements. It works best
1084     /// when comparing with a known value. The `max_abs_diff` that should be used used
1085     /// depends on the values being compared against.
1086     ///
1087     /// For more see
1088     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
1089     #[inline]
1090     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool1091     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1092         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1093             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1094             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1095             && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1096     }
1097 
1098     #[inline]
as_mat4(&self) -> Mat41099     pub fn as_mat4(&self) -> Mat4 {
1100         Mat4::from_cols(
1101             self.x_axis.as_vec4(),
1102             self.y_axis.as_vec4(),
1103             self.z_axis.as_vec4(),
1104             self.w_axis.as_vec4(),
1105         )
1106     }
1107 }
1108 
1109 impl Default for DMat4 {
1110     #[inline]
default() -> Self1111     fn default() -> Self {
1112         Self::IDENTITY
1113     }
1114 }
1115 
1116 impl Add<DMat4> for DMat4 {
1117     type Output = Self;
1118     #[inline]
add(self, rhs: Self) -> Self::Output1119     fn add(self, rhs: Self) -> Self::Output {
1120         self.add_mat4(&rhs)
1121     }
1122 }
1123 
1124 impl AddAssign<DMat4> for DMat4 {
1125     #[inline]
add_assign(&mut self, rhs: Self)1126     fn add_assign(&mut self, rhs: Self) {
1127         *self = self.add_mat4(&rhs);
1128     }
1129 }
1130 
1131 impl Sub<DMat4> for DMat4 {
1132     type Output = Self;
1133     #[inline]
sub(self, rhs: Self) -> Self::Output1134     fn sub(self, rhs: Self) -> Self::Output {
1135         self.sub_mat4(&rhs)
1136     }
1137 }
1138 
1139 impl SubAssign<DMat4> for DMat4 {
1140     #[inline]
sub_assign(&mut self, rhs: Self)1141     fn sub_assign(&mut self, rhs: Self) {
1142         *self = self.sub_mat4(&rhs);
1143     }
1144 }
1145 
1146 impl Neg for DMat4 {
1147     type Output = Self;
1148     #[inline]
neg(self) -> Self::Output1149     fn neg(self) -> Self::Output {
1150         Self::from_cols(
1151             self.x_axis.neg(),
1152             self.y_axis.neg(),
1153             self.z_axis.neg(),
1154             self.w_axis.neg(),
1155         )
1156     }
1157 }
1158 
1159 impl Mul<DMat4> for DMat4 {
1160     type Output = Self;
1161     #[inline]
mul(self, rhs: Self) -> Self::Output1162     fn mul(self, rhs: Self) -> Self::Output {
1163         self.mul_mat4(&rhs)
1164     }
1165 }
1166 
1167 impl MulAssign<DMat4> for DMat4 {
1168     #[inline]
mul_assign(&mut self, rhs: Self)1169     fn mul_assign(&mut self, rhs: Self) {
1170         *self = self.mul_mat4(&rhs);
1171     }
1172 }
1173 
1174 impl Mul<DVec4> for DMat4 {
1175     type Output = DVec4;
1176     #[inline]
mul(self, rhs: DVec4) -> Self::Output1177     fn mul(self, rhs: DVec4) -> Self::Output {
1178         self.mul_vec4(rhs)
1179     }
1180 }
1181 
1182 impl Mul<DMat4> for f64 {
1183     type Output = DMat4;
1184     #[inline]
mul(self, rhs: DMat4) -> Self::Output1185     fn mul(self, rhs: DMat4) -> Self::Output {
1186         rhs.mul_scalar(self)
1187     }
1188 }
1189 
1190 impl Mul<f64> for DMat4 {
1191     type Output = Self;
1192     #[inline]
mul(self, rhs: f64) -> Self::Output1193     fn mul(self, rhs: f64) -> Self::Output {
1194         self.mul_scalar(rhs)
1195     }
1196 }
1197 
1198 impl MulAssign<f64> for DMat4 {
1199     #[inline]
mul_assign(&mut self, rhs: f64)1200     fn mul_assign(&mut self, rhs: f64) {
1201         *self = self.mul_scalar(rhs);
1202     }
1203 }
1204 
1205 impl Sum<Self> for DMat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,1206     fn sum<I>(iter: I) -> Self
1207     where
1208         I: Iterator<Item = Self>,
1209     {
1210         iter.fold(Self::ZERO, Self::add)
1211     }
1212 }
1213 
1214 impl<'a> Sum<&'a Self> for DMat4 {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1215     fn sum<I>(iter: I) -> Self
1216     where
1217         I: Iterator<Item = &'a Self>,
1218     {
1219         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1220     }
1221 }
1222 
1223 impl Product for DMat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,1224     fn product<I>(iter: I) -> Self
1225     where
1226         I: Iterator<Item = Self>,
1227     {
1228         iter.fold(Self::IDENTITY, Self::mul)
1229     }
1230 }
1231 
1232 impl<'a> Product<&'a Self> for DMat4 {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,1233     fn product<I>(iter: I) -> Self
1234     where
1235         I: Iterator<Item = &'a Self>,
1236     {
1237         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1238     }
1239 }
1240 
1241 impl PartialEq for DMat4 {
1242     #[inline]
eq(&self, rhs: &Self) -> bool1243     fn eq(&self, rhs: &Self) -> bool {
1244         self.x_axis.eq(&rhs.x_axis)
1245             && self.y_axis.eq(&rhs.y_axis)
1246             && self.z_axis.eq(&rhs.z_axis)
1247             && self.w_axis.eq(&rhs.w_axis)
1248     }
1249 }
1250 
1251 #[cfg(not(target_arch = "spirv"))]
1252 impl AsRef<[f64; 16]> for DMat4 {
1253     #[inline]
as_ref(&self) -> &[f64; 16]1254     fn as_ref(&self) -> &[f64; 16] {
1255         unsafe { &*(self as *const Self as *const [f64; 16]) }
1256     }
1257 }
1258 
1259 #[cfg(not(target_arch = "spirv"))]
1260 impl AsMut<[f64; 16]> for DMat4 {
1261     #[inline]
as_mut(&mut self) -> &mut [f64; 16]1262     fn as_mut(&mut self) -> &mut [f64; 16] {
1263         unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
1264     }
1265 }
1266 
1267 #[cfg(not(target_arch = "spirv"))]
1268 impl fmt::Debug for DMat4 {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1269     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1270         fmt.debug_struct(stringify!(DMat4))
1271             .field("x_axis", &self.x_axis)
1272             .field("y_axis", &self.y_axis)
1273             .field("z_axis", &self.z_axis)
1274             .field("w_axis", &self.w_axis)
1275             .finish()
1276     }
1277 }
1278 
1279 #[cfg(not(target_arch = "spirv"))]
1280 impl fmt::Display for DMat4 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1281     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1282         write!(
1283             f,
1284             "[{}, {}, {}, {}]",
1285             self.x_axis, self.y_axis, self.z_axis, self.w_axis
1286         )
1287     }
1288 }
1289