1 // Generated from mat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A};
4 #[cfg(not(target_arch = "spirv"))]
5 use core::fmt;
6 use core::iter::{Product, Sum};
7 use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
8 
9 use core::arch::wasm32::*;
10 
11 /// Creates a 3x3 matrix from three column vectors.
12 #[inline(always)]
13 #[must_use]
mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A14 pub const fn mat3a(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Mat3A {
15     Mat3A::from_cols(x_axis, y_axis, z_axis)
16 }
17 
18 /// A 3x3 column major matrix.
19 ///
20 /// This 3x3 matrix type features convenience methods for creating and using linear and
21 /// affine transformations. If you are primarily dealing with 2D affine transformations the
22 /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
23 /// using a 3x3 matrix.
24 ///
25 /// Linear transformations including 3D rotation and scale can be created using methods
26 /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
27 /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
28 /// [`Self::from_rotation_z()`].
29 ///
30 /// The resulting matrices can be use to transform 3D vectors using regular vector
31 /// multiplication.
32 ///
33 /// Affine transformations including 2D translation, rotation and scale can be created
34 /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
35 /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
36 ///
37 /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
38 /// are provided for performing affine transforms on 2D vectors and points. These multiply
39 /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
40 /// vectors respectively. These methods assume that `Self` contains a valid affine
41 /// transform.
42 #[derive(Clone, Copy)]
43 #[repr(C)]
44 pub struct Mat3A {
45     pub x_axis: Vec3A,
46     pub y_axis: Vec3A,
47     pub z_axis: Vec3A,
48 }
49 
50 impl Mat3A {
51     /// A 3x3 matrix with all elements set to `0.0`.
52     pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
53 
54     /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
55     pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
56 
57     /// All NAN:s.
58     pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
59 
60     #[allow(clippy::too_many_arguments)]
61     #[inline(always)]
62     #[must_use]
new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self63     const fn new(
64         m00: f32,
65         m01: f32,
66         m02: f32,
67         m10: f32,
68         m11: f32,
69         m12: f32,
70         m20: f32,
71         m21: f32,
72         m22: f32,
73     ) -> Self {
74         Self {
75             x_axis: Vec3A::new(m00, m01, m02),
76             y_axis: Vec3A::new(m10, m11, m12),
77             z_axis: Vec3A::new(m20, m21, m22),
78         }
79     }
80 
81     /// Creates a 3x3 matrix from three column vectors.
82     #[inline(always)]
83     #[must_use]
from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self84     pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
85         Self {
86             x_axis,
87             y_axis,
88             z_axis,
89         }
90     }
91 
92     /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
93     /// If your data is stored in row major you will need to `transpose` the returned
94     /// matrix.
95     #[inline]
96     #[must_use]
from_cols_array(m: &[f32; 9]) -> Self97     pub const fn from_cols_array(m: &[f32; 9]) -> Self {
98         Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
99     }
100 
101     /// Creates a `[f32; 9]` array storing data in column major order.
102     /// If you require data in row major order `transpose` the matrix first.
103     #[inline]
104     #[must_use]
to_cols_array(&self) -> [f32; 9]105     pub const fn to_cols_array(&self) -> [f32; 9] {
106         let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
107         let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
108         let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
109 
110         [
111             x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
112             z_axis_z,
113         ]
114     }
115 
116     /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
117     /// If your data is in row major order you will need to `transpose` the returned
118     /// matrix.
119     #[inline]
120     #[must_use]
from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self121     pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
122         Self::from_cols(
123             Vec3A::from_array(m[0]),
124             Vec3A::from_array(m[1]),
125             Vec3A::from_array(m[2]),
126         )
127     }
128 
129     /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
130     /// If you require data in row major order `transpose` the matrix first.
131     #[inline]
132     #[must_use]
to_cols_array_2d(&self) -> [[f32; 3]; 3]133     pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
134         [
135             self.x_axis.to_array(),
136             self.y_axis.to_array(),
137             self.z_axis.to_array(),
138         ]
139     }
140 
141     /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
142     #[doc(alias = "scale")]
143     #[inline]
144     #[must_use]
from_diagonal(diagonal: Vec3) -> Self145     pub const fn from_diagonal(diagonal: Vec3) -> Self {
146         Self::new(
147             diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
148         )
149     }
150 
151     /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
152     #[inline]
153     #[must_use]
from_mat4(m: Mat4) -> Self154     pub fn from_mat4(m: Mat4) -> Self {
155         Self::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
156     }
157 
158     /// Creates a 3D rotation matrix from the given quaternion.
159     ///
160     /// # Panics
161     ///
162     /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
163     #[inline]
164     #[must_use]
from_quat(rotation: Quat) -> Self165     pub fn from_quat(rotation: Quat) -> Self {
166         glam_assert!(rotation.is_normalized());
167 
168         let x2 = rotation.x + rotation.x;
169         let y2 = rotation.y + rotation.y;
170         let z2 = rotation.z + rotation.z;
171         let xx = rotation.x * x2;
172         let xy = rotation.x * y2;
173         let xz = rotation.x * z2;
174         let yy = rotation.y * y2;
175         let yz = rotation.y * z2;
176         let zz = rotation.z * z2;
177         let wx = rotation.w * x2;
178         let wy = rotation.w * y2;
179         let wz = rotation.w * z2;
180 
181         Self::from_cols(
182             Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
183             Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
184             Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
185         )
186     }
187 
188     /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
189     /// radians).
190     ///
191     /// # Panics
192     ///
193     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
194     #[inline]
195     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self196     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
197         glam_assert!(axis.is_normalized());
198 
199         let (sin, cos) = math::sin_cos(angle);
200         let (xsin, ysin, zsin) = axis.mul(sin).into();
201         let (x, y, z) = axis.into();
202         let (x2, y2, z2) = axis.mul(axis).into();
203         let omc = 1.0 - cos;
204         let xyomc = x * y * omc;
205         let xzomc = x * z * omc;
206         let yzomc = y * z * omc;
207         Self::from_cols(
208             Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
209             Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
210             Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
211         )
212     }
213 
214     /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
215     /// radians).
216     #[inline]
217     #[must_use]
from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self218     pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
219         let quat = Quat::from_euler(order, a, b, c);
220         Self::from_quat(quat)
221     }
222 
223     /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
224     #[inline]
225     #[must_use]
from_rotation_x(angle: f32) -> Self226     pub fn from_rotation_x(angle: f32) -> Self {
227         let (sina, cosa) = math::sin_cos(angle);
228         Self::from_cols(
229             Vec3A::X,
230             Vec3A::new(0.0, cosa, sina),
231             Vec3A::new(0.0, -sina, cosa),
232         )
233     }
234 
235     /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
236     #[inline]
237     #[must_use]
from_rotation_y(angle: f32) -> Self238     pub fn from_rotation_y(angle: f32) -> Self {
239         let (sina, cosa) = math::sin_cos(angle);
240         Self::from_cols(
241             Vec3A::new(cosa, 0.0, -sina),
242             Vec3A::Y,
243             Vec3A::new(sina, 0.0, cosa),
244         )
245     }
246 
247     /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
248     #[inline]
249     #[must_use]
from_rotation_z(angle: f32) -> Self250     pub fn from_rotation_z(angle: f32) -> Self {
251         let (sina, cosa) = math::sin_cos(angle);
252         Self::from_cols(
253             Vec3A::new(cosa, sina, 0.0),
254             Vec3A::new(-sina, cosa, 0.0),
255             Vec3A::Z,
256         )
257     }
258 
259     /// Creates an affine transformation matrix from the given 2D `translation`.
260     ///
261     /// The resulting matrix can be used to transform 2D points and vectors. See
262     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
263     #[inline]
264     #[must_use]
from_translation(translation: Vec2) -> Self265     pub fn from_translation(translation: Vec2) -> Self {
266         Self::from_cols(
267             Vec3A::X,
268             Vec3A::Y,
269             Vec3A::new(translation.x, translation.y, 1.0),
270         )
271     }
272 
273     /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
274     /// radians).
275     ///
276     /// The resulting matrix can be used to transform 2D points and vectors. See
277     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
278     #[inline]
279     #[must_use]
from_angle(angle: f32) -> Self280     pub fn from_angle(angle: f32) -> Self {
281         let (sin, cos) = math::sin_cos(angle);
282         Self::from_cols(
283             Vec3A::new(cos, sin, 0.0),
284             Vec3A::new(-sin, cos, 0.0),
285             Vec3A::Z,
286         )
287     }
288 
289     /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
290     /// radians) and `translation`.
291     ///
292     /// The resulting matrix can be used to transform 2D points and vectors. See
293     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
294     #[inline]
295     #[must_use]
from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self296     pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
297         let (sin, cos) = math::sin_cos(angle);
298         Self::from_cols(
299             Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
300             Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
301             Vec3A::new(translation.x, translation.y, 1.0),
302         )
303     }
304 
305     /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
306     ///
307     /// The resulting matrix can be used to transform 2D points and vectors. See
308     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
309     ///
310     /// # Panics
311     ///
312     /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
313     #[inline]
314     #[must_use]
from_scale(scale: Vec2) -> Self315     pub fn from_scale(scale: Vec2) -> Self {
316         // Do not panic as long as any component is non-zero
317         glam_assert!(scale.cmpne(Vec2::ZERO).any());
318 
319         Self::from_cols(
320             Vec3A::new(scale.x, 0.0, 0.0),
321             Vec3A::new(0.0, scale.y, 0.0),
322             Vec3A::Z,
323         )
324     }
325 
326     /// Creates an affine transformation matrix from the given 2x2 matrix.
327     ///
328     /// The resulting matrix can be used to transform 2D points and vectors. See
329     /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
330     #[inline]
from_mat2(m: Mat2) -> Self331     pub fn from_mat2(m: Mat2) -> Self {
332         Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
333     }
334 
335     /// Creates a 3x3 matrix from the first 9 values in `slice`.
336     ///
337     /// # Panics
338     ///
339     /// Panics if `slice` is less than 9 elements long.
340     #[inline]
341     #[must_use]
from_cols_slice(slice: &[f32]) -> Self342     pub const fn from_cols_slice(slice: &[f32]) -> Self {
343         Self::new(
344             slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
345             slice[8],
346         )
347     }
348 
349     /// Writes the columns of `self` to the first 9 elements in `slice`.
350     ///
351     /// # Panics
352     ///
353     /// Panics if `slice` is less than 9 elements long.
354     #[inline]
write_cols_to_slice(self, slice: &mut [f32])355     pub fn write_cols_to_slice(self, slice: &mut [f32]) {
356         slice[0] = self.x_axis.x;
357         slice[1] = self.x_axis.y;
358         slice[2] = self.x_axis.z;
359         slice[3] = self.y_axis.x;
360         slice[4] = self.y_axis.y;
361         slice[5] = self.y_axis.z;
362         slice[6] = self.z_axis.x;
363         slice[7] = self.z_axis.y;
364         slice[8] = self.z_axis.z;
365     }
366 
367     /// Returns the matrix column for the given `index`.
368     ///
369     /// # Panics
370     ///
371     /// Panics if `index` is greater than 2.
372     #[inline]
373     #[must_use]
col(&self, index: usize) -> Vec3A374     pub fn col(&self, index: usize) -> Vec3A {
375         match index {
376             0 => self.x_axis,
377             1 => self.y_axis,
378             2 => self.z_axis,
379             _ => panic!("index out of bounds"),
380         }
381     }
382 
383     /// Returns a mutable reference to the matrix column for the given `index`.
384     ///
385     /// # Panics
386     ///
387     /// Panics if `index` is greater than 2.
388     #[inline]
col_mut(&mut self, index: usize) -> &mut Vec3A389     pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
390         match index {
391             0 => &mut self.x_axis,
392             1 => &mut self.y_axis,
393             2 => &mut self.z_axis,
394             _ => panic!("index out of bounds"),
395         }
396     }
397 
398     /// Returns the matrix row for the given `index`.
399     ///
400     /// # Panics
401     ///
402     /// Panics if `index` is greater than 2.
403     #[inline]
404     #[must_use]
row(&self, index: usize) -> Vec3A405     pub fn row(&self, index: usize) -> Vec3A {
406         match index {
407             0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
408             1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
409             2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
410             _ => panic!("index out of bounds"),
411         }
412     }
413 
414     /// Returns `true` if, and only if, all elements are finite.
415     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
416     #[inline]
417     #[must_use]
is_finite(&self) -> bool418     pub fn is_finite(&self) -> bool {
419         self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
420     }
421 
422     /// Returns `true` if any elements are `NaN`.
423     #[inline]
424     #[must_use]
is_nan(&self) -> bool425     pub fn is_nan(&self) -> bool {
426         self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
427     }
428 
429     /// Returns the transpose of `self`.
430     #[inline]
431     #[must_use]
transpose(&self) -> Self432     pub fn transpose(&self) -> Self {
433         let tmp0 = i32x4_shuffle::<0, 1, 4, 5>(self.x_axis.0, self.y_axis.0);
434         let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0);
435 
436         Self {
437             x_axis: Vec3A(i32x4_shuffle::<0, 2, 4, 4>(tmp0, self.z_axis.0)),
438             y_axis: Vec3A(i32x4_shuffle::<1, 3, 5, 5>(tmp0, self.z_axis.0)),
439             z_axis: Vec3A(i32x4_shuffle::<0, 2, 6, 6>(tmp1, self.z_axis.0)),
440         }
441     }
442 
443     /// Returns the determinant of `self`.
444     #[inline]
445     #[must_use]
determinant(&self) -> f32446     pub fn determinant(&self) -> f32 {
447         self.z_axis.dot(self.x_axis.cross(self.y_axis))
448     }
449 
450     /// Returns the inverse of `self`.
451     ///
452     /// If the matrix is not invertible the returned matrix will be invalid.
453     ///
454     /// # Panics
455     ///
456     /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
457     #[inline]
458     #[must_use]
inverse(&self) -> Self459     pub fn inverse(&self) -> Self {
460         let tmp0 = self.y_axis.cross(self.z_axis);
461         let tmp1 = self.z_axis.cross(self.x_axis);
462         let tmp2 = self.x_axis.cross(self.y_axis);
463         let det = self.z_axis.dot(tmp2);
464         glam_assert!(det != 0.0);
465         let inv_det = Vec3A::splat(det.recip());
466         Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose()
467     }
468 
469     /// Transforms the given 2D vector as a point.
470     ///
471     /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
472     ///
473     /// This method assumes that `self` contains a valid affine transform.
474     ///
475     /// # Panics
476     ///
477     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
478     #[inline]
479     #[must_use]
transform_point2(&self, rhs: Vec2) -> Vec2480     pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
481         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
482         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
483     }
484 
485     /// Rotates the given 2D vector.
486     ///
487     /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
488     ///
489     /// This method assumes that `self` contains a valid affine transform.
490     ///
491     /// # Panics
492     ///
493     /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
494     #[inline]
495     #[must_use]
transform_vector2(&self, rhs: Vec2) -> Vec2496     pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
497         glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
498         Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
499     }
500 
501     /// Transforms a 3D vector.
502     #[inline]
503     #[must_use]
mul_vec3(&self, rhs: Vec3) -> Vec3504     pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
505         self.mul_vec3a(rhs.into()).into()
506     }
507 
508     /// Transforms a [`Vec3A`].
509     #[inline]
510     #[must_use]
mul_vec3a(&self, rhs: Vec3A) -> Vec3A511     pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
512         let mut res = self.x_axis.mul(rhs.xxx());
513         res = res.add(self.y_axis.mul(rhs.yyy()));
514         res = res.add(self.z_axis.mul(rhs.zzz()));
515         res
516     }
517 
518     /// Multiplies two 3x3 matrices.
519     #[inline]
520     #[must_use]
mul_mat3(&self, rhs: &Self) -> Self521     pub fn mul_mat3(&self, rhs: &Self) -> Self {
522         Self::from_cols(
523             self.mul(rhs.x_axis),
524             self.mul(rhs.y_axis),
525             self.mul(rhs.z_axis),
526         )
527     }
528 
529     /// Adds two 3x3 matrices.
530     #[inline]
531     #[must_use]
add_mat3(&self, rhs: &Self) -> Self532     pub fn add_mat3(&self, rhs: &Self) -> Self {
533         Self::from_cols(
534             self.x_axis.add(rhs.x_axis),
535             self.y_axis.add(rhs.y_axis),
536             self.z_axis.add(rhs.z_axis),
537         )
538     }
539 
540     /// Subtracts two 3x3 matrices.
541     #[inline]
542     #[must_use]
sub_mat3(&self, rhs: &Self) -> Self543     pub fn sub_mat3(&self, rhs: &Self) -> Self {
544         Self::from_cols(
545             self.x_axis.sub(rhs.x_axis),
546             self.y_axis.sub(rhs.y_axis),
547             self.z_axis.sub(rhs.z_axis),
548         )
549     }
550 
551     /// Multiplies a 3x3 matrix by a scalar.
552     #[inline]
553     #[must_use]
mul_scalar(&self, rhs: f32) -> Self554     pub fn mul_scalar(&self, rhs: f32) -> Self {
555         Self::from_cols(
556             self.x_axis.mul(rhs),
557             self.y_axis.mul(rhs),
558             self.z_axis.mul(rhs),
559         )
560     }
561 
562     /// Returns true if the absolute difference of all elements between `self` and `rhs`
563     /// is less than or equal to `max_abs_diff`.
564     ///
565     /// This can be used to compare if two matrices contain similar elements. It works best
566     /// when comparing with a known value. The `max_abs_diff` that should be used used
567     /// depends on the values being compared against.
568     ///
569     /// For more see
570     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
571     #[inline]
572     #[must_use]
abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool573     pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
574         self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
575             && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
576             && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
577     }
578 
579     #[inline]
as_dmat3(&self) -> DMat3580     pub fn as_dmat3(&self) -> DMat3 {
581         DMat3::from_cols(
582             self.x_axis.as_dvec3(),
583             self.y_axis.as_dvec3(),
584             self.z_axis.as_dvec3(),
585         )
586     }
587 }
588 
589 impl Default for Mat3A {
590     #[inline]
default() -> Self591     fn default() -> Self {
592         Self::IDENTITY
593     }
594 }
595 
596 impl Add<Mat3A> for Mat3A {
597     type Output = Self;
598     #[inline]
add(self, rhs: Self) -> Self::Output599     fn add(self, rhs: Self) -> Self::Output {
600         self.add_mat3(&rhs)
601     }
602 }
603 
604 impl AddAssign<Mat3A> for Mat3A {
605     #[inline]
add_assign(&mut self, rhs: Self)606     fn add_assign(&mut self, rhs: Self) {
607         *self = self.add_mat3(&rhs);
608     }
609 }
610 
611 impl Sub<Mat3A> for Mat3A {
612     type Output = Self;
613     #[inline]
sub(self, rhs: Self) -> Self::Output614     fn sub(self, rhs: Self) -> Self::Output {
615         self.sub_mat3(&rhs)
616     }
617 }
618 
619 impl SubAssign<Mat3A> for Mat3A {
620     #[inline]
sub_assign(&mut self, rhs: Self)621     fn sub_assign(&mut self, rhs: Self) {
622         *self = self.sub_mat3(&rhs);
623     }
624 }
625 
626 impl Neg for Mat3A {
627     type Output = Self;
628     #[inline]
neg(self) -> Self::Output629     fn neg(self) -> Self::Output {
630         Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
631     }
632 }
633 
634 impl Mul<Mat3A> for Mat3A {
635     type Output = Self;
636     #[inline]
mul(self, rhs: Self) -> Self::Output637     fn mul(self, rhs: Self) -> Self::Output {
638         self.mul_mat3(&rhs)
639     }
640 }
641 
642 impl MulAssign<Mat3A> for Mat3A {
643     #[inline]
mul_assign(&mut self, rhs: Self)644     fn mul_assign(&mut self, rhs: Self) {
645         *self = self.mul_mat3(&rhs);
646     }
647 }
648 
649 impl Mul<Vec3A> for Mat3A {
650     type Output = Vec3A;
651     #[inline]
mul(self, rhs: Vec3A) -> Self::Output652     fn mul(self, rhs: Vec3A) -> Self::Output {
653         self.mul_vec3a(rhs)
654     }
655 }
656 
657 impl Mul<Mat3A> for f32 {
658     type Output = Mat3A;
659     #[inline]
mul(self, rhs: Mat3A) -> Self::Output660     fn mul(self, rhs: Mat3A) -> Self::Output {
661         rhs.mul_scalar(self)
662     }
663 }
664 
665 impl Mul<f32> for Mat3A {
666     type Output = Self;
667     #[inline]
mul(self, rhs: f32) -> Self::Output668     fn mul(self, rhs: f32) -> Self::Output {
669         self.mul_scalar(rhs)
670     }
671 }
672 
673 impl MulAssign<f32> for Mat3A {
674     #[inline]
mul_assign(&mut self, rhs: f32)675     fn mul_assign(&mut self, rhs: f32) {
676         *self = self.mul_scalar(rhs);
677     }
678 }
679 
680 impl Mul<Vec3> for Mat3A {
681     type Output = Vec3;
682     #[inline]
mul(self, rhs: Vec3) -> Vec3683     fn mul(self, rhs: Vec3) -> Vec3 {
684         self.mul_vec3a(rhs.into()).into()
685     }
686 }
687 
688 impl From<Mat3> for Mat3A {
689     #[inline]
from(m: Mat3) -> Self690     fn from(m: Mat3) -> Self {
691         Self {
692             x_axis: m.x_axis.into(),
693             y_axis: m.y_axis.into(),
694             z_axis: m.z_axis.into(),
695         }
696     }
697 }
698 
699 impl Sum<Self> for Mat3A {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,700     fn sum<I>(iter: I) -> Self
701     where
702         I: Iterator<Item = Self>,
703     {
704         iter.fold(Self::ZERO, Self::add)
705     }
706 }
707 
708 impl<'a> Sum<&'a Self> for Mat3A {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,709     fn sum<I>(iter: I) -> Self
710     where
711         I: Iterator<Item = &'a Self>,
712     {
713         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
714     }
715 }
716 
717 impl Product for Mat3A {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,718     fn product<I>(iter: I) -> Self
719     where
720         I: Iterator<Item = Self>,
721     {
722         iter.fold(Self::IDENTITY, Self::mul)
723     }
724 }
725 
726 impl<'a> Product<&'a Self> for Mat3A {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,727     fn product<I>(iter: I) -> Self
728     where
729         I: Iterator<Item = &'a Self>,
730     {
731         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
732     }
733 }
734 
735 impl PartialEq for Mat3A {
736     #[inline]
eq(&self, rhs: &Self) -> bool737     fn eq(&self, rhs: &Self) -> bool {
738         self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
739     }
740 }
741 
742 #[cfg(not(target_arch = "spirv"))]
743 impl fmt::Debug for Mat3A {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result744     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
745         fmt.debug_struct(stringify!(Mat3A))
746             .field("x_axis", &self.x_axis)
747             .field("y_axis", &self.y_axis)
748             .field("z_axis", &self.z_axis)
749             .finish()
750     }
751 }
752 
753 #[cfg(not(target_arch = "spirv"))]
754 impl fmt::Display for Mat3A {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result755     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
756         write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
757     }
758 }
759