1#[cfg(feature = "f64")]
4use crate::DMat4;
5
6use crate::{
7 EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4,
8 euler::{FromEuler, ToEuler},
9 f32::math,
10 neon::*,
11 swizzles::*,
12};
13use core::fmt;
14use core::iter::{Product, Sum};
15use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
16
17use core::arch::aarch64::*;
18
19#[cfg(feature = "zerocopy-08")]
20use zerocopy_derive_08::*;
21
22#[inline(always)]
24#[must_use]
25pub const fn mat4(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Mat4 {
26 Mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
27}
28
29#[derive(Clone, Copy)]
49#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
50#[cfg_attr(
51 feature = "zerocopy-08",
52 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
53)]
54#[repr(C)]
55pub struct Mat4 {
56 pub x_axis: Vec4,
57 pub y_axis: Vec4,
58 pub z_axis: Vec4,
59 pub w_axis: Vec4,
60}
61
62impl Mat4 {
63 pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO);
65
66 pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W);
68
69 pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN);
71
72 #[allow(clippy::too_many_arguments)]
73 #[inline(always)]
74 #[must_use]
75 const fn new(
76 m00: f32,
77 m01: f32,
78 m02: f32,
79 m03: f32,
80 m10: f32,
81 m11: f32,
82 m12: f32,
83 m13: f32,
84 m20: f32,
85 m21: f32,
86 m22: f32,
87 m23: f32,
88 m30: f32,
89 m31: f32,
90 m32: f32,
91 m33: f32,
92 ) -> Self {
93 Self {
94 x_axis: Vec4::new(m00, m01, m02, m03),
95 y_axis: Vec4::new(m10, m11, m12, m13),
96 z_axis: Vec4::new(m20, m21, m22, m23),
97 w_axis: Vec4::new(m30, m31, m32, m33),
98 }
99 }
100
101 #[inline(always)]
105 #[must_use]
106 pub const fn from_cols(x_axis: Vec4, y_axis: Vec4, z_axis: Vec4, w_axis: Vec4) -> Self {
107 Self {
108 x_axis,
109 y_axis,
110 z_axis,
111 w_axis,
112 }
113 }
114
115 #[inline(always)]
121 #[must_use]
122 pub const fn from_rows(row0: Vec4, row1: Vec4, row2: Vec4, row3: Vec4) -> Self {
123 let [m00, m01, m02, m03] = row0.to_array();
124 let [m10, m11, m12, m13] = row1.to_array();
125 let [m20, m21, m22, m23] = row2.to_array();
126 let [m30, m31, m32, m33] = row3.to_array();
127 Self::new(
128 m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33,
129 )
130 }
131
132 #[inline]
136 #[must_use]
137 pub const fn from_cols_array(m: &[f32; 16]) -> Self {
138 Self::new(
139 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],
140 m[14], m[15],
141 )
142 }
143
144 #[inline]
148 #[must_use]
149 pub const fn to_cols_array(&self) -> [f32; 16] {
150 let [x_axis_x, x_axis_y, x_axis_z, x_axis_w] = self.x_axis.to_array();
151 let [y_axis_x, y_axis_y, y_axis_z, y_axis_w] = self.y_axis.to_array();
152 let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array();
153 let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array();
154
155 [
156 x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w,
157 z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w,
158 ]
159 }
160
161 #[inline]
165 #[must_use]
166 pub const fn from_cols_array_2d(m: &[[f32; 4]; 4]) -> Self {
167 Self::from_cols(
168 Vec4::from_array(m[0]),
169 Vec4::from_array(m[1]),
170 Vec4::from_array(m[2]),
171 Vec4::from_array(m[3]),
172 )
173 }
174
175 #[inline]
179 #[must_use]
180 pub const fn to_cols_array_2d(&self) -> [[f32; 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: &[f32; 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) -> [f32; 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: Vec4) -> Self {
223 let [x, y, z, w] = diagonal.to_array();
225 Self::new(
226 x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w,
227 )
228 }
229
230 #[inline]
231 #[must_use]
232 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
233 fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) {
234 glam_assert!(rotation.is_normalized());
235
236 let (x, y, z, w) = rotation.into();
237 let x2 = x + x;
238 let y2 = y + y;
239 let z2 = z + z;
240 let xx = x * x2;
241 let xy = x * y2;
242 let xz = x * z2;
243 let yy = y * y2;
244 let yz = y * z2;
245 let zz = z * z2;
246 let wx = w * x2;
247 let wy = w * y2;
248 let wz = w * z2;
249
250 let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0);
251 let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0);
252 let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0);
253 (x_axis, y_axis, z_axis)
254 }
255
256 #[inline]
266 #[must_use]
267 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
268 pub fn from_scale_rotation_translation(scale: Vec3, rotation: Quat, translation: Vec3) -> Self {
269 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
270 Self::from_cols(
271 x_axis.mul(scale.x),
272 y_axis.mul(scale.y),
273 z_axis.mul(scale.z),
274 Vec4::from((translation, 1.0)),
275 )
276 }
277
278 #[inline]
287 #[must_use]
288 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
289 pub fn from_rotation_translation(rotation: Quat, translation: Vec3) -> Self {
290 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
291 Self::from_cols(x_axis, y_axis, z_axis, Vec4::from((translation, 1.0)))
292 }
293
294 #[inline]
302 #[must_use]
303 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
304 pub fn to_scale_rotation_translation(&self) -> (Vec3, Quat, Vec3) {
305 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
306
307 let r = Mat3A::from_mat4(*self);
308
309 let det = r.determinant();
310
311 glam_assert!(det != 0.0);
312
313 let scale = Vec3::new(
314 r.x_axis.length() * det.signum(),
315 r.y_axis.length(),
316 r.z_axis.length(),
317 );
318
319 glam_assert!(scale.cmpne(Vec3::ZERO).all());
320
321 let inv_scale = scale.recip();
322
323 let rotation = Quat::from_mat3a(&Mat3A::from_cols(
324 r.x_axis.mul(inv_scale.x),
325 r.y_axis.mul(inv_scale.y),
326 r.z_axis.mul(inv_scale.z),
327 ));
328
329 let translation = self.w_axis.xyz();
330
331 (scale, rotation, translation)
332 }
333
334 #[inline]
343 #[must_use]
344 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
345 pub fn from_quat(rotation: Quat) -> Self {
346 let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation);
347 Self::from_cols(x_axis, y_axis, z_axis, Vec4::W)
348 }
349
350 #[inline]
356 #[must_use]
357 pub fn from_mat3(m: Mat3) -> Self {
358 Self::from_cols(
359 Vec4::from((m.x_axis, 0.0)),
360 Vec4::from((m.y_axis, 0.0)),
361 Vec4::from((m.z_axis, 0.0)),
362 Vec4::W,
363 )
364 }
365
366 #[inline]
371 #[must_use]
372 pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
373 Self::from_cols(
374 Vec4::from((mat3.x_axis, 0.0)),
375 Vec4::from((mat3.y_axis, 0.0)),
376 Vec4::from((mat3.z_axis, 0.0)),
377 Vec4::from((translation, 1.0)),
378 )
379 }
380
381 #[inline]
387 #[must_use]
388 pub fn from_mat3a(m: Mat3A) -> Self {
389 Self::from_cols(
390 Vec4::from((m.x_axis, 0.0)),
391 Vec4::from((m.y_axis, 0.0)),
392 Vec4::from((m.z_axis, 0.0)),
393 Vec4::W,
394 )
395 }
396
397 #[inline]
402 #[must_use]
403 pub fn from_translation(translation: Vec3) -> Self {
404 Self::from_cols(
405 Vec4::X,
406 Vec4::Y,
407 Vec4::Z,
408 Vec4::new(translation.x, translation.y, translation.z, 1.0),
409 )
410 }
411
412 #[inline]
422 #[must_use]
423 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
424 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
425 glam_assert!(axis.is_normalized());
426
427 let (sin, cos) = math::sin_cos(angle);
428 let axis_sin = axis.mul(sin);
429 let axis_sq = axis.mul(axis);
430 let omc = 1.0 - cos;
431 let xyomc = axis.x * axis.y * omc;
432 let xzomc = axis.x * axis.z * omc;
433 let yzomc = axis.y * axis.z * omc;
434 Self::from_cols(
435 Vec4::new(
436 axis_sq.x * omc + cos,
437 xyomc + axis_sin.z,
438 xzomc - axis_sin.y,
439 0.0,
440 ),
441 Vec4::new(
442 xyomc - axis_sin.z,
443 axis_sq.y * omc + cos,
444 yzomc + axis_sin.x,
445 0.0,
446 ),
447 Vec4::new(
448 xzomc + axis_sin.y,
449 yzomc - axis_sin.x,
450 axis_sq.z * omc + cos,
451 0.0,
452 ),
453 Vec4::W,
454 )
455 }
456
457 #[inline]
463 #[must_use]
464 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
465 Self::from_euler_angles(order, a, b, c)
466 }
467
468 #[inline]
478 #[must_use]
479 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
480 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
481 glam_assert!(
482 self.x_axis.xyz().is_normalized()
483 && self.y_axis.xyz().is_normalized()
484 && self.z_axis.xyz().is_normalized()
485 );
486 Mat3::from_mat4(*self).to_euler_angles(order)
487 }
488
489 #[inline]
495 #[must_use]
496 pub fn from_rotation_x(angle: f32) -> Self {
497 let (sina, cosa) = math::sin_cos(angle);
498 Self::from_cols(
499 Vec4::X,
500 Vec4::new(0.0, cosa, sina, 0.0),
501 Vec4::new(0.0, -sina, cosa, 0.0),
502 Vec4::W,
503 )
504 }
505
506 #[inline]
512 #[must_use]
513 pub fn from_rotation_y(angle: f32) -> Self {
514 let (sina, cosa) = math::sin_cos(angle);
515 Self::from_cols(
516 Vec4::new(cosa, 0.0, -sina, 0.0),
517 Vec4::Y,
518 Vec4::new(sina, 0.0, cosa, 0.0),
519 Vec4::W,
520 )
521 }
522
523 #[inline]
529 #[must_use]
530 pub fn from_rotation_z(angle: f32) -> Self {
531 let (sina, cosa) = math::sin_cos(angle);
532 Self::from_cols(
533 Vec4::new(cosa, sina, 0.0, 0.0),
534 Vec4::new(-sina, cosa, 0.0, 0.0),
535 Vec4::Z,
536 Vec4::W,
537 )
538 }
539
540 #[inline]
549 #[must_use]
550 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
551 pub fn from_scale(scale: Vec3) -> Self {
552 glam_assert!(scale.cmpne(Vec3::ZERO).any());
554
555 Self::from_cols(
556 Vec4::new(scale.x, 0.0, 0.0, 0.0),
557 Vec4::new(0.0, scale.y, 0.0, 0.0),
558 Vec4::new(0.0, 0.0, scale.z, 0.0),
559 Vec4::W,
560 )
561 }
562
563 #[inline]
571 #[must_use]
572 #[track_caller]
573 pub const fn from_cols_slice(slice: &[f32]) -> Self {
574 Self::new(
575 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
576 slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15],
577 )
578 }
579
580 #[inline]
586 #[track_caller]
587 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
588 slice[0] = self.x_axis.x;
589 slice[1] = self.x_axis.y;
590 slice[2] = self.x_axis.z;
591 slice[3] = self.x_axis.w;
592 slice[4] = self.y_axis.x;
593 slice[5] = self.y_axis.y;
594 slice[6] = self.y_axis.z;
595 slice[7] = self.y_axis.w;
596 slice[8] = self.z_axis.x;
597 slice[9] = self.z_axis.y;
598 slice[10] = self.z_axis.z;
599 slice[11] = self.z_axis.w;
600 slice[12] = self.w_axis.x;
601 slice[13] = self.w_axis.y;
602 slice[14] = self.w_axis.z;
603 slice[15] = self.w_axis.w;
604 }
605
606 #[inline]
617 #[must_use]
618 #[track_caller]
619 pub const fn from_rows_slice(slice: &[f32]) -> Self {
620 Self::new(
621 slice[0], slice[4], slice[8], slice[12], slice[1], slice[5], slice[9], slice[13],
622 slice[2], slice[6], slice[10], slice[14], slice[3], slice[7], slice[11], slice[15],
623 )
624 }
625
626 #[inline]
632 #[must_use]
633 #[track_caller]
634 pub fn col(&self, index: usize) -> Vec4 {
635 match index {
636 0 => self.x_axis,
637 1 => self.y_axis,
638 2 => self.z_axis,
639 3 => self.w_axis,
640 _ => panic!("index out of bounds"),
641 }
642 }
643
644 #[inline]
650 #[track_caller]
651 pub fn col_mut(&mut self, index: usize) -> &mut Vec4 {
652 match index {
653 0 => &mut self.x_axis,
654 1 => &mut self.y_axis,
655 2 => &mut self.z_axis,
656 3 => &mut self.w_axis,
657 _ => panic!("index out of bounds"),
658 }
659 }
660
661 #[inline]
669 #[must_use]
670 #[track_caller]
671 pub fn row(&self, index: usize) -> Vec4 {
672 match index {
673 0 => Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
674 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
675 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
676 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
677 _ => panic!("index out of bounds"),
678 }
679 }
680
681 #[inline]
691 #[track_caller]
692 pub fn set_row(&mut self, index: usize, row: Vec4) {
693 match index {
694 0 => {
695 self.x_axis.x = row.x;
696 self.y_axis.x = row.y;
697 self.z_axis.x = row.z;
698 self.w_axis.x = row.w;
699 }
700 1 => {
701 self.x_axis.y = row.x;
702 self.y_axis.y = row.y;
703 self.z_axis.y = row.z;
704 self.w_axis.y = row.w;
705 }
706 2 => {
707 self.x_axis.z = row.x;
708 self.y_axis.z = row.y;
709 self.z_axis.z = row.z;
710 self.w_axis.z = row.w;
711 }
712 3 => {
713 self.x_axis.w = row.x;
714 self.y_axis.w = row.y;
715 self.z_axis.w = row.z;
716 self.w_axis.w = row.w;
717 }
718 _ => panic!("index out of bounds"),
719 }
720 }
721
722 #[inline]
725 #[must_use]
726 pub fn is_finite(&self) -> bool {
727 self.x_axis.is_finite()
728 && self.y_axis.is_finite()
729 && self.z_axis.is_finite()
730 && self.w_axis.is_finite()
731 }
732
733 #[inline]
735 #[must_use]
736 pub fn is_nan(&self) -> bool {
737 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan() || self.w_axis.is_nan()
738 }
739
740 #[inline]
742 #[must_use]
743 pub fn transpose(&self) -> Self {
744 Self {
745 x_axis: Vec4::new(self.x_axis.x, self.y_axis.x, self.z_axis.x, self.w_axis.x),
746 y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y),
747 z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z),
748 w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w),
749 }
750 }
751
752 #[inline]
754 #[must_use]
755 pub fn diagonal(&self) -> Vec4 {
756 Vec4::new(self.x_axis.x, self.y_axis.y, self.z_axis.z, self.w_axis.w)
757 }
758
759 #[must_use]
761 pub fn determinant(&self) -> f32 {
762 let (m00, m01, m02, m03) = self.x_axis.into();
763 let (m10, m11, m12, m13) = self.y_axis.into();
764 let (m20, m21, m22, m23) = self.z_axis.into();
765 let (m30, m31, m32, m33) = self.w_axis.into();
766
767 let a2323 = m22 * m33 - m23 * m32;
768 let a1323 = m21 * m33 - m23 * m31;
769 let a1223 = m21 * m32 - m22 * m31;
770 let a0323 = m20 * m33 - m23 * m30;
771 let a0223 = m20 * m32 - m22 * m30;
772 let a0123 = m20 * m31 - m21 * m30;
773
774 m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223)
775 - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223)
776 + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123)
777 - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123)
778 }
779
780 #[inline(always)]
792 #[must_use]
793 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
794 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
795 unsafe {
796 let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
798 let r = vuzp2q_f32(a, b);
799 vtrn2q_f32(r, r)
800 };
801 let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
802 let r = vuzp1q_f32(a, b);
803 vtrn2q_f32(r, r)
804 };
805 let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
806 let r = vuzp1q_f32(a, a);
807 vuzp1q_f32(r, b)
808 };
809 let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
810 let r = vzip1q_f32(a, b);
811 vzip2q_f32(r, r)
812 };
813 let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
814 let r = vuzp1q_f32(a, b);
815 vtrn1q_f32(r, r)
816 };
817 let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t {
818 let r = vuzp1q_f32(a, b);
819 vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2)
820 };
821 let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) };
822 let fac0 = {
823 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
824 let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0);
825
826 let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0);
827 let swp01 = swizzle0046(swp0a, swp0a);
828 let swp02 = swizzle0046(swp0b, swp0b);
829 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
830
831 let mul00 = vmulq_f32(swp00, swp01);
832 let mul01 = vmulq_f32(swp02, swp03);
833 vsubq_f32(mul00, mul01)
834 };
835 let fac1 = {
836 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
837 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
838
839 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
840 let swp01 = swizzle0046(swp0a, swp0a);
841 let swp02 = swizzle0046(swp0b, swp0b);
842 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
843
844 let mul00 = vmulq_f32(swp00, swp01);
845 let mul01 = vmulq_f32(swp02, swp03);
846 vsubq_f32(mul00, mul01)
847 };
848 let fac2 = {
849 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
850 let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0);
851
852 let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0);
853 let swp01 = swizzle0046(swp0a, swp0a);
854 let swp02 = swizzle0046(swp0b, swp0b);
855 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
856
857 let mul00 = vmulq_f32(swp00, swp01);
858 let mul01 = vmulq_f32(swp02, swp03);
859 vsubq_f32(mul00, mul01)
860 };
861 let fac3 = {
862 let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0);
863 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
864
865 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
866 let swp01 = swizzle0046(swp0a, swp0a);
867 let swp02 = swizzle0046(swp0b, swp0b);
868 let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0);
869
870 let mul00 = vmulq_f32(swp00, swp01);
871 let mul01 = vmulq_f32(swp02, swp03);
872 vsubq_f32(mul00, mul01)
873 };
874 let fac4 = {
875 let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0);
876 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
877
878 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
879 let swp01 = swizzle0046(swp0a, swp0a);
880 let swp02 = swizzle0046(swp0b, swp0b);
881 let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0);
882
883 let mul00 = vmulq_f32(swp00, swp01);
884 let mul01 = vmulq_f32(swp02, swp03);
885 vsubq_f32(mul00, mul01)
886 };
887 let fac5 = {
888 let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0);
889 let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0);
890
891 let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0);
892 let swp01 = swizzle0046(swp0a, swp0a);
893 let swp02 = swizzle0046(swp0b, swp0b);
894 let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0);
895
896 let mul00 = vmulq_f32(swp00, swp01);
897 let mul01 = vmulq_f32(swp02, swp03);
898 vsubq_f32(mul00, mul01)
899 };
900
901 const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0;
902 const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0;
903
904 let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0);
905 let vec0 = swizzle0266(temp0, temp0);
906
907 let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0);
908 let vec1 = swizzle0266(temp1, temp1);
909
910 let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0);
911 let vec2 = swizzle0266(temp2, temp2);
912
913 let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0);
914 let vec3 = swizzle0266(temp3, temp3);
915
916 let mul00 = vmulq_f32(vec1, fac0);
917 let mul01 = vmulq_f32(vec2, fac1);
918 let mul02 = vmulq_f32(vec3, fac2);
919 let sub00 = vsubq_f32(mul00, mul01);
920 let add00 = vaddq_f32(sub00, mul02);
921 let inv0 = vmulq_f32(SIGN_B, add00);
922
923 let mul03 = vmulq_f32(vec0, fac0);
924 let mul04 = vmulq_f32(vec2, fac3);
925 let mul05 = vmulq_f32(vec3, fac4);
926 let sub01 = vsubq_f32(mul03, mul04);
927 let add01 = vaddq_f32(sub01, mul05);
928 let inv1 = vmulq_f32(SIGN_A, add01);
929
930 let mul06 = vmulq_f32(vec0, fac1);
931 let mul07 = vmulq_f32(vec1, fac3);
932 let mul08 = vmulq_f32(vec3, fac5);
933 let sub02 = vsubq_f32(mul06, mul07);
934 let add02 = vaddq_f32(sub02, mul08);
935 let inv2 = vmulq_f32(SIGN_B, add02);
936
937 let mul09 = vmulq_f32(vec0, fac2);
938 let mul10 = vmulq_f32(vec1, fac4);
939 let mul11 = vmulq_f32(vec2, fac5);
940 let sub03 = vsubq_f32(mul09, mul10);
941 let add03 = vaddq_f32(sub03, mul11);
942 let inv3 = vmulq_f32(SIGN_A, add03);
943
944 let row0 = swizzle0044(inv0, inv1);
945 let row1 = swizzle0044(inv2, inv3);
946 let row2 = swizzle0246(row0, row1);
947
948 let dot0 = dot4(self.x_axis.0, row2);
949
950 let rcp0 = dot0.recip();
951 let m = Self {
952 x_axis: Vec4(vmulq_n_f32(inv0, rcp0)),
953 y_axis: Vec4(vmulq_n_f32(inv1, rcp0)),
954 z_axis: Vec4(vmulq_n_f32(inv2, rcp0)),
955 w_axis: Vec4(vmulq_n_f32(inv3, rcp0)),
956 };
957 if CHECKED {
958 if !m.is_finite() {
959 return (Self::ZERO, false);
960 }
961 } else {
962 glam_assert!(m.is_finite());
963 }
964 (m, true)
965 }
966 }
967
968 #[must_use]
980 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
981 pub fn inverse(&self) -> Self {
982 self.inverse_checked::<false>().0
983 }
984
985 #[must_use]
988 pub fn try_inverse(&self) -> Option<Self> {
989 let (m, is_valid) = self.inverse_checked::<true>();
990 if is_valid { Some(m) } else { None }
991 }
992
993 #[must_use]
996 pub fn inverse_or_zero(&self) -> Self {
997 self.inverse_checked::<true>().0
998 }
999
1000 #[inline]
1007 #[must_use]
1008 pub fn project_point3(&self, rhs: Vec3) -> Vec3 {
1009 let mut res = self.x_axis.mul(rhs.x);
1010 res = self.y_axis.mul(rhs.y).add(res);
1011 res = self.z_axis.mul(rhs.z).add(res);
1012 res = self.w_axis.add(res);
1013 res = res.div(res.w);
1014 res.xyz()
1015 }
1016
1017 #[inline]
1030 #[must_use]
1031 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1032 pub fn transform_point3(&self, rhs: Vec3) -> Vec3 {
1033 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1034 let mut res = self.x_axis.mul(rhs.x);
1035 res = self.y_axis.mul(rhs.y).add(res);
1036 res = self.z_axis.mul(rhs.z).add(res);
1037 res = self.w_axis.add(res);
1038 res.xyz()
1039 }
1040
1041 #[inline]
1052 #[must_use]
1053 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1054 pub fn transform_vector3(&self, rhs: Vec3) -> Vec3 {
1055 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1056 let mut res = self.x_axis.mul(rhs.x);
1057 res = self.y_axis.mul(rhs.y).add(res);
1058 res = self.z_axis.mul(rhs.z).add(res);
1059 res.xyz()
1060 }
1061
1062 #[inline]
1069 #[must_use]
1070 pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A {
1071 let mut res = self.x_axis.mul(rhs.xxxx());
1072 res = self.y_axis.mul(rhs.yyyy()).add(res);
1073 res = self.z_axis.mul(rhs.zzzz()).add(res);
1074 res = self.w_axis.add(res);
1075 res = res.div(res.wwww());
1076 Vec3A::from_vec4(res)
1077 }
1078
1079 #[inline]
1091 #[must_use]
1092 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1093 pub fn transform_point3a(&self, rhs: Vec3A) -> Vec3A {
1094 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1095 let mut res = self.x_axis.mul(rhs.xxxx());
1096 res = self.y_axis.mul(rhs.yyyy()).add(res);
1097 res = self.z_axis.mul(rhs.zzzz()).add(res);
1098 res = self.w_axis.add(res);
1099 Vec3A::from_vec4(res)
1100 }
1101
1102 #[inline]
1112 #[must_use]
1113 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1114 pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A {
1115 glam_assert!(self.row(3).abs_diff_eq(Vec4::W, 1e-6));
1116 let mut res = self.x_axis.mul(rhs.xxxx());
1117 res = self.y_axis.mul(rhs.yyyy()).add(res);
1118 res = self.z_axis.mul(rhs.zzzz()).add(res);
1119 Vec3A::from_vec4(res)
1120 }
1121
1122 #[inline]
1124 #[must_use]
1125 pub fn mul_vec4(&self, rhs: Vec4) -> Vec4 {
1126 let mut res = self.x_axis.mul(rhs.xxxx());
1127 res = res.add(self.y_axis.mul(rhs.yyyy()));
1128 res = res.add(self.z_axis.mul(rhs.zzzz()));
1129 res = res.add(self.w_axis.mul(rhs.wwww()));
1130 res
1131 }
1132
1133 #[inline]
1135 #[must_use]
1136 pub fn mul_transpose_vec4(&self, rhs: Vec4) -> Vec4 {
1137 Vec4::new(
1138 self.x_axis.dot(rhs),
1139 self.y_axis.dot(rhs),
1140 self.z_axis.dot(rhs),
1141 self.w_axis.dot(rhs),
1142 )
1143 }
1144
1145 #[inline]
1147 #[must_use]
1148 pub fn mul_mat4(&self, rhs: &Self) -> Self {
1149 self.mul(rhs)
1150 }
1151
1152 #[inline]
1154 #[must_use]
1155 pub fn add_mat4(&self, rhs: &Self) -> Self {
1156 self.add(rhs)
1157 }
1158
1159 #[inline]
1161 #[must_use]
1162 pub fn sub_mat4(&self, rhs: &Self) -> Self {
1163 self.sub(rhs)
1164 }
1165
1166 #[inline]
1168 #[must_use]
1169 pub fn mul_scalar(&self, rhs: f32) -> Self {
1170 Self::from_cols(
1171 self.x_axis.mul(rhs),
1172 self.y_axis.mul(rhs),
1173 self.z_axis.mul(rhs),
1174 self.w_axis.mul(rhs),
1175 )
1176 }
1177
1178 #[inline]
1182 #[must_use]
1183 pub fn mul_diagonal_scale(&self, scale: Vec4) -> Self {
1184 Self::from_cols(
1185 self.x_axis * scale.x,
1186 self.y_axis * scale.y,
1187 self.z_axis * scale.z,
1188 self.w_axis * scale.w,
1189 )
1190 }
1191
1192 #[inline]
1194 #[must_use]
1195 pub fn div_scalar(&self, rhs: f32) -> Self {
1196 let rhs = Vec4::splat(rhs);
1197 Self::from_cols(
1198 self.x_axis.div(rhs),
1199 self.y_axis.div(rhs),
1200 self.z_axis.div(rhs),
1201 self.w_axis.div(rhs),
1202 )
1203 }
1204
1205 #[inline]
1207 #[must_use]
1208 pub fn recip(&self) -> Self {
1209 Self::from_cols(
1210 self.x_axis.recip(),
1211 self.y_axis.recip(),
1212 self.z_axis.recip(),
1213 self.w_axis.recip(),
1214 )
1215 }
1216
1217 #[inline]
1227 #[must_use]
1228 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1229 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1230 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1231 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1232 && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff)
1233 }
1234
1235 #[inline]
1237 #[must_use]
1238 pub fn abs(&self) -> Self {
1239 Self::from_cols(
1240 self.x_axis.abs(),
1241 self.y_axis.abs(),
1242 self.z_axis.abs(),
1243 self.w_axis.abs(),
1244 )
1245 }
1246
1247 #[cfg(feature = "f64")]
1248 #[inline]
1249 #[must_use]
1250 pub fn as_dmat4(&self) -> DMat4 {
1251 DMat4::from_cols(
1252 self.x_axis.as_dvec4(),
1253 self.y_axis.as_dvec4(),
1254 self.z_axis.as_dvec4(),
1255 self.w_axis.as_dvec4(),
1256 )
1257 }
1258}
1259
1260impl Default for Mat4 {
1261 #[inline]
1262 fn default() -> Self {
1263 Self::IDENTITY
1264 }
1265}
1266
1267impl Add for Mat4 {
1268 type Output = Self;
1269 #[inline]
1270 fn add(self, rhs: Self) -> Self {
1271 Self::from_cols(
1272 self.x_axis.add(rhs.x_axis),
1273 self.y_axis.add(rhs.y_axis),
1274 self.z_axis.add(rhs.z_axis),
1275 self.w_axis.add(rhs.w_axis),
1276 )
1277 }
1278}
1279
1280impl Add<&Self> for Mat4 {
1281 type Output = Self;
1282 #[inline]
1283 fn add(self, rhs: &Self) -> Self {
1284 self.add(*rhs)
1285 }
1286}
1287
1288impl Add<&Mat4> for &Mat4 {
1289 type Output = Mat4;
1290 #[inline]
1291 fn add(self, rhs: &Mat4) -> Mat4 {
1292 (*self).add(*rhs)
1293 }
1294}
1295
1296impl Add<Mat4> for &Mat4 {
1297 type Output = Mat4;
1298 #[inline]
1299 fn add(self, rhs: Mat4) -> Mat4 {
1300 (*self).add(rhs)
1301 }
1302}
1303
1304impl AddAssign for Mat4 {
1305 #[inline]
1306 fn add_assign(&mut self, rhs: Self) {
1307 *self = self.add(rhs);
1308 }
1309}
1310
1311impl AddAssign<&Self> for Mat4 {
1312 #[inline]
1313 fn add_assign(&mut self, rhs: &Self) {
1314 self.add_assign(*rhs);
1315 }
1316}
1317
1318impl Sub for Mat4 {
1319 type Output = Self;
1320 #[inline]
1321 fn sub(self, rhs: Self) -> Self {
1322 Self::from_cols(
1323 self.x_axis.sub(rhs.x_axis),
1324 self.y_axis.sub(rhs.y_axis),
1325 self.z_axis.sub(rhs.z_axis),
1326 self.w_axis.sub(rhs.w_axis),
1327 )
1328 }
1329}
1330
1331impl Sub<&Self> for Mat4 {
1332 type Output = Self;
1333 #[inline]
1334 fn sub(self, rhs: &Self) -> Self {
1335 self.sub(*rhs)
1336 }
1337}
1338
1339impl Sub<&Mat4> for &Mat4 {
1340 type Output = Mat4;
1341 #[inline]
1342 fn sub(self, rhs: &Mat4) -> Mat4 {
1343 (*self).sub(*rhs)
1344 }
1345}
1346
1347impl Sub<Mat4> for &Mat4 {
1348 type Output = Mat4;
1349 #[inline]
1350 fn sub(self, rhs: Mat4) -> Mat4 {
1351 (*self).sub(rhs)
1352 }
1353}
1354
1355impl SubAssign for Mat4 {
1356 #[inline]
1357 fn sub_assign(&mut self, rhs: Self) {
1358 *self = self.sub(rhs);
1359 }
1360}
1361
1362impl SubAssign<&Self> for Mat4 {
1363 #[inline]
1364 fn sub_assign(&mut self, rhs: &Self) {
1365 self.sub_assign(*rhs);
1366 }
1367}
1368
1369impl Neg for Mat4 {
1370 type Output = Self;
1371 #[inline]
1372 fn neg(self) -> Self::Output {
1373 Self::from_cols(
1374 self.x_axis.neg(),
1375 self.y_axis.neg(),
1376 self.z_axis.neg(),
1377 self.w_axis.neg(),
1378 )
1379 }
1380}
1381
1382impl Neg for &Mat4 {
1383 type Output = Mat4;
1384 #[inline]
1385 fn neg(self) -> Mat4 {
1386 (*self).neg()
1387 }
1388}
1389
1390impl Mul for Mat4 {
1391 type Output = Self;
1392 #[inline]
1393 fn mul(self, rhs: Self) -> Self {
1394 Self::from_cols(
1395 self.mul(rhs.x_axis),
1396 self.mul(rhs.y_axis),
1397 self.mul(rhs.z_axis),
1398 self.mul(rhs.w_axis),
1399 )
1400 }
1401}
1402
1403impl Mul<&Self> for Mat4 {
1404 type Output = Self;
1405 #[inline]
1406 fn mul(self, rhs: &Self) -> Self {
1407 self.mul(*rhs)
1408 }
1409}
1410
1411impl Mul<&Mat4> for &Mat4 {
1412 type Output = Mat4;
1413 #[inline]
1414 fn mul(self, rhs: &Mat4) -> Mat4 {
1415 (*self).mul(*rhs)
1416 }
1417}
1418
1419impl Mul<Mat4> for &Mat4 {
1420 type Output = Mat4;
1421 #[inline]
1422 fn mul(self, rhs: Mat4) -> Mat4 {
1423 (*self).mul(rhs)
1424 }
1425}
1426
1427impl MulAssign for Mat4 {
1428 #[inline]
1429 fn mul_assign(&mut self, rhs: Self) {
1430 *self = self.mul(rhs);
1431 }
1432}
1433
1434impl MulAssign<&Self> for Mat4 {
1435 #[inline]
1436 fn mul_assign(&mut self, rhs: &Self) {
1437 self.mul_assign(*rhs);
1438 }
1439}
1440
1441impl Mul<Vec4> for Mat4 {
1442 type Output = Vec4;
1443 #[inline]
1444 fn mul(self, rhs: Vec4) -> Self::Output {
1445 self.mul_vec4(rhs)
1446 }
1447}
1448
1449impl Mul<&Vec4> for Mat4 {
1450 type Output = Vec4;
1451 #[inline]
1452 fn mul(self, rhs: &Vec4) -> Vec4 {
1453 self.mul(*rhs)
1454 }
1455}
1456
1457impl Mul<&Vec4> for &Mat4 {
1458 type Output = Vec4;
1459 #[inline]
1460 fn mul(self, rhs: &Vec4) -> Vec4 {
1461 (*self).mul(*rhs)
1462 }
1463}
1464
1465impl Mul<Vec4> for &Mat4 {
1466 type Output = Vec4;
1467 #[inline]
1468 fn mul(self, rhs: Vec4) -> Vec4 {
1469 (*self).mul(rhs)
1470 }
1471}
1472
1473impl Mul<Mat4> for f32 {
1474 type Output = Mat4;
1475 #[inline]
1476 fn mul(self, rhs: Mat4) -> Self::Output {
1477 rhs.mul_scalar(self)
1478 }
1479}
1480
1481impl Mul<&Mat4> for f32 {
1482 type Output = Mat4;
1483 #[inline]
1484 fn mul(self, rhs: &Mat4) -> Mat4 {
1485 self.mul(*rhs)
1486 }
1487}
1488
1489impl Mul<&Mat4> for &f32 {
1490 type Output = Mat4;
1491 #[inline]
1492 fn mul(self, rhs: &Mat4) -> Mat4 {
1493 (*self).mul(*rhs)
1494 }
1495}
1496
1497impl Mul<Mat4> for &f32 {
1498 type Output = Mat4;
1499 #[inline]
1500 fn mul(self, rhs: Mat4) -> Mat4 {
1501 (*self).mul(rhs)
1502 }
1503}
1504
1505impl Mul<f32> for Mat4 {
1506 type Output = Self;
1507 #[inline]
1508 fn mul(self, rhs: f32) -> Self {
1509 self.mul_scalar(rhs)
1510 }
1511}
1512
1513impl Mul<&f32> for Mat4 {
1514 type Output = Self;
1515 #[inline]
1516 fn mul(self, rhs: &f32) -> Self {
1517 self.mul(*rhs)
1518 }
1519}
1520
1521impl Mul<&f32> for &Mat4 {
1522 type Output = Mat4;
1523 #[inline]
1524 fn mul(self, rhs: &f32) -> Mat4 {
1525 (*self).mul(*rhs)
1526 }
1527}
1528
1529impl Mul<f32> for &Mat4 {
1530 type Output = Mat4;
1531 #[inline]
1532 fn mul(self, rhs: f32) -> Mat4 {
1533 (*self).mul(rhs)
1534 }
1535}
1536
1537impl MulAssign<f32> for Mat4 {
1538 #[inline]
1539 fn mul_assign(&mut self, rhs: f32) {
1540 *self = self.mul(rhs);
1541 }
1542}
1543
1544impl MulAssign<&f32> for Mat4 {
1545 #[inline]
1546 fn mul_assign(&mut self, rhs: &f32) {
1547 self.mul_assign(*rhs);
1548 }
1549}
1550
1551impl Div<Mat4> for f32 {
1552 type Output = Mat4;
1553 #[inline]
1554 fn div(self, rhs: Mat4) -> Self::Output {
1555 Mat4::from_cols(
1556 self.div(rhs.x_axis),
1557 self.div(rhs.y_axis),
1558 self.div(rhs.z_axis),
1559 self.div(rhs.w_axis),
1560 )
1561 }
1562}
1563
1564impl Div<&Mat4> for f32 {
1565 type Output = Mat4;
1566 #[inline]
1567 fn div(self, rhs: &Mat4) -> Mat4 {
1568 self.div(*rhs)
1569 }
1570}
1571
1572impl Div<&Mat4> for &f32 {
1573 type Output = Mat4;
1574 #[inline]
1575 fn div(self, rhs: &Mat4) -> Mat4 {
1576 (*self).div(*rhs)
1577 }
1578}
1579
1580impl Div<Mat4> for &f32 {
1581 type Output = Mat4;
1582 #[inline]
1583 fn div(self, rhs: Mat4) -> Mat4 {
1584 (*self).div(rhs)
1585 }
1586}
1587
1588impl Div<f32> for Mat4 {
1589 type Output = Self;
1590 #[inline]
1591 fn div(self, rhs: f32) -> Self {
1592 self.div_scalar(rhs)
1593 }
1594}
1595
1596impl Div<&f32> for Mat4 {
1597 type Output = Self;
1598 #[inline]
1599 fn div(self, rhs: &f32) -> Self {
1600 self.div(*rhs)
1601 }
1602}
1603
1604impl Div<&f32> for &Mat4 {
1605 type Output = Mat4;
1606 #[inline]
1607 fn div(self, rhs: &f32) -> Mat4 {
1608 (*self).div(*rhs)
1609 }
1610}
1611
1612impl Div<f32> for &Mat4 {
1613 type Output = Mat4;
1614 #[inline]
1615 fn div(self, rhs: f32) -> Mat4 {
1616 (*self).div(rhs)
1617 }
1618}
1619
1620impl DivAssign<f32> for Mat4 {
1621 #[inline]
1622 fn div_assign(&mut self, rhs: f32) {
1623 *self = self.div(rhs);
1624 }
1625}
1626
1627impl DivAssign<&f32> for Mat4 {
1628 #[inline]
1629 fn div_assign(&mut self, rhs: &f32) {
1630 self.div_assign(*rhs);
1631 }
1632}
1633
1634impl Sum<Self> for Mat4 {
1635 fn sum<I>(iter: I) -> Self
1636 where
1637 I: Iterator<Item = Self>,
1638 {
1639 iter.fold(Self::ZERO, Self::add)
1640 }
1641}
1642
1643impl<'a> Sum<&'a Self> for Mat4 {
1644 fn sum<I>(iter: I) -> Self
1645 where
1646 I: Iterator<Item = &'a Self>,
1647 {
1648 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1649 }
1650}
1651
1652impl Product for Mat4 {
1653 fn product<I>(iter: I) -> Self
1654 where
1655 I: Iterator<Item = Self>,
1656 {
1657 iter.fold(Self::IDENTITY, Self::mul)
1658 }
1659}
1660
1661impl<'a> Product<&'a Self> for Mat4 {
1662 fn product<I>(iter: I) -> Self
1663 where
1664 I: Iterator<Item = &'a Self>,
1665 {
1666 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1667 }
1668}
1669
1670impl PartialEq for Mat4 {
1671 #[inline]
1672 fn eq(&self, rhs: &Self) -> bool {
1673 self.x_axis.eq(&rhs.x_axis)
1674 && self.y_axis.eq(&rhs.y_axis)
1675 && self.z_axis.eq(&rhs.z_axis)
1676 && self.w_axis.eq(&rhs.w_axis)
1677 }
1678}
1679
1680impl AsRef<[f32; 16]> for Mat4 {
1681 #[inline]
1682 fn as_ref(&self) -> &[f32; 16] {
1683 unsafe { &*(self as *const Self as *const [f32; 16]) }
1684 }
1685}
1686
1687impl AsMut<[f32; 16]> for Mat4 {
1688 #[inline]
1689 fn as_mut(&mut self) -> &mut [f32; 16] {
1690 unsafe { &mut *(self as *mut Self as *mut [f32; 16]) }
1691 }
1692}
1693
1694impl fmt::Debug for Mat4 {
1695 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1696 fmt.debug_struct(stringify!(Mat4))
1697 .field("x_axis", &self.x_axis)
1698 .field("y_axis", &self.y_axis)
1699 .field("z_axis", &self.z_axis)
1700 .field("w_axis", &self.w_axis)
1701 .finish()
1702 }
1703}
1704
1705impl fmt::Display for Mat4 {
1706 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1707 if let Some(p) = f.precision() {
1708 write!(
1709 f,
1710 "[{:.*}, {:.*}, {:.*}, {:.*}]",
1711 p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis
1712 )
1713 } else {
1714 write!(
1715 f,
1716 "[{}, {}, {}, {}]",
1717 self.x_axis, self.y_axis, self.z_axis, self.w_axis
1718 )
1719 }
1720 }
1721}