1use crate::{
4 euler::{FromEuler, ToEuler},
5 f64::math,
6 swizzles::*,
7 DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4,
8};
9use core::fmt;
10use core::iter::{Product, Sum};
11use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
12
13#[cfg(feature = "zerocopy-08")]
14use zerocopy_derive_08::*;
15
16#[inline(always)]
18#[must_use]
19pub const fn dmat4(x_axis: DVec4, y_axis: DVec4, z_axis: DVec4, w_axis: DVec4) -> DMat4 {
20 DMat4::from_cols(x_axis, y_axis, z_axis, w_axis)
21}
22
23#[derive(Clone, Copy)]
39#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
40#[cfg_attr(
41 feature = "zerocopy-08",
42 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
43)]
44#[cfg_attr(feature = "cuda", repr(align(16)))]
45#[repr(C)]
46pub struct DMat4 {
47 pub x_axis: DVec4,
48 pub y_axis: DVec4,
49 pub z_axis: DVec4,
50 pub w_axis: DVec4,
51}
52
53impl DMat4 {
54 pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO);
56
57 pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W);
59
60 pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN);
62
63 #[allow(clippy::too_many_arguments)]
64 #[inline(always)]
65 #[must_use]
66 const fn new(
67 m00: f64,
68 m01: f64,
69 m02: f64,
70 m03: f64,
71 m10: f64,
72 m11: f64,
73 m12: f64,
74 m13: f64,
75 m20: f64,
76 m21: f64,
77 m22: f64,
78 m23: f64,
79 m30: f64,
80 m31: f64,
81 m32: f64,
82 m33: f64,
83 ) -> Self {
84 Self {
85 x_axis: DVec4::new(m00, m01, m02, m03),
86 y_axis: DVec4::new(m10, m11, m12, m13),
87 z_axis: DVec4::new(m20, m21, m22, m23),
88 w_axis: DVec4::new(m30, m31, m32, m33),
89 }
90 }
91
92 #[inline(always)]
96 #[must_use]
97 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 #[inline(always)]
112 #[must_use]
113 pub const fn from_rows(row0: DVec4, row1: DVec4, row2: DVec4, row3: DVec4) -> Self {
114 let [m00, m01, m02, m03] = row0.to_array();
115 let [m10, m11, m12, m13] = row1.to_array();
116 let [m20, m21, m22, m23] = row2.to_array();
117 let [m30, m31, m32, m33] = row3.to_array();
118 Self::new(
119 m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33,
120 )
121 }
122
123 #[inline]
127 #[must_use]
128 pub const fn from_cols_array(m: &[f64; 16]) -> Self {
129 Self::new(
130 m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13],
131 m[14], m[15],
132 )
133 }
134
135 #[inline]
139 #[must_use]
140 pub const fn to_cols_array(&self) -> [f64; 16] {
141 [
142 self.x_axis.x,
143 self.x_axis.y,
144 self.x_axis.z,
145 self.x_axis.w,
146 self.y_axis.x,
147 self.y_axis.y,
148 self.y_axis.z,
149 self.y_axis.w,
150 self.z_axis.x,
151 self.z_axis.y,
152 self.z_axis.z,
153 self.z_axis.w,
154 self.w_axis.x,
155 self.w_axis.y,
156 self.w_axis.z,
157 self.w_axis.w,
158 ]
159 }
160
161 #[inline]
165 #[must_use]
166 pub const fn from_cols_array_2d(m: &[[f64; 4]; 4]) -> Self {
167 Self::from_cols(
168 DVec4::from_array(m[0]),
169 DVec4::from_array(m[1]),
170 DVec4::from_array(m[2]),
171 DVec4::from_array(m[3]),
172 )
173 }
174
175 #[inline]
179 #[must_use]
180 pub const fn to_cols_array_2d(&self) -> [[f64; 4]; 4] {
181 [
182 self.x_axis.to_array(),
183 self.y_axis.to_array(),
184 self.z_axis.to_array(),
185 self.w_axis.to_array(),
186 ]
187 }
188
189 #[inline]
195 #[must_use]
196 pub const fn from_rows_array(m: &[f64; 16]) -> Self {
197 Self::new(
198 m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7],
199 m[11], m[15],
200 )
201 }
202
203 #[inline]
209 #[must_use]
210 pub const fn to_rows_array(&self) -> [f64; 16] {
211 let m = self.to_cols_array();
212 [
213 m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13], m[2], m[6], m[10], m[14], m[3], m[7],
214 m[11], m[15],
215 ]
216 }
217
218 #[doc(alias = "scale")]
220 #[inline]
221 #[must_use]
222 pub const fn from_diagonal(diagonal: DVec4) -> Self {
223 Self::new(
224 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,
225 0.0, 0.0, diagonal.w,
226 )
227 }
228
229 #[inline]
230 #[must_use]
231 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
232 fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) {
233 glam_assert!(rotation.is_normalized());
234
235 let (x, y, z, w) = rotation.into();
236 let x2 = x + x;
237 let y2 = y + y;
238 let z2 = z + z;
239 let xx = x * x2;
240 let xy = x * y2;
241 let xz = x * z2;
242 let yy = y * y2;
243 let yz = y * z2;
244 let zz = z * z2;
245 let wx = w * x2;
246 let wy = w * y2;
247 let wz = w * z2;
248
249 let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
250 let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
251 let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
252 (x_axis, y_axis, z_axis)
253 }
254
255 #[inline]
265 #[must_use]
266 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
267 pub fn from_scale_rotation_translation(
268 scale: DVec3,
269 rotation: DQuat,
270 translation: DVec3,
271 ) -> Self {
272 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
273 Self::from_cols(
274 x_axis.mul(scale.x),
275 y_axis.mul(scale.y),
276 z_axis.mul(scale.z),
277 DVec4::from((translation, 1.0)),
278 )
279 }
280
281 #[inline]
290 #[must_use]
291 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
292 pub fn from_rotation_translation(rotation: DQuat, translation: DVec3) -> Self {
293 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
294 Self::from_cols(x_axis, y_axis, z_axis, DVec4::from((translation, 1.0)))
295 }
296
297 #[inline]
305 #[must_use]
306 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
307 pub fn to_scale_rotation_translation(&self) -> (DVec3, DQuat, DVec3) {
308 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
309
310 let r = DMat3::from_mat4(*self);
311
312 let det = r.determinant();
313
314 glam_assert!(det != 0.0);
315
316 let scale = DVec3::new(
317 r.x_axis.length() * math::signum(det),
318 r.y_axis.length(),
319 r.z_axis.length(),
320 );
321
322 glam_assert!(scale.cmpne(DVec3::ZERO).all());
323
324 let inv_scale = scale.recip();
325
326 let rotation = DQuat::from_rotation_axes(
327 r.x_axis.mul(inv_scale.x),
328 r.y_axis.mul(inv_scale.y),
329 r.z_axis.mul(inv_scale.z),
330 );
331
332 let translation = self.w_axis.xyz();
333
334 (scale, rotation, translation)
335 }
336
337 #[inline]
346 #[must_use]
347 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
348 pub fn from_quat(rotation: DQuat) -> Self {
349 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
350 Self::from_cols(x_axis, y_axis, z_axis, DVec4::W)
351 }
352
353 #[inline]
359 #[must_use]
360 pub fn from_mat3(m: DMat3) -> Self {
361 Self::from_cols(
362 DVec4::from((m.x_axis, 0.0)),
363 DVec4::from((m.y_axis, 0.0)),
364 DVec4::from((m.z_axis, 0.0)),
365 DVec4::W,
366 )
367 }
368
369 #[inline]
374 #[must_use]
375 pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self {
376 Self::from_cols(
377 DVec4::from((mat3.x_axis, 0.0)),
378 DVec4::from((mat3.y_axis, 0.0)),
379 DVec4::from((mat3.z_axis, 0.0)),
380 DVec4::from((translation, 1.0)),
381 )
382 }
383
384 #[inline]
389 #[must_use]
390 pub fn from_translation(translation: DVec3) -> Self {
391 Self::from_cols(
392 DVec4::X,
393 DVec4::Y,
394 DVec4::Z,
395 DVec4::new(translation.x, translation.y, translation.z, 1.0),
396 )
397 }
398
399 #[inline]
409 #[must_use]
410 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
411 pub fn from_axis_angle(axis: DVec3, angle: f64) -> Self {
412 glam_assert!(axis.is_normalized());
413
414 let (sin, cos) = math::sin_cos(angle);
415 let axis_sin = axis.mul(sin);
416 let axis_sq = axis.mul(axis);
417 let omc = 1.0 - cos;
418 let xyomc = axis.x * axis.y * omc;
419 let xzomc = axis.x * axis.z * omc;
420 let yzomc = axis.y * axis.z * omc;
421 Self::from_cols(
422 DVec4::new(
423 axis_sq.x * omc + cos,
424 xyomc + axis_sin.z,
425 xzomc - axis_sin.y,
426 0.0,
427 ),
428 DVec4::new(
429 xyomc - axis_sin.z,
430 axis_sq.y * omc + cos,
431 yzomc + axis_sin.x,
432 0.0,
433 ),
434 DVec4::new(
435 xzomc + axis_sin.y,
436 yzomc - axis_sin.x,
437 axis_sq.z * omc + cos,
438 0.0,
439 ),
440 DVec4::W,
441 )
442 }
443
444 #[inline]
450 #[must_use]
451 pub fn from_euler(order: EulerRot, a: f64, b: f64, c: f64) -> Self {
452 Self::from_euler_angles(order, a, b, c)
453 }
454
455 #[inline]
465 #[must_use]
466 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
467 pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) {
468 glam_assert!(
469 self.x_axis.xyz().is_normalized()
470 && self.y_axis.xyz().is_normalized()
471 && self.z_axis.xyz().is_normalized()
472 );
473 DMat3::from_mat4(*self).to_euler_angles(order)
474 }
475
476 #[inline]
482 #[must_use]
483 pub fn from_rotation_x(angle: f64) -> Self {
484 let (sina, cosa) = math::sin_cos(angle);
485 Self::from_cols(
486 DVec4::X,
487 DVec4::new(0.0, cosa, sina, 0.0),
488 DVec4::new(0.0, -sina, cosa, 0.0),
489 DVec4::W,
490 )
491 }
492
493 #[inline]
499 #[must_use]
500 pub fn from_rotation_y(angle: f64) -> Self {
501 let (sina, cosa) = math::sin_cos(angle);
502 Self::from_cols(
503 DVec4::new(cosa, 0.0, -sina, 0.0),
504 DVec4::Y,
505 DVec4::new(sina, 0.0, cosa, 0.0),
506 DVec4::W,
507 )
508 }
509
510 #[inline]
516 #[must_use]
517 pub fn from_rotation_z(angle: f64) -> Self {
518 let (sina, cosa) = math::sin_cos(angle);
519 Self::from_cols(
520 DVec4::new(cosa, sina, 0.0, 0.0),
521 DVec4::new(-sina, cosa, 0.0, 0.0),
522 DVec4::Z,
523 DVec4::W,
524 )
525 }
526
527 #[inline]
536 #[must_use]
537 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
538 pub fn from_scale(scale: DVec3) -> Self {
539 glam_assert!(scale.cmpne(DVec3::ZERO).any());
541
542 Self::from_cols(
543 DVec4::new(scale.x, 0.0, 0.0, 0.0),
544 DVec4::new(0.0, scale.y, 0.0, 0.0),
545 DVec4::new(0.0, 0.0, scale.z, 0.0),
546 DVec4::W,
547 )
548 }
549
550 #[inline]
558 #[must_use]
559 #[track_caller]
560 pub const fn from_cols_slice(slice: &[f64]) -> Self {
561 Self::new(
562 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
563 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
564 )
565 }
566
567 #[inline]
573 #[track_caller]
574 pub fn write_cols_to_slice(&self, slice: &mut [f64]) {
575 slice[0] = self.x_axis.x;
576 slice[1] = self.x_axis.y;
577 slice[2] = self.x_axis.z;
578 slice[3] = self.x_axis.w;
579 slice[4] = self.y_axis.x;
580 slice[5] = self.y_axis.y;
581 slice[6] = self.y_axis.z;
582 slice[7] = self.y_axis.w;
583 slice[8] = self.z_axis.x;
584 slice[9] = self.z_axis.y;
585 slice[10] = self.z_axis.z;
586 slice[11] = self.z_axis.w;
587 slice[12] = self.w_axis.x;
588 slice[13] = self.w_axis.y;
589 slice[14] = self.w_axis.z;
590 slice[15] = self.w_axis.w;
591 }
592
593 #[inline]
604 #[must_use]
605 #[track_caller]
606 pub const fn from_rows_slice(slice: &[f64]) -> Self {
607 Self::new(
608 slice[0], slice[4], slice[8], slice[12], slice[1], slice[5], slice[9], slice[13],
609 slice[2], slice[6], slice[10], slice[14], slice[3], slice[7], slice[11], slice[15],
610 )
611 }
612
613 #[inline]
619 #[must_use]
620 #[track_caller]
621 pub fn col(&self, index: usize) -> DVec4 {
622 match index {
623 0 => self.x_axis,
624 1 => self.y_axis,
625 2 => self.z_axis,
626 3 => self.w_axis,
627 _ => panic!("index out of bounds"),
628 }
629 }
630
631 #[inline]
637 #[track_caller]
638 pub fn col_mut(&mut self, index: usize) -> &mut DVec4 {
639 match index {
640 0 => &mut self.x_axis,
641 1 => &mut self.y_axis,
642 2 => &mut self.z_axis,
643 3 => &mut self.w_axis,
644 _ => panic!("index out of bounds"),
645 }
646 }
647
648 #[inline]
656 #[must_use]
657 #[track_caller]
658 pub fn row(&self, index: usize) -> DVec4 {
659 match index {
660 0 => DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
661 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
662 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
663 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
664 _ => panic!("index out of bounds"),
665 }
666 }
667
668 #[inline]
678 #[track_caller]
679 pub fn set_row(&mut self, index: usize, row: DVec4) {
680 match index {
681 0 => {
682 self.x_axis.x = row.x;
683 self.y_axis.x = row.y;
684 self.z_axis.x = row.z;
685 self.w_axis.x = row.w;
686 }
687 1 => {
688 self.x_axis.y = row.x;
689 self.y_axis.y = row.y;
690 self.z_axis.y = row.z;
691 self.w_axis.y = row.w;
692 }
693 2 => {
694 self.x_axis.z = row.x;
695 self.y_axis.z = row.y;
696 self.z_axis.z = row.z;
697 self.w_axis.z = row.w;
698 }
699 3 => {
700 self.x_axis.w = row.x;
701 self.y_axis.w = row.y;
702 self.z_axis.w = row.z;
703 self.w_axis.w = row.w;
704 }
705 _ => panic!("index out of bounds"),
706 }
707 }
708
709 #[inline]
712 #[must_use]
713 pub fn is_finite(&self) -> bool {
714 self.x_axis.is_finite()
715 && self.y_axis.is_finite()
716 && self.z_axis.is_finite()
717 && self.w_axis.is_finite()
718 }
719
720 #[inline]
722 #[must_use]
723 pub fn is_nan(&self) -> bool {
724 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
725 }
726
727 #[inline]
729 #[must_use]
730 pub fn transpose(&self) -> Self {
731 Self {
732 x_axis: DVec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
733 y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
734 z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
735 w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
736 }
737 }
738
739 #[inline]
741 #[must_use]
742 pub fn diagonal(&self) -> DVec4 {
743 DVec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
744 }
745
746 #[must_use]
748 pub fn determinant(&self) -> f64 {
749 let (m00, m01, m02, m03) = self.x_axis.into();
750 let (m10, m11, m12, m13) = self.y_axis.into();
751 let (m20, m21, m22, m23) = self.z_axis.into();
752 let (m30, m31, m32, m33) = self.w_axis.into();
753
754 let a2323 = m22 * m33 - m23 * m32;
755 let a1323 = m21 * m33 - m23 * m31;
756 let a1223 = m21 * m32 - m22 * m31;
757 let a0323 = m20 * m33 - m23 * m30;
758 let a0223 = m20 * m32 - m22 * m30;
759 let a0123 = m20 * m31 - m21 * m30;
760
761 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
762 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
763 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
764 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
765 }
766
767 #[inline(always)]
779 #[must_use]
780 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
781 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
782 let (m00, m01, m02, m03) = self.x_axis.into();
783 let (m10, m11, m12, m13) = self.y_axis.into();
784 let (m20, m21, m22, m23) = self.z_axis.into();
785 let (m30, m31, m32, m33) = self.w_axis.into();
786
787 let coef00 = m22 * m33 - m32 * m23;
788 let coef02 = m12 * m33 - m32 * m13;
789 let coef03 = m12 * m23 - m22 * m13;
790
791 let coef04 = m21 * m33 - m31 * m23;
792 let coef06 = m11 * m33 - m31 * m13;
793 let coef07 = m11 * m23 - m21 * m13;
794
795 let coef08 = m21 * m32 - m31 * m22;
796 let coef10 = m11 * m32 - m31 * m12;
797 let coef11 = m11 * m22 - m21 * m12;
798
799 let coef12 = m20 * m33 - m30 * m23;
800 let coef14 = m10 * m33 - m30 * m13;
801 let coef15 = m10 * m23 - m20 * m13;
802
803 let coef16 = m20 * m32 - m30 * m22;
804 let coef18 = m10 * m32 - m30 * m12;
805 let coef19 = m10 * m22 - m20 * m12;
806
807 let coef20 = m20 * m31 - m30 * m21;
808 let coef22 = m10 * m31 - m30 * m11;
809 let coef23 = m10 * m21 - m20 * m11;
810
811 let fac0 = DVec4::new(coef00, coef00, coef02, coef03);
812 let fac1 = DVec4::new(coef04, coef04, coef06, coef07);
813 let fac2 = DVec4::new(coef08, coef08, coef10, coef11);
814 let fac3 = DVec4::new(coef12, coef12, coef14, coef15);
815 let fac4 = DVec4::new(coef16, coef16, coef18, coef19);
816 let fac5 = DVec4::new(coef20, coef20, coef22, coef23);
817
818 let vec0 = DVec4::new(m10, m00, m00, m00);
819 let vec1 = DVec4::new(m11, m01, m01, m01);
820 let vec2 = DVec4::new(m12, m02, m02, m02);
821 let vec3 = DVec4::new(m13, m03, m03, m03);
822
823 let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2));
824 let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4));
825 let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5));
826 let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5));
827
828 let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0);
829 let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0);
830
831 let inverse = Self::from_cols(
832 inv0.mul(sign_a),
833 inv1.mul(sign_b),
834 inv2.mul(sign_a),
835 inv3.mul(sign_b),
836 );
837
838 let col0 = DVec4::new(
839 inverse.x_axis.x,
840 inverse.y_axis.x,
841 inverse.z_axis.x,
842 inverse.w_axis.x,
843 );
844
845 let dot0 = self.x_axis.mul(col0);
846 let dot1 = dot0.x + dot0.y + dot0.z + dot0.w;
847 let m = inverse.mul(1.0 / dot1);
848
849 if CHECKED {
850 if !m.is_finite() {
851 return (Self::ZERO, false);
852 }
853 } else {
854 glam_assert!(m.is_finite());
855 }
856
857 (m, true)
858 }
859
860 #[must_use]
872 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
873 pub fn inverse(&self) -> Self {
874 self.inverse_checked::<false>().0
875 }
876
877 #[must_use]
880 pub fn try_inverse(&self) -> Option<Self> {
881 let (m, is_valid) = self.inverse_checked::<true>();
882 if is_valid {
883 Some(m)
884 } else {
885 None
886 }
887 }
888
889 #[must_use]
892 pub fn inverse_or_zero(&self) -> Self {
893 self.inverse_checked::<true>().0
894 }
895
896 #[deprecated(
906 since = "0.33.1",
907 note = "use the `glam::dcamera::lh::view::look_to_mat4` function instead"
908 )]
909 #[inline]
910 #[must_use]
911 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
912 pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
913 #[allow(deprecated)]
914 Self::look_to_rh(eye, -dir, up)
915 }
916
917 #[deprecated(
927 since = "0.33.1",
928 note = "use the `glam::dcamera::rh::view::look_to_mat4` function instead"
929 )]
930 #[inline]
931 #[must_use]
932 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
933 pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self {
934 glam_assert!(dir.is_normalized());
935 glam_assert!(up.is_normalized());
936 let f = dir;
937 let s = f.cross(up).normalize();
938 let u = s.cross(f);
939
940 Self::from_cols(
941 DVec4::new(s.x, u.x, -f.x, 0.0),
942 DVec4::new(s.y, u.y, -f.y, 0.0),
943 DVec4::new(s.z, u.z, -f.z, 0.0),
944 DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0),
945 )
946 }
947
948 #[deprecated(
958 since = "0.33.1",
959 note = "use the `glam::dcamera::lh::view::look_at_mat4` function instead"
960 )]
961 #[inline]
962 #[must_use]
963 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
964 pub fn look_at_lh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
965 #[allow(deprecated)]
966 Self::look_to_lh(eye, center.sub(eye).normalize(), up)
967 }
968
969 #[deprecated(
979 since = "0.33.1",
980 note = "use the `glam::dcamera::rh::view::look_at_mat4` function instead"
981 )]
982 #[inline]
983 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
984 pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self {
985 #[allow(deprecated)]
986 Self::look_to_rh(eye, center.sub(eye).normalize(), up)
987 }
988
989 #[deprecated(
995 since = "0.33.1",
996 note = "use the `glam::dcamera::rh::proj::opengl::frustum` function instead"
997 )]
998 #[inline]
999 #[must_use]
1000 pub fn frustum_rh_gl(
1001 left: f64,
1002 right: f64,
1003 bottom: f64,
1004 top: f64,
1005 z_near: f64,
1006 z_far: f64,
1007 ) -> Self {
1008 let inv_width = 1.0 / (right - left);
1009 let inv_height = 1.0 / (top - bottom);
1010 let inv_depth = 1.0 / (z_far - z_near);
1011 let a = (right + left) * inv_width;
1012 let b = (top + bottom) * inv_height;
1013 let c = -(z_far + z_near) * inv_depth;
1014 let d = -(2.0 * z_far * z_near) * inv_depth;
1015 let two_z_near = 2.0 * z_near;
1016 Self::from_cols(
1017 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1018 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1019 DVec4::new(a, b, c, -1.0),
1020 DVec4::new(0.0, 0.0, d, 0.0),
1021 )
1022 }
1023
1024 #[deprecated(
1031 since = "0.33.1",
1032 note = "use the `glam::dcamera::lh::proj::directx::frustum` function instead"
1033 )]
1034 #[inline]
1035 #[must_use]
1036 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1037 pub fn frustum_lh(
1038 left: f64,
1039 right: f64,
1040 bottom: f64,
1041 top: f64,
1042 z_near: f64,
1043 z_far: f64,
1044 ) -> Self {
1045 glam_assert!(left != right && bottom != top);
1046 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1047 let inv_width = 1.0 / (right - left);
1048 let inv_height = 1.0 / (top - bottom);
1049 let inv_depth = 1.0 / (z_far - z_near);
1050 let a = (right + left) * inv_width;
1051 let b = (top + bottom) * inv_height;
1052 let c = z_far * inv_depth;
1053 let d = -(z_far * z_near) * inv_depth;
1054 let two_z_near = 2.0 * z_near;
1055 Self::from_cols(
1056 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1057 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1058 DVec4::new(a, b, c, 1.0),
1059 DVec4::new(0.0, 0.0, d, 0.0),
1060 )
1061 }
1062
1063 #[deprecated(
1070 since = "0.33.1",
1071 note = "use the `glam::dcamera::rh::proj::directx::frustum` function instead"
1072 )]
1073 #[inline]
1074 #[must_use]
1075 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1076 pub fn frustum_rh(
1077 left: f64,
1078 right: f64,
1079 bottom: f64,
1080 top: f64,
1081 z_near: f64,
1082 z_far: f64,
1083 ) -> Self {
1084 glam_assert!(left != right && bottom != top);
1085 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1086 let inv_width = 1.0 / (right - left);
1087 let inv_height = 1.0 / (top - bottom);
1088 let inv_depth = 1.0 / (z_far - z_near);
1089 let a = (right + left) * inv_width;
1090 let b = (top + bottom) * inv_height;
1091 let c = -z_far * inv_depth;
1092 let d = -(z_far * z_near) * inv_depth;
1093 let two_z_near = 2.0 * z_near;
1094 Self::from_cols(
1095 DVec4::new(two_z_near * inv_width, 0.0, 0.0, 0.0),
1096 DVec4::new(0.0, two_z_near * inv_height, 0.0, 0.0),
1097 DVec4::new(a, b, c, -1.0),
1098 DVec4::new(0.0, 0.0, d, 0.0),
1099 )
1100 }
1101
1102 #[deprecated(
1109 since = "0.33.1",
1110 note = "use the `glam::dcamera::rh::proj::opengl::perspective` function instead"
1111 )]
1112 #[inline]
1113 #[must_use]
1114 pub fn perspective_rh_gl(
1115 fov_y_radians: f64,
1116 aspect_ratio: f64,
1117 z_near: f64,
1118 z_far: f64,
1119 ) -> Self {
1120 let inv_length = 1.0 / (z_near - z_far);
1121 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1122 let a = f / aspect_ratio;
1123 let b = (z_near + z_far) * inv_length;
1124 let c = (2.0 * z_near * z_far) * inv_length;
1125 Self::from_cols(
1126 DVec4::new(a, 0.0, 0.0, 0.0),
1127 DVec4::new(0.0, f, 0.0, 0.0),
1128 DVec4::new(0.0, 0.0, b, -1.0),
1129 DVec4::new(0.0, 0.0, c, 0.0),
1130 )
1131 }
1132
1133 #[deprecated(
1143 since = "0.33.1",
1144 note = "use the `glam::dcamera::lh::proj::directx::perspective` function instead"
1145 )]
1146 #[inline]
1147 #[must_use]
1148 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1149 pub fn perspective_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
1150 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f64::consts::PI);
1151 glam_assert!(aspect_ratio != 0.0);
1152 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1153 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1154 let h = cos_fov / sin_fov;
1155 let w = h / aspect_ratio;
1156 let r = z_far / (z_far - z_near);
1157 Self::from_cols(
1158 DVec4::new(w, 0.0, 0.0, 0.0),
1159 DVec4::new(0.0, h, 0.0, 0.0),
1160 DVec4::new(0.0, 0.0, r, 1.0),
1161 DVec4::new(0.0, 0.0, -r * z_near, 0.0),
1162 )
1163 }
1164
1165 #[deprecated(
1175 since = "0.33.1",
1176 note = "use the `glam::dcamera::rh::proj::directx::perspective` function instead"
1177 )]
1178 #[inline]
1179 #[must_use]
1180 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1181 pub fn perspective_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64) -> Self {
1182 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f64::consts::PI);
1183 glam_assert!(aspect_ratio != 0.0);
1184 glam_assert!(z_near > 0.0 && z_far > 0.0 && z_near != z_far);
1185 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1186 let h = cos_fov / sin_fov;
1187 let w = h / aspect_ratio;
1188 let r = z_far / (z_near - z_far);
1189 Self::from_cols(
1190 DVec4::new(w, 0.0, 0.0, 0.0),
1191 DVec4::new(0.0, h, 0.0, 0.0),
1192 DVec4::new(0.0, 0.0, r, -1.0),
1193 DVec4::new(0.0, 0.0, r * z_near, 0.0),
1194 )
1195 }
1196
1197 #[deprecated(
1207 since = "0.33.1",
1208 note = "use the `glam::dcamera::lh::proj::directx::perspective_infinite` function instead"
1209 )]
1210 #[inline]
1211 #[must_use]
1212 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1213 pub fn perspective_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1214 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f64::consts::PI);
1215 glam_assert!(aspect_ratio != 0.0);
1216 glam_assert!(z_near > 0.0);
1217 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1218 let h = cos_fov / sin_fov;
1219 let w = h / aspect_ratio;
1220 Self::from_cols(
1221 DVec4::new(w, 0.0, 0.0, 0.0),
1222 DVec4::new(0.0, h, 0.0, 0.0),
1223 DVec4::new(0.0, 0.0, 1.0, 1.0),
1224 DVec4::new(0.0, 0.0, -z_near, 0.0),
1225 )
1226 }
1227
1228 #[deprecated(
1237 since = "0.33.1",
1238 note = "use the `glam::dcamera::lh::proj::directx::perspective_infinite_reverse` function instead"
1239 )]
1240 #[inline]
1241 #[must_use]
1242 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1243 pub fn perspective_infinite_reverse_lh(
1244 fov_y_radians: f64,
1245 aspect_ratio: f64,
1246 z_near: f64,
1247 ) -> Self {
1248 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f64::consts::PI);
1249 glam_assert!(aspect_ratio != 0.0);
1250 glam_assert!(z_near > 0.0);
1251 let (sin_fov, cos_fov) = math::sin_cos(0.5 * fov_y_radians);
1252 let h = cos_fov / sin_fov;
1253 let w = h / aspect_ratio;
1254 Self::from_cols(
1255 DVec4::new(w, 0.0, 0.0, 0.0),
1256 DVec4::new(0.0, h, 0.0, 0.0),
1257 DVec4::new(0.0, 0.0, 0.0, 1.0),
1258 DVec4::new(0.0, 0.0, z_near, 0.0),
1259 )
1260 }
1261
1262 #[deprecated(
1272 since = "0.33.1",
1273 note = "use the `glam::dcamera::rh::proj::directx::perspective_infinite` function instead"
1274 )]
1275 #[inline]
1276 #[must_use]
1277 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1278 pub fn perspective_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self {
1279 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f64::consts::PI);
1280 glam_assert!(aspect_ratio != 0.0);
1281 glam_assert!(z_near > 0.0);
1282 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1283 Self::from_cols(
1284 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1285 DVec4::new(0.0, f, 0.0, 0.0),
1286 DVec4::new(0.0, 0.0, -1.0, -1.0),
1287 DVec4::new(0.0, 0.0, -z_near, 0.0),
1288 )
1289 }
1290
1291 #[deprecated(
1300 since = "0.33.1",
1301 note = "use the `glam::dcamera::rh::proj::directx::perspective_infinite_reverse` function instead"
1302 )]
1303 #[inline]
1304 #[must_use]
1305 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1306 pub fn perspective_infinite_reverse_rh(
1307 fov_y_radians: f64,
1308 aspect_ratio: f64,
1309 z_near: f64,
1310 ) -> Self {
1311 glam_assert!(fov_y_radians > 0.0 && fov_y_radians < core::f64::consts::PI);
1312 glam_assert!(aspect_ratio != 0.0);
1313 glam_assert!(z_near > 0.0);
1314 let f = 1.0 / math::tan(0.5 * fov_y_radians);
1315 Self::from_cols(
1316 DVec4::new(f / aspect_ratio, 0.0, 0.0, 0.0),
1317 DVec4::new(0.0, f, 0.0, 0.0),
1318 DVec4::new(0.0, 0.0, 0.0, -1.0),
1319 DVec4::new(0.0, 0.0, z_near, 0.0),
1320 )
1321 }
1322
1323 #[deprecated(
1330 since = "0.33.1",
1331 note = "use the `glam::dcamera::rh::proj::opengl::orthographic` function instead"
1332 )]
1333 #[inline]
1334 #[must_use]
1335 pub fn orthographic_rh_gl(
1336 left: f64,
1337 right: f64,
1338 bottom: f64,
1339 top: f64,
1340 near: f64,
1341 far: f64,
1342 ) -> Self {
1343 let a = 2.0 / (right - left);
1344 let b = 2.0 / (top - bottom);
1345 let c = 2.0 / (near - far);
1346 let tx = -(right + left) / (right - left);
1347 let ty = -(top + bottom) / (top - bottom);
1348 let tz = -(far + near) / (far - near);
1349
1350 Self::from_cols(
1351 DVec4::new(a, 0.0, 0.0, 0.0),
1352 DVec4::new(0.0, b, 0.0, 0.0),
1353 DVec4::new(0.0, 0.0, c, 0.0),
1354 DVec4::new(tx, ty, tz, 1.0),
1355 )
1356 }
1357
1358 #[deprecated(
1362 since = "0.33.1",
1363 note = "use the `glam::dcamera::lh::proj::directx::orthographic` function instead"
1364 )]
1365 #[inline]
1366 #[must_use]
1367 pub fn orthographic_lh(
1368 left: f64,
1369 right: f64,
1370 bottom: f64,
1371 top: f64,
1372 near: f64,
1373 far: f64,
1374 ) -> Self {
1375 let rcp_width = 1.0 / (right - left);
1376 let rcp_height = 1.0 / (top - bottom);
1377 let r = 1.0 / (far - near);
1378 Self::from_cols(
1379 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1380 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1381 DVec4::new(0.0, 0.0, r, 0.0),
1382 DVec4::new(
1383 -(left + right) * rcp_width,
1384 -(top + bottom) * rcp_height,
1385 -r * near,
1386 1.0,
1387 ),
1388 )
1389 }
1390
1391 #[deprecated(
1395 since = "0.33.1",
1396 note = "use the `glam::dcamera::rh::proj::directx::orthographic` function instead"
1397 )]
1398 #[inline]
1399 #[must_use]
1400 pub fn orthographic_rh(
1401 left: f64,
1402 right: f64,
1403 bottom: f64,
1404 top: f64,
1405 near: f64,
1406 far: f64,
1407 ) -> Self {
1408 let rcp_width = 1.0 / (right - left);
1409 let rcp_height = 1.0 / (top - bottom);
1410 let r = 1.0 / (near - far);
1411 Self::from_cols(
1412 DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0),
1413 DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0),
1414 DVec4::new(0.0, 0.0, r, 0.0),
1415 DVec4::new(
1416 -(left + right) * rcp_width,
1417 -(top + bottom) * rcp_height,
1418 r * near,
1419 1.0,
1420 ),
1421 )
1422 }
1423
1424 #[inline]
1431 #[must_use]
1432 pub fn project_point3(&self, rhs: DVec3) -> DVec3 {
1433 let mut res = self.x_axis.mul(rhs.x);
1434 res = self.y_axis.mul(rhs.y).add(res);
1435 res = self.z_axis.mul(rhs.z).add(res);
1436 res = self.w_axis.add(res);
1437 res = res.div(res.w);
1438 res.xyz()
1439 }
1440
1441 #[inline]
1454 #[must_use]
1455 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1456 pub fn transform_point3(&self, rhs: DVec3) -> DVec3 {
1457 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1458 let mut res = self.x_axis.mul(rhs.x);
1459 res = self.y_axis.mul(rhs.y).add(res);
1460 res = self.z_axis.mul(rhs.z).add(res);
1461 res = self.w_axis.add(res);
1462 res.xyz()
1463 }
1464
1465 #[inline]
1476 #[must_use]
1477 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1478 pub fn transform_vector3(&self, rhs: DVec3) -> DVec3 {
1479 glam_assert!(self.row(3).abs_diff_eq(DVec4::W, 1e-6));
1480 let mut res = self.x_axis.mul(rhs.x);
1481 res = self.y_axis.mul(rhs.y).add(res);
1482 res = self.z_axis.mul(rhs.z).add(res);
1483 res.xyz()
1484 }
1485
1486 #[inline]
1488 #[must_use]
1489 pub fn mul_vec4(&self, rhs: DVec4) -> DVec4 {
1490 let mut res = self.x_axis.mul(rhs.x);
1491 res = res.add(self.y_axis.mul(rhs.y));
1492 res = res.add(self.z_axis.mul(rhs.z));
1493 res = res.add(self.w_axis.mul(rhs.w));
1494 res
1495 }
1496
1497 #[inline]
1499 #[must_use]
1500 pub fn mul_transpose_vec4(&self, rhs: DVec4) -> DVec4 {
1501 DVec4::new(
1502 self.x_axis.dot(rhs),
1503 self.y_axis.dot(rhs),
1504 self.z_axis.dot(rhs),
1505 self.w_axis.dot(rhs),
1506 )
1507 }
1508
1509 #[inline]
1511 #[must_use]
1512 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1513 self.mul(rhs)
1514 }
1515
1516 #[inline]
1518 #[must_use]
1519 pub fn add_mat4(&self, rhs: &Self) -> Self {
1520 self.add(rhs)
1521 }
1522
1523 #[inline]
1525 #[must_use]
1526 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1527 self.sub(rhs)
1528 }
1529
1530 #[inline]
1532 #[must_use]
1533 pub fn mul_scalar(&self, rhs: f64) -> Self {
1534 Self::from_cols(
1535 self.x_axis.mul(rhs),
1536 self.y_axis.mul(rhs),
1537 self.z_axis.mul(rhs),
1538 self.w_axis.mul(rhs),
1539 )
1540 }
1541
1542 #[inline]
1546 #[must_use]
1547 pub fn mul_diagonal_scale(&self, scale: DVec4) -> Self {
1548 Self::from_cols(
1549 self.x_axis * scale.x,
1550 self.y_axis * scale.y,
1551 self.z_axis * scale.z,
1552 self.w_axis * scale.w,
1553 )
1554 }
1555
1556 #[inline]
1558 #[must_use]
1559 pub fn div_scalar(&self, rhs: f64) -> Self {
1560 let rhs = DVec4::splat(rhs);
1561 Self::from_cols(
1562 self.x_axis.div(rhs),
1563 self.y_axis.div(rhs),
1564 self.z_axis.div(rhs),
1565 self.w_axis.div(rhs),
1566 )
1567 }
1568
1569 #[inline]
1571 #[must_use]
1572 pub fn recip(&self) -> Self {
1573 Self::from_cols(
1574 self.x_axis.recip(),
1575 self.y_axis.recip(),
1576 self.z_axis.recip(),
1577 self.w_axis.recip(),
1578 )
1579 }
1580
1581 #[inline]
1591 #[must_use]
1592 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f64) -> bool {
1593 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1594 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1595 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1596 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1597 }
1598
1599 #[inline]
1601 #[must_use]
1602 pub fn abs(&self) -> Self {
1603 Self::from_cols(
1604 self.x_axis.abs(),
1605 self.y_axis.abs(),
1606 self.z_axis.abs(),
1607 self.w_axis.abs(),
1608 )
1609 }
1610
1611 #[cfg(feature = "f64")]
1612 #[inline]
1613 #[must_use]
1614 pub fn as_mat4(&self) -> Mat4 {
1615 Mat4::from_cols(
1616 self.x_axis.as_vec4(),
1617 self.y_axis.as_vec4(),
1618 self.z_axis.as_vec4(),
1619 self.w_axis.as_vec4(),
1620 )
1621 }
1622}
1623
1624impl Default for DMat4 {
1625 #[inline]
1626 fn default() -> Self {
1627 Self::IDENTITY
1628 }
1629}
1630
1631impl Add for DMat4 {
1632 type Output = Self;
1633 #[inline]
1634 fn add(self, rhs: Self) -> Self {
1635 Self::from_cols(
1636 self.x_axis.add(rhs.x_axis),
1637 self.y_axis.add(rhs.y_axis),
1638 self.z_axis.add(rhs.z_axis),
1639 self.w_axis.add(rhs.w_axis),
1640 )
1641 }
1642}
1643
1644impl Add<&Self> for DMat4 {
1645 type Output = Self;
1646 #[inline]
1647 fn add(self, rhs: &Self) -> Self {
1648 self.add(*rhs)
1649 }
1650}
1651
1652impl Add<&DMat4> for &DMat4 {
1653 type Output = DMat4;
1654 #[inline]
1655 fn add(self, rhs: &DMat4) -> DMat4 {
1656 (*self).add(*rhs)
1657 }
1658}
1659
1660impl Add<DMat4> for &DMat4 {
1661 type Output = DMat4;
1662 #[inline]
1663 fn add(self, rhs: DMat4) -> DMat4 {
1664 (*self).add(rhs)
1665 }
1666}
1667
1668impl AddAssign for DMat4 {
1669 #[inline]
1670 fn add_assign(&mut self, rhs: Self) {
1671 *self = self.add(rhs);
1672 }
1673}
1674
1675impl AddAssign<&Self> for DMat4 {
1676 #[inline]
1677 fn add_assign(&mut self, rhs: &Self) {
1678 self.add_assign(*rhs);
1679 }
1680}
1681
1682impl Sub for DMat4 {
1683 type Output = Self;
1684 #[inline]
1685 fn sub(self, rhs: Self) -> Self {
1686 Self::from_cols(
1687 self.x_axis.sub(rhs.x_axis),
1688 self.y_axis.sub(rhs.y_axis),
1689 self.z_axis.sub(rhs.z_axis),
1690 self.w_axis.sub(rhs.w_axis),
1691 )
1692 }
1693}
1694
1695impl Sub<&Self> for DMat4 {
1696 type Output = Self;
1697 #[inline]
1698 fn sub(self, rhs: &Self) -> Self {
1699 self.sub(*rhs)
1700 }
1701}
1702
1703impl Sub<&DMat4> for &DMat4 {
1704 type Output = DMat4;
1705 #[inline]
1706 fn sub(self, rhs: &DMat4) -> DMat4 {
1707 (*self).sub(*rhs)
1708 }
1709}
1710
1711impl Sub<DMat4> for &DMat4 {
1712 type Output = DMat4;
1713 #[inline]
1714 fn sub(self, rhs: DMat4) -> DMat4 {
1715 (*self).sub(rhs)
1716 }
1717}
1718
1719impl SubAssign for DMat4 {
1720 #[inline]
1721 fn sub_assign(&mut self, rhs: Self) {
1722 *self = self.sub(rhs);
1723 }
1724}
1725
1726impl SubAssign<&Self> for DMat4 {
1727 #[inline]
1728 fn sub_assign(&mut self, rhs: &Self) {
1729 self.sub_assign(*rhs);
1730 }
1731}
1732
1733impl Neg for DMat4 {
1734 type Output = Self;
1735 #[inline]
1736 fn neg(self) -> Self::Output {
1737 Self::from_cols(
1738 self.x_axis.neg(),
1739 self.y_axis.neg(),
1740 self.z_axis.neg(),
1741 self.w_axis.neg(),
1742 )
1743 }
1744}
1745
1746impl Neg for &DMat4 {
1747 type Output = DMat4;
1748 #[inline]
1749 fn neg(self) -> DMat4 {
1750 (*self).neg()
1751 }
1752}
1753
1754impl Mul for DMat4 {
1755 type Output = Self;
1756 #[inline]
1757 fn mul(self, rhs: Self) -> Self {
1758 Self::from_cols(
1759 self.mul(rhs.x_axis),
1760 self.mul(rhs.y_axis),
1761 self.mul(rhs.z_axis),
1762 self.mul(rhs.w_axis),
1763 )
1764 }
1765}
1766
1767impl Mul<&Self> for DMat4 {
1768 type Output = Self;
1769 #[inline]
1770 fn mul(self, rhs: &Self) -> Self {
1771 self.mul(*rhs)
1772 }
1773}
1774
1775impl Mul<&DMat4> for &DMat4 {
1776 type Output = DMat4;
1777 #[inline]
1778 fn mul(self, rhs: &DMat4) -> DMat4 {
1779 (*self).mul(*rhs)
1780 }
1781}
1782
1783impl Mul<DMat4> for &DMat4 {
1784 type Output = DMat4;
1785 #[inline]
1786 fn mul(self, rhs: DMat4) -> DMat4 {
1787 (*self).mul(rhs)
1788 }
1789}
1790
1791impl MulAssign for DMat4 {
1792 #[inline]
1793 fn mul_assign(&mut self, rhs: Self) {
1794 *self = self.mul(rhs);
1795 }
1796}
1797
1798impl MulAssign<&Self> for DMat4 {
1799 #[inline]
1800 fn mul_assign(&mut self, rhs: &Self) {
1801 self.mul_assign(*rhs);
1802 }
1803}
1804
1805impl Mul<DVec4> for DMat4 {
1806 type Output = DVec4;
1807 #[inline]
1808 fn mul(self, rhs: DVec4) -> Self::Output {
1809 self.mul_vec4(rhs)
1810 }
1811}
1812
1813impl Mul<&DVec4> for DMat4 {
1814 type Output = DVec4;
1815 #[inline]
1816 fn mul(self, rhs: &DVec4) -> DVec4 {
1817 self.mul(*rhs)
1818 }
1819}
1820
1821impl Mul<&DVec4> for &DMat4 {
1822 type Output = DVec4;
1823 #[inline]
1824 fn mul(self, rhs: &DVec4) -> DVec4 {
1825 (*self).mul(*rhs)
1826 }
1827}
1828
1829impl Mul<DVec4> for &DMat4 {
1830 type Output = DVec4;
1831 #[inline]
1832 fn mul(self, rhs: DVec4) -> DVec4 {
1833 (*self).mul(rhs)
1834 }
1835}
1836
1837impl Mul<DMat4> for f64 {
1838 type Output = DMat4;
1839 #[inline]
1840 fn mul(self, rhs: DMat4) -> Self::Output {
1841 rhs.mul_scalar(self)
1842 }
1843}
1844
1845impl Mul<&DMat4> for f64 {
1846 type Output = DMat4;
1847 #[inline]
1848 fn mul(self, rhs: &DMat4) -> DMat4 {
1849 self.mul(*rhs)
1850 }
1851}
1852
1853impl Mul<&DMat4> for &f64 {
1854 type Output = DMat4;
1855 #[inline]
1856 fn mul(self, rhs: &DMat4) -> DMat4 {
1857 (*self).mul(*rhs)
1858 }
1859}
1860
1861impl Mul<DMat4> for &f64 {
1862 type Output = DMat4;
1863 #[inline]
1864 fn mul(self, rhs: DMat4) -> DMat4 {
1865 (*self).mul(rhs)
1866 }
1867}
1868
1869impl Mul<f64> for DMat4 {
1870 type Output = Self;
1871 #[inline]
1872 fn mul(self, rhs: f64) -> Self {
1873 self.mul_scalar(rhs)
1874 }
1875}
1876
1877impl Mul<&f64> for DMat4 {
1878 type Output = Self;
1879 #[inline]
1880 fn mul(self, rhs: &f64) -> Self {
1881 self.mul(*rhs)
1882 }
1883}
1884
1885impl Mul<&f64> for &DMat4 {
1886 type Output = DMat4;
1887 #[inline]
1888 fn mul(self, rhs: &f64) -> DMat4 {
1889 (*self).mul(*rhs)
1890 }
1891}
1892
1893impl Mul<f64> for &DMat4 {
1894 type Output = DMat4;
1895 #[inline]
1896 fn mul(self, rhs: f64) -> DMat4 {
1897 (*self).mul(rhs)
1898 }
1899}
1900
1901impl MulAssign<f64> for DMat4 {
1902 #[inline]
1903 fn mul_assign(&mut self, rhs: f64) {
1904 *self = self.mul(rhs);
1905 }
1906}
1907
1908impl MulAssign<&f64> for DMat4 {
1909 #[inline]
1910 fn mul_assign(&mut self, rhs: &f64) {
1911 self.mul_assign(*rhs);
1912 }
1913}
1914
1915impl Div<DMat4> for f64 {
1916 type Output = DMat4;
1917 #[inline]
1918 fn div(self, rhs: DMat4) -> Self::Output {
1919 DMat4::from_cols(
1920 self.div(rhs.x_axis),
1921 self.div(rhs.y_axis),
1922 self.div(rhs.z_axis),
1923 self.div(rhs.w_axis),
1924 )
1925 }
1926}
1927
1928impl Div<&DMat4> for f64 {
1929 type Output = DMat4;
1930 #[inline]
1931 fn div(self, rhs: &DMat4) -> DMat4 {
1932 self.div(*rhs)
1933 }
1934}
1935
1936impl Div<&DMat4> for &f64 {
1937 type Output = DMat4;
1938 #[inline]
1939 fn div(self, rhs: &DMat4) -> DMat4 {
1940 (*self).div(*rhs)
1941 }
1942}
1943
1944impl Div<DMat4> for &f64 {
1945 type Output = DMat4;
1946 #[inline]
1947 fn div(self, rhs: DMat4) -> DMat4 {
1948 (*self).div(rhs)
1949 }
1950}
1951
1952impl Div<f64> for DMat4 {
1953 type Output = Self;
1954 #[inline]
1955 fn div(self, rhs: f64) -> Self {
1956 self.div_scalar(rhs)
1957 }
1958}
1959
1960impl Div<&f64> for DMat4 {
1961 type Output = Self;
1962 #[inline]
1963 fn div(self, rhs: &f64) -> Self {
1964 self.div(*rhs)
1965 }
1966}
1967
1968impl Div<&f64> for &DMat4 {
1969 type Output = DMat4;
1970 #[inline]
1971 fn div(self, rhs: &f64) -> DMat4 {
1972 (*self).div(*rhs)
1973 }
1974}
1975
1976impl Div<f64> for &DMat4 {
1977 type Output = DMat4;
1978 #[inline]
1979 fn div(self, rhs: f64) -> DMat4 {
1980 (*self).div(rhs)
1981 }
1982}
1983
1984impl DivAssign<f64> for DMat4 {
1985 #[inline]
1986 fn div_assign(&mut self, rhs: f64) {
1987 *self = self.div(rhs);
1988 }
1989}
1990
1991impl DivAssign<&f64> for DMat4 {
1992 #[inline]
1993 fn div_assign(&mut self, rhs: &f64) {
1994 self.div_assign(*rhs);
1995 }
1996}
1997
1998impl Sum<Self> for DMat4 {
1999 fn sum<I>(iter: I) -> Self
2000 where
2001 I: Iterator<Item = Self>,
2002 {
2003 iter.fold(Self::ZERO, Self::add)
2004 }
2005}
2006
2007impl<'a> Sum<&'a Self> for DMat4 {
2008 fn sum<I>(iter: I) -> Self
2009 where
2010 I: Iterator<Item = &'a Self>,
2011 {
2012 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
2013 }
2014}
2015
2016impl Product for DMat4 {
2017 fn product<I>(iter: I) -> Self
2018 where
2019 I: Iterator<Item = Self>,
2020 {
2021 iter.fold(Self::IDENTITY, Self::mul)
2022 }
2023}
2024
2025impl<'a> Product<&'a Self> for DMat4 {
2026 fn product<I>(iter: I) -> Self
2027 where
2028 I: Iterator<Item = &'a Self>,
2029 {
2030 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
2031 }
2032}
2033
2034impl PartialEq for DMat4 {
2035 #[inline]
2036 fn eq(&self, rhs: &Self) -> bool {
2037 self.x_axis.eq(&rhs.x_axis)
2038 && self.y_axis.eq(&rhs.y_axis)
2039 && self.z_axis.eq(&rhs.z_axis)
2040 && self.w_axis.eq(&rhs.w_axis)
2041 }
2042}
2043
2044impl AsRef<[f64; 16]> for DMat4 {
2045 #[inline]
2046 fn as_ref(&self) -> &[f64; 16] {
2047 unsafe { &*(self as *const Self as *const [f64; 16]) }
2048 }
2049}
2050
2051impl AsMut<[f64; 16]> for DMat4 {
2052 #[inline]
2053 fn as_mut(&mut self) -> &mut [f64; 16] {
2054 unsafe { &mut *(self as *mut Self as *mut [f64; 16]) }
2055 }
2056}
2057
2058impl fmt::Debug for DMat4 {
2059 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2060 fmt.debug_struct(stringify!(DMat4))
2061 .field("x_axis", &self.x_axis)
2062 .field("y_axis", &self.y_axis)
2063 .field("z_axis", &self.z_axis)
2064 .field("w_axis", &self.w_axis)
2065 .finish()
2066 }
2067}
2068
2069impl fmt::Display for DMat4 {
2070 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2071 if let Some(p) = f.precision() {
2072 write!(
2073 f,
2074 "[{:.*}, {:.*}, {:.*}, {:.*}]",
2075 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
2076 )
2077 } else {
2078 write!(
2079 f,
2080 "[{}, {}, {}, {}]",
2081 self.x_axis, self.y_axis, self.z_axis, self.w_axis
2082 )
2083 }
2084 }
2085}