1#[cfg(feature = "f64")]
4use crate::DMat3;
5
6use crate::{
7 euler::{FromEuler, ToEuler},
8 f32::math,
9 swizzles::*,
10 EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A,
11};
12use core::fmt;
13use core::iter::{Product, Sum};
14use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
15
16#[cfg(target_arch = "x86")]
17use core::arch::x86::*;
18#[cfg(target_arch = "x86_64")]
19use core::arch::x86_64::*;
20
21#[cfg(feature = "zerocopy-08")]
22use zerocopy_derive_08::*;
23
24#[inline(always)]
26#[must_use]
27pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
28 Mat3A::from_cols(x_axis, y_axis, z_axis)
29}
30
31#[derive(Clone, Copy)]
60#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
61#[cfg_attr(
62 feature = "zerocopy-08",
63 derive(FromBytes, Immutable, IntoBytes, KnownLayout)
64)]
65#[repr(C)]
66pub struct Mat3A {
67 pub x_axis: Vec3A,
68 pub y_axis: Vec3A,
69 pub z_axis: Vec3A,
70}
71
72impl Mat3A {
73 pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
75
76 pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
78
79 pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
81
82 #[allow(clippy::too_many_arguments)]
83 #[inline(always)]
84 #[must_use]
85 const fn new(
86 m00: f32,
87 m01: f32,
88 m02: f32,
89 m10: f32,
90 m11: f32,
91 m12: f32,
92 m20: f32,
93 m21: f32,
94 m22: f32,
95 ) -> Self {
96 Self {
97 x_axis: Vec3A::new(m00, m01, m02),
98 y_axis: Vec3A::new(m10, m11, m12),
99 z_axis: Vec3A::new(m20, m21, m22),
100 }
101 }
102
103 #[inline(always)]
107 #[must_use]
108 pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
109 Self {
110 x_axis,
111 y_axis,
112 z_axis,
113 }
114 }
115
116 #[inline(always)]
122 #[must_use]
123 pub const fn from_rows(row0: Vec3A, row1: Vec3A, row2: Vec3A) -> Self {
124 let [m00, m01, m02] = row0.to_array();
125 let [m10, m11, m12] = row1.to_array();
126 let [m20, m21, m22] = row2.to_array();
127 Self::new(m00, m10, m20, m01, m11, m21, m02, m12, m22)
128 }
129
130 #[inline]
134 #[must_use]
135 pub const fn from_cols_array(m: &[f32; 9]) -> Self {
136 Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
137 }
138
139 #[inline]
143 #[must_use]
144 pub const fn to_cols_array(&self) -> [f32; 9] {
145 let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
146 let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
147 let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
148
149 [
150 x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
151 z_axis_z,
152 ]
153 }
154
155 #[inline]
159 #[must_use]
160 pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
161 Self::from_cols(
162 Vec3A::from_array(m[0]),
163 Vec3A::from_array(m[1]),
164 Vec3A::from_array(m[2]),
165 )
166 }
167
168 #[inline]
172 #[must_use]
173 pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
174 [
175 self.x_axis.to_array(),
176 self.y_axis.to_array(),
177 self.z_axis.to_array(),
178 ]
179 }
180
181 #[inline]
187 #[must_use]
188 pub const fn from_rows_array(m: &[f32; 9]) -> Self {
189 Self::new(m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8])
190 }
191
192 #[inline]
198 #[must_use]
199 pub const fn to_rows_array(&self) -> [f32; 9] {
200 let m = self.to_cols_array();
201 [m[0], m[3], m[6], m[1], m[4], m[7], m[2], m[5], m[8]]
202 }
203
204 #[doc(alias = "scale")]
206 #[inline]
207 #[must_use]
208 pub const fn from_diagonal(diagonal: Vec3) -> Self {
209 Self::new(
210 diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
211 )
212 }
213
214 #[inline]
216 #[must_use]
217 pub fn from_mat4(m: Mat4) -> Self {
218 Self::from_cols(
219 Vec3A::from_vec4(m.x_axis),
220 Vec3A::from_vec4(m.y_axis),
221 Vec3A::from_vec4(m.z_axis),
222 )
223 }
224
225 #[inline]
232 #[must_use]
233 #[track_caller]
234 pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
235 match (i, j) {
236 (0, 0) => Self::from_cols(
237 Vec3A::from_vec4(m.y_axis.yzww()),
238 Vec3A::from_vec4(m.z_axis.yzww()),
239 Vec3A::from_vec4(m.w_axis.yzww()),
240 ),
241 (0, 1) => Self::from_cols(
242 Vec3A::from_vec4(m.y_axis.xzww()),
243 Vec3A::from_vec4(m.z_axis.xzww()),
244 Vec3A::from_vec4(m.w_axis.xzww()),
245 ),
246 (0, 2) => Self::from_cols(
247 Vec3A::from_vec4(m.y_axis.xyww()),
248 Vec3A::from_vec4(m.z_axis.xyww()),
249 Vec3A::from_vec4(m.w_axis.xyww()),
250 ),
251 (0, 3) => Self::from_cols(
252 Vec3A::from_vec4(m.y_axis.xyzw()),
253 Vec3A::from_vec4(m.z_axis.xyzw()),
254 Vec3A::from_vec4(m.w_axis.xyzw()),
255 ),
256 (1, 0) => Self::from_cols(
257 Vec3A::from_vec4(m.x_axis.yzww()),
258 Vec3A::from_vec4(m.z_axis.yzww()),
259 Vec3A::from_vec4(m.w_axis.yzww()),
260 ),
261 (1, 1) => Self::from_cols(
262 Vec3A::from_vec4(m.x_axis.xzww()),
263 Vec3A::from_vec4(m.z_axis.xzww()),
264 Vec3A::from_vec4(m.w_axis.xzww()),
265 ),
266 (1, 2) => Self::from_cols(
267 Vec3A::from_vec4(m.x_axis.xyww()),
268 Vec3A::from_vec4(m.z_axis.xyww()),
269 Vec3A::from_vec4(m.w_axis.xyww()),
270 ),
271 (1, 3) => Self::from_cols(
272 Vec3A::from_vec4(m.x_axis.xyzw()),
273 Vec3A::from_vec4(m.z_axis.xyzw()),
274 Vec3A::from_vec4(m.w_axis.xyzw()),
275 ),
276 (2, 0) => Self::from_cols(
277 Vec3A::from_vec4(m.x_axis.yzww()),
278 Vec3A::from_vec4(m.y_axis.yzww()),
279 Vec3A::from_vec4(m.w_axis.yzww()),
280 ),
281 (2, 1) => Self::from_cols(
282 Vec3A::from_vec4(m.x_axis.xzww()),
283 Vec3A::from_vec4(m.y_axis.xzww()),
284 Vec3A::from_vec4(m.w_axis.xzww()),
285 ),
286 (2, 2) => Self::from_cols(
287 Vec3A::from_vec4(m.x_axis.xyww()),
288 Vec3A::from_vec4(m.y_axis.xyww()),
289 Vec3A::from_vec4(m.w_axis.xyww()),
290 ),
291 (2, 3) => Self::from_cols(
292 Vec3A::from_vec4(m.x_axis.xyzw()),
293 Vec3A::from_vec4(m.y_axis.xyzw()),
294 Vec3A::from_vec4(m.w_axis.xyzw()),
295 ),
296 (3, 0) => Self::from_cols(
297 Vec3A::from_vec4(m.x_axis.yzww()),
298 Vec3A::from_vec4(m.y_axis.yzww()),
299 Vec3A::from_vec4(m.z_axis.yzww()),
300 ),
301 (3, 1) => Self::from_cols(
302 Vec3A::from_vec4(m.x_axis.xzww()),
303 Vec3A::from_vec4(m.y_axis.xzww()),
304 Vec3A::from_vec4(m.z_axis.xzww()),
305 ),
306 (3, 2) => Self::from_cols(
307 Vec3A::from_vec4(m.x_axis.xyww()),
308 Vec3A::from_vec4(m.y_axis.xyww()),
309 Vec3A::from_vec4(m.z_axis.xyww()),
310 ),
311 (3, 3) => Self::from_cols(
312 Vec3A::from_vec4(m.x_axis.xyzw()),
313 Vec3A::from_vec4(m.y_axis.xyzw()),
314 Vec3A::from_vec4(m.z_axis.xyzw()),
315 ),
316 _ => panic!("index out of bounds"),
317 }
318 }
319
320 #[inline]
326 #[must_use]
327 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
328 pub fn from_quat(rotation: Quat) -> Self {
329 glam_assert!(rotation.is_normalized());
330
331 let x2 = rotation.x + rotation.x;
332 let y2 = rotation.y + rotation.y;
333 let z2 = rotation.z + rotation.z;
334 let xx = rotation.x * x2;
335 let xy = rotation.x * y2;
336 let xz = rotation.x * z2;
337 let yy = rotation.y * y2;
338 let yz = rotation.y * z2;
339 let zz = rotation.z * z2;
340 let wx = rotation.w * x2;
341 let wy = rotation.w * y2;
342 let wz = rotation.w * z2;
343
344 Self::from_cols(
345 Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
346 Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
347 Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
348 )
349 }
350
351 #[inline]
358 #[must_use]
359 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
360 pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
361 glam_assert!(axis.is_normalized());
362
363 let (sin, cos) = math::sin_cos(angle);
364 let (xsin, ysin, zsin) = axis.mul(sin).into();
365 let (x, y, z) = axis.into();
366 let (x2, y2, z2) = axis.mul(axis).into();
367 let omc = 1.0 - cos;
368 let xyomc = x * y * omc;
369 let xzomc = x * z * omc;
370 let yzomc = y * z * omc;
371 Self::from_cols(
372 Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
373 Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
374 Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
375 )
376 }
377
378 #[inline]
381 #[must_use]
382 pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
383 Self::from_euler_angles(order, a, b, c)
384 }
385
386 #[inline]
395 #[must_use]
396 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
397 pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
398 glam_assert!(
399 self.x_axis.is_normalized()
400 && self.y_axis.is_normalized()
401 && self.z_axis.is_normalized()
402 );
403 self.to_euler_angles(order)
404 }
405
406 #[inline]
408 #[must_use]
409 pub fn from_rotation_x(angle: f32) -> Self {
410 let (sina, cosa) = math::sin_cos(angle);
411 Self::from_cols(
412 Vec3A::X,
413 Vec3A::new(0.0, cosa, sina),
414 Vec3A::new(0.0, -sina, cosa),
415 )
416 }
417
418 #[inline]
420 #[must_use]
421 pub fn from_rotation_y(angle: f32) -> Self {
422 let (sina, cosa) = math::sin_cos(angle);
423 Self::from_cols(
424 Vec3A::new(cosa, 0.0, -sina),
425 Vec3A::Y,
426 Vec3A::new(sina, 0.0, cosa),
427 )
428 }
429
430 #[inline]
432 #[must_use]
433 pub fn from_rotation_z(angle: f32) -> Self {
434 let (sina, cosa) = math::sin_cos(angle);
435 Self::from_cols(
436 Vec3A::new(cosa, sina, 0.0),
437 Vec3A::new(-sina, cosa, 0.0),
438 Vec3A::Z,
439 )
440 }
441
442 #[inline]
447 #[must_use]
448 pub fn from_translation(translation: Vec2) -> Self {
449 Self::from_cols(
450 Vec3A::X,
451 Vec3A::Y,
452 Vec3A::new(translation.x, translation.y, 1.0),
453 )
454 }
455
456 #[inline]
462 #[must_use]
463 pub fn from_angle(angle: f32) -> Self {
464 let (sin, cos) = math::sin_cos(angle);
465 Self::from_cols(
466 Vec3A::new(cos, sin, 0.0),
467 Vec3A::new(-sin, cos, 0.0),
468 Vec3A::Z,
469 )
470 }
471
472 #[inline]
478 #[must_use]
479 pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
480 let (sin, cos) = math::sin_cos(angle);
481 Self::from_cols(
482 Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
483 Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
484 Vec3A::new(translation.x, translation.y, 1.0),
485 )
486 }
487
488 #[inline]
497 #[must_use]
498 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
499 pub fn from_scale(scale: Vec2) -> Self {
500 glam_assert!(scale.cmpne(Vec2::ZERO).any());
502
503 Self::from_cols(
504 Vec3A::new(scale.x, 0.0, 0.0),
505 Vec3A::new(0.0, scale.y, 0.0),
506 Vec3A::Z,
507 )
508 }
509
510 #[inline]
515 pub fn from_mat2(m: Mat2) -> Self {
516 Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
517 }
518
519 #[inline]
527 #[must_use]
528 #[track_caller]
529 pub const fn from_cols_slice(slice: &[f32]) -> Self {
530 Self::new(
531 slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
532 slice[8],
533 )
534 }
535
536 #[inline]
542 #[track_caller]
543 pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
544 slice[0] = self.x_axis.x;
545 slice[1] = self.x_axis.y;
546 slice[2] = self.x_axis.z;
547 slice[3] = self.y_axis.x;
548 slice[4] = self.y_axis.y;
549 slice[5] = self.y_axis.z;
550 slice[6] = self.z_axis.x;
551 slice[7] = self.z_axis.y;
552 slice[8] = self.z_axis.z;
553 }
554
555 #[inline]
566 #[must_use]
567 #[track_caller]
568 pub const fn from_rows_slice(slice: &[f32]) -> Self {
569 Self::new(
570 slice[0], slice[3], slice[6], slice[1], slice[4], slice[7], slice[2], slice[5],
571 slice[8],
572 )
573 }
574
575 #[inline]
581 #[must_use]
582 #[track_caller]
583 pub fn col(&self, index: usize) -> Vec3A {
584 match index {
585 0 => self.x_axis,
586 1 => self.y_axis,
587 2 => self.z_axis,
588 _ => panic!("index out of bounds"),
589 }
590 }
591
592 #[inline]
598 #[track_caller]
599 pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
600 match index {
601 0 => &mut self.x_axis,
602 1 => &mut self.y_axis,
603 2 => &mut self.z_axis,
604 _ => panic!("index out of bounds"),
605 }
606 }
607
608 #[inline]
616 #[must_use]
617 #[track_caller]
618 pub fn row(&self, index: usize) -> Vec3A {
619 match index {
620 0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
621 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
622 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
623 _ => panic!("index out of bounds"),
624 }
625 }
626
627 #[inline]
637 #[track_caller]
638 pub fn set_row(&mut self, index: usize, row: Vec3A) {
639 match index {
640 0 => {
641 self.x_axis.x = row.x;
642 self.y_axis.x = row.y;
643 self.z_axis.x = row.z;
644 }
645 1 => {
646 self.x_axis.y = row.x;
647 self.y_axis.y = row.y;
648 self.z_axis.y = row.z;
649 }
650 2 => {
651 self.x_axis.z = row.x;
652 self.y_axis.z = row.y;
653 self.z_axis.z = row.z;
654 }
655 _ => panic!("index out of bounds"),
656 }
657 }
658
659 #[inline]
662 #[must_use]
663 pub fn is_finite(&self) -> bool {
664 self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
665 }
666
667 #[inline]
669 #[must_use]
670 pub fn is_nan(&self) -> bool {
671 self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
672 }
673
674 #[inline]
676 #[must_use]
677 pub fn transpose(&self) -> Self {
678 unsafe {
679 let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
680 let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
681
682 Self {
683 x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)),
684 y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)),
685 z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)),
686 }
687 }
688 }
689
690 #[inline]
692 #[must_use]
693 pub fn diagonal(&self) -> Vec3A {
694 Vec3A::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
695 }
696
697 #[inline]
699 #[must_use]
700 pub fn determinant(&self) -> f32 {
701 self.x_axis.dot(self.y_axis.cross(self.z_axis))
702 }
703
704 #[inline(always)]
716 #[must_use]
717 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
718 fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
719 let tmp0 = self.y_axis.cross(self.z_axis);
720 let tmp1 = self.z_axis.cross(self.x_axis);
721 let tmp2 = self.x_axis.cross(self.y_axis);
722 let inv_det = Vec3A::splat(1.0 / self.x_axis.dot(tmp0));
723 let m =
724 Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose();
725 if CHECKED {
726 if !m.is_finite() {
727 return (Self::ZERO, false);
728 }
729 } else {
730 glam_assert!(m.is_finite());
731 }
732 (m, true)
733 }
734
735 #[inline]
747 #[must_use]
748 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
749 pub fn inverse(&self) -> Self {
750 self.inverse_checked::<false>().0
751 }
752
753 #[inline]
756 #[must_use]
757 pub fn try_inverse(&self) -> Option<Self> {
758 let (m, is_valid) = self.inverse_checked::<true>();
759 if is_valid {
760 Some(m)
761 } else {
762 None
763 }
764 }
765
766 #[inline]
769 #[must_use]
770 pub fn inverse_or_zero(&self) -> Self {
771 self.inverse_checked::<true>().0
772 }
773
774 #[inline]
784 #[must_use]
785 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
786 pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
787 glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
788 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
789 }
790
791 #[inline]
801 #[must_use]
802 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
803 pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
804 glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
805 Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
806 }
807
808 #[deprecated(
817 since = "0.33.1",
818 note = "use the `glam::camera::lh::view::look_to_mat3` function instead"
819 )]
820 #[inline]
821 #[must_use]
822 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
823 pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
824 #[allow(deprecated)]
825 Self::look_to_rh(-dir, up)
826 }
827
828 #[deprecated(
837 since = "0.33.1",
838 note = "use the `glam::camera::rh::view::look_to_mat3` function instead"
839 )]
840 #[inline]
841 #[must_use]
842 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
843 pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
844 glam_assert!(dir.is_normalized());
845 glam_assert!(up.is_normalized());
846 let f = dir;
847 let s = f.cross(up).normalize();
848 let u = s.cross(f);
849
850 Self::from_cols(
851 Vec3A::new(s.x, u.x, -f.x),
852 Vec3A::new(s.y, u.y, -f.y),
853 Vec3A::new(s.z, u.z, -f.z),
854 )
855 }
856
857 #[deprecated(
867 since = "0.33.1",
868 note = "use the `glam::camera::lh::view::look_at_mat3` function instead"
869 )]
870 #[inline]
871 #[must_use]
872 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
873 pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
874 #[allow(deprecated)]
875 Self::look_to_lh(center.sub(eye).normalize(), up)
876 }
877
878 #[deprecated(
888 since = "0.33.1",
889 note = "use the `glam::camera::rh::view::look_at_mat3` function instead"
890 )]
891 #[inline]
892 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
893 pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
894 #[allow(deprecated)]
895 Self::look_to_rh(center.sub(eye).normalize(), up)
896 }
897
898 #[inline]
900 #[must_use]
901 pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
902 self.mul_vec3a(rhs.into()).into()
903 }
904
905 #[inline]
907 #[must_use]
908 pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
909 let mut res = self.x_axis.mul(rhs.xxx());
910 res = res.add(self.y_axis.mul(rhs.yyy()));
911 res = res.add(self.z_axis.mul(rhs.zzz()));
912 res
913 }
914
915 #[inline]
917 #[must_use]
918 pub fn mul_transpose_vec3(&self, rhs: Vec3) -> Vec3 {
919 self.mul_transpose_vec3a(rhs.into()).into()
920 }
921
922 #[inline]
924 #[must_use]
925 pub fn mul_transpose_vec3a(&self, rhs: Vec3A) -> Vec3A {
926 Vec3A::new(
927 self.x_axis.dot(rhs),
928 self.y_axis.dot(rhs),
929 self.z_axis.dot(rhs),
930 )
931 }
932
933 #[inline]
935 #[must_use]
936 pub fn mul_mat3(&self, rhs: &Self) -> Self {
937 self.mul(rhs)
938 }
939
940 #[inline]
942 #[must_use]
943 pub fn add_mat3(&self, rhs: &Self) -> Self {
944 self.add(rhs)
945 }
946
947 #[inline]
949 #[must_use]
950 pub fn sub_mat3(&self, rhs: &Self) -> Self {
951 self.sub(rhs)
952 }
953
954 #[inline]
956 #[must_use]
957 pub fn mul_scalar(&self, rhs: f32) -> Self {
958 Self::from_cols(
959 self.x_axis.mul(rhs),
960 self.y_axis.mul(rhs),
961 self.z_axis.mul(rhs),
962 )
963 }
964
965 #[inline]
969 #[must_use]
970 pub fn mul_diagonal_scale(&self, scale: Vec3) -> Self {
971 Self::from_cols(
972 self.x_axis * scale.x,
973 self.y_axis * scale.y,
974 self.z_axis * scale.z,
975 )
976 }
977
978 #[inline]
980 #[must_use]
981 pub fn div_scalar(&self, rhs: f32) -> Self {
982 let rhs = Vec3A::splat(rhs);
983 Self::from_cols(
984 self.x_axis.div(rhs),
985 self.y_axis.div(rhs),
986 self.z_axis.div(rhs),
987 )
988 }
989
990 #[inline]
992 #[must_use]
993 pub fn recip(&self) -> Self {
994 Self::from_cols(
995 self.x_axis.recip(),
996 self.y_axis.recip(),
997 self.z_axis.recip(),
998 )
999 }
1000
1001 #[inline]
1011 #[must_use]
1012 pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
1013 self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
1014 && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
1015 && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
1016 }
1017
1018 #[inline]
1020 #[must_use]
1021 pub fn abs(&self) -> Self {
1022 Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
1023 }
1024
1025 #[cfg(feature = "f64")]
1026 #[inline]
1027 #[must_use]
1028 pub fn as_dmat3(&self) -> DMat3 {
1029 DMat3::from_cols(
1030 self.x_axis.as_dvec3(),
1031 self.y_axis.as_dvec3(),
1032 self.z_axis.as_dvec3(),
1033 )
1034 }
1035}
1036
1037impl Default for Mat3A {
1038 #[inline]
1039 fn default() -> Self {
1040 Self::IDENTITY
1041 }
1042}
1043
1044impl Add for Mat3A {
1045 type Output = Self;
1046 #[inline]
1047 fn add(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 )
1053 }
1054}
1055
1056impl Add<&Self> for Mat3A {
1057 type Output = Self;
1058 #[inline]
1059 fn add(self, rhs: &Self) -> Self {
1060 self.add(*rhs)
1061 }
1062}
1063
1064impl Add<&Mat3A> for &Mat3A {
1065 type Output = Mat3A;
1066 #[inline]
1067 fn add(self, rhs: &Mat3A) -> Mat3A {
1068 (*self).add(*rhs)
1069 }
1070}
1071
1072impl Add<Mat3A> for &Mat3A {
1073 type Output = Mat3A;
1074 #[inline]
1075 fn add(self, rhs: Mat3A) -> Mat3A {
1076 (*self).add(rhs)
1077 }
1078}
1079
1080impl AddAssign for Mat3A {
1081 #[inline]
1082 fn add_assign(&mut self, rhs: Self) {
1083 *self = self.add(rhs);
1084 }
1085}
1086
1087impl AddAssign<&Self> for Mat3A {
1088 #[inline]
1089 fn add_assign(&mut self, rhs: &Self) {
1090 self.add_assign(*rhs);
1091 }
1092}
1093
1094impl Sub for Mat3A {
1095 type Output = Self;
1096 #[inline]
1097 fn sub(self, rhs: Self) -> Self {
1098 Self::from_cols(
1099 self.x_axis.sub(rhs.x_axis),
1100 self.y_axis.sub(rhs.y_axis),
1101 self.z_axis.sub(rhs.z_axis),
1102 )
1103 }
1104}
1105
1106impl Sub<&Self> for Mat3A {
1107 type Output = Self;
1108 #[inline]
1109 fn sub(self, rhs: &Self) -> Self {
1110 self.sub(*rhs)
1111 }
1112}
1113
1114impl Sub<&Mat3A> for &Mat3A {
1115 type Output = Mat3A;
1116 #[inline]
1117 fn sub(self, rhs: &Mat3A) -> Mat3A {
1118 (*self).sub(*rhs)
1119 }
1120}
1121
1122impl Sub<Mat3A> for &Mat3A {
1123 type Output = Mat3A;
1124 #[inline]
1125 fn sub(self, rhs: Mat3A) -> Mat3A {
1126 (*self).sub(rhs)
1127 }
1128}
1129
1130impl SubAssign for Mat3A {
1131 #[inline]
1132 fn sub_assign(&mut self, rhs: Self) {
1133 *self = self.sub(rhs);
1134 }
1135}
1136
1137impl SubAssign<&Self> for Mat3A {
1138 #[inline]
1139 fn sub_assign(&mut self, rhs: &Self) {
1140 self.sub_assign(*rhs);
1141 }
1142}
1143
1144impl Neg for Mat3A {
1145 type Output = Self;
1146 #[inline]
1147 fn neg(self) -> Self::Output {
1148 Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
1149 }
1150}
1151
1152impl Neg for &Mat3A {
1153 type Output = Mat3A;
1154 #[inline]
1155 fn neg(self) -> Mat3A {
1156 (*self).neg()
1157 }
1158}
1159
1160impl Mul for Mat3A {
1161 type Output = Self;
1162 #[inline]
1163 fn mul(self, rhs: Self) -> Self {
1164 Self::from_cols(
1165 self.mul(rhs.x_axis),
1166 self.mul(rhs.y_axis),
1167 self.mul(rhs.z_axis),
1168 )
1169 }
1170}
1171
1172impl Mul<&Self> for Mat3A {
1173 type Output = Self;
1174 #[inline]
1175 fn mul(self, rhs: &Self) -> Self {
1176 self.mul(*rhs)
1177 }
1178}
1179
1180impl Mul<&Mat3A> for &Mat3A {
1181 type Output = Mat3A;
1182 #[inline]
1183 fn mul(self, rhs: &Mat3A) -> Mat3A {
1184 (*self).mul(*rhs)
1185 }
1186}
1187
1188impl Mul<Mat3A> for &Mat3A {
1189 type Output = Mat3A;
1190 #[inline]
1191 fn mul(self, rhs: Mat3A) -> Mat3A {
1192 (*self).mul(rhs)
1193 }
1194}
1195
1196impl MulAssign for Mat3A {
1197 #[inline]
1198 fn mul_assign(&mut self, rhs: Self) {
1199 *self = self.mul(rhs);
1200 }
1201}
1202
1203impl MulAssign<&Self> for Mat3A {
1204 #[inline]
1205 fn mul_assign(&mut self, rhs: &Self) {
1206 self.mul_assign(*rhs);
1207 }
1208}
1209
1210impl Mul<Vec3A> for Mat3A {
1211 type Output = Vec3A;
1212 #[inline]
1213 fn mul(self, rhs: Vec3A) -> Self::Output {
1214 self.mul_vec3a(rhs)
1215 }
1216}
1217
1218impl Mul<&Vec3A> for Mat3A {
1219 type Output = Vec3A;
1220 #[inline]
1221 fn mul(self, rhs: &Vec3A) -> Vec3A {
1222 self.mul(*rhs)
1223 }
1224}
1225
1226impl Mul<&Vec3A> for &Mat3A {
1227 type Output = Vec3A;
1228 #[inline]
1229 fn mul(self, rhs: &Vec3A) -> Vec3A {
1230 (*self).mul(*rhs)
1231 }
1232}
1233
1234impl Mul<Vec3A> for &Mat3A {
1235 type Output = Vec3A;
1236 #[inline]
1237 fn mul(self, rhs: Vec3A) -> Vec3A {
1238 (*self).mul(rhs)
1239 }
1240}
1241
1242impl Mul<Mat3A> for f32 {
1243 type Output = Mat3A;
1244 #[inline]
1245 fn mul(self, rhs: Mat3A) -> Self::Output {
1246 rhs.mul_scalar(self)
1247 }
1248}
1249
1250impl Mul<&Mat3A> for f32 {
1251 type Output = Mat3A;
1252 #[inline]
1253 fn mul(self, rhs: &Mat3A) -> Mat3A {
1254 self.mul(*rhs)
1255 }
1256}
1257
1258impl Mul<&Mat3A> for &f32 {
1259 type Output = Mat3A;
1260 #[inline]
1261 fn mul(self, rhs: &Mat3A) -> Mat3A {
1262 (*self).mul(*rhs)
1263 }
1264}
1265
1266impl Mul<Mat3A> for &f32 {
1267 type Output = Mat3A;
1268 #[inline]
1269 fn mul(self, rhs: Mat3A) -> Mat3A {
1270 (*self).mul(rhs)
1271 }
1272}
1273
1274impl Mul<f32> for Mat3A {
1275 type Output = Self;
1276 #[inline]
1277 fn mul(self, rhs: f32) -> Self {
1278 self.mul_scalar(rhs)
1279 }
1280}
1281
1282impl Mul<&f32> for Mat3A {
1283 type Output = Self;
1284 #[inline]
1285 fn mul(self, rhs: &f32) -> Self {
1286 self.mul(*rhs)
1287 }
1288}
1289
1290impl Mul<&f32> for &Mat3A {
1291 type Output = Mat3A;
1292 #[inline]
1293 fn mul(self, rhs: &f32) -> Mat3A {
1294 (*self).mul(*rhs)
1295 }
1296}
1297
1298impl Mul<f32> for &Mat3A {
1299 type Output = Mat3A;
1300 #[inline]
1301 fn mul(self, rhs: f32) -> Mat3A {
1302 (*self).mul(rhs)
1303 }
1304}
1305
1306impl MulAssign<f32> for Mat3A {
1307 #[inline]
1308 fn mul_assign(&mut self, rhs: f32) {
1309 *self = self.mul(rhs);
1310 }
1311}
1312
1313impl MulAssign<&f32> for Mat3A {
1314 #[inline]
1315 fn mul_assign(&mut self, rhs: &f32) {
1316 self.mul_assign(*rhs);
1317 }
1318}
1319
1320impl Div<Mat3A> for f32 {
1321 type Output = Mat3A;
1322 #[inline]
1323 fn div(self, rhs: Mat3A) -> Self::Output {
1324 Mat3A::from_cols(
1325 self.div(rhs.x_axis),
1326 self.div(rhs.y_axis),
1327 self.div(rhs.z_axis),
1328 )
1329 }
1330}
1331
1332impl Div<&Mat3A> for f32 {
1333 type Output = Mat3A;
1334 #[inline]
1335 fn div(self, rhs: &Mat3A) -> Mat3A {
1336 self.div(*rhs)
1337 }
1338}
1339
1340impl Div<&Mat3A> for &f32 {
1341 type Output = Mat3A;
1342 #[inline]
1343 fn div(self, rhs: &Mat3A) -> Mat3A {
1344 (*self).div(*rhs)
1345 }
1346}
1347
1348impl Div<Mat3A> for &f32 {
1349 type Output = Mat3A;
1350 #[inline]
1351 fn div(self, rhs: Mat3A) -> Mat3A {
1352 (*self).div(rhs)
1353 }
1354}
1355
1356impl Div<f32> for Mat3A {
1357 type Output = Self;
1358 #[inline]
1359 fn div(self, rhs: f32) -> Self {
1360 self.div_scalar(rhs)
1361 }
1362}
1363
1364impl Div<&f32> for Mat3A {
1365 type Output = Self;
1366 #[inline]
1367 fn div(self, rhs: &f32) -> Self {
1368 self.div(*rhs)
1369 }
1370}
1371
1372impl Div<&f32> for &Mat3A {
1373 type Output = Mat3A;
1374 #[inline]
1375 fn div(self, rhs: &f32) -> Mat3A {
1376 (*self).div(*rhs)
1377 }
1378}
1379
1380impl Div<f32> for &Mat3A {
1381 type Output = Mat3A;
1382 #[inline]
1383 fn div(self, rhs: f32) -> Mat3A {
1384 (*self).div(rhs)
1385 }
1386}
1387
1388impl DivAssign<f32> for Mat3A {
1389 #[inline]
1390 fn div_assign(&mut self, rhs: f32) {
1391 *self = self.div(rhs);
1392 }
1393}
1394
1395impl DivAssign<&f32> for Mat3A {
1396 #[inline]
1397 fn div_assign(&mut self, rhs: &f32) {
1398 self.div_assign(*rhs);
1399 }
1400}
1401
1402impl Mul<Vec3> for Mat3A {
1403 type Output = Vec3;
1404 #[inline]
1405 fn mul(self, rhs: Vec3) -> Vec3 {
1406 self.mul_vec3a(rhs.into()).into()
1407 }
1408}
1409
1410impl Mul<&Vec3> for Mat3A {
1411 type Output = Vec3;
1412 #[inline]
1413 fn mul(self, rhs: &Vec3) -> Vec3 {
1414 self.mul(*rhs)
1415 }
1416}
1417
1418impl Mul<&Vec3> for &Mat3A {
1419 type Output = Vec3;
1420 #[inline]
1421 fn mul(self, rhs: &Vec3) -> Vec3 {
1422 (*self).mul(*rhs)
1423 }
1424}
1425
1426impl Mul<Vec3> for &Mat3A {
1427 type Output = Vec3;
1428 #[inline]
1429 fn mul(self, rhs: Vec3) -> Vec3 {
1430 (*self).mul(rhs)
1431 }
1432}
1433
1434impl From<Mat3> for Mat3A {
1435 #[inline]
1436 fn from(m: Mat3) -> Self {
1437 Self {
1438 x_axis: m.x_axis.into(),
1439 y_axis: m.y_axis.into(),
1440 z_axis: m.z_axis.into(),
1441 }
1442 }
1443}
1444
1445impl Sum<Self> for Mat3A {
1446 fn sum<I>(iter: I) -> Self
1447 where
1448 I: Iterator<Item = Self>,
1449 {
1450 iter.fold(Self::ZERO, Self::add)
1451 }
1452}
1453
1454impl<'a> Sum<&'a Self> for Mat3A {
1455 fn sum<I>(iter: I) -> Self
1456 where
1457 I: Iterator<Item = &'a Self>,
1458 {
1459 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1460 }
1461}
1462
1463impl Product for Mat3A {
1464 fn product<I>(iter: I) -> Self
1465 where
1466 I: Iterator<Item = Self>,
1467 {
1468 iter.fold(Self::IDENTITY, Self::mul)
1469 }
1470}
1471
1472impl<'a> Product<&'a Self> for Mat3A {
1473 fn product<I>(iter: I) -> Self
1474 where
1475 I: Iterator<Item = &'a Self>,
1476 {
1477 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1478 }
1479}
1480
1481impl PartialEq for Mat3A {
1482 #[inline]
1483 fn eq(&self, rhs: &Self) -> bool {
1484 self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
1485 }
1486}
1487
1488impl fmt::Debug for Mat3A {
1489 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1490 fmt.debug_struct(stringify!(Mat3A))
1491 .field("x_axis", &self.x_axis)
1492 .field("y_axis", &self.y_axis)
1493 .field("z_axis", &self.z_axis)
1494 .finish()
1495 }
1496}
1497
1498impl fmt::Display for Mat3A {
1499 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1500 if let Some(p) = f.precision() {
1501 write!(
1502 f,
1503 "[{:.*}, {:.*}, {:.*}]",
1504 p, self.x_axis, p, self.y_axis, p, self.z_axis
1505 )
1506 } else {
1507 write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
1508 }
1509 }
1510}