Skip to main content

glam/f32/sse2/
mat3a.rs

1// Generated from mat.rs.tera template. Edit the template, not the generated file.
2
3#[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")]
22use zerocopy_derive::*;
23
24/// Creates a 3x3 matrix from three column vectors.
25#[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/// A 3x3 column major matrix.
32///
33/// This 3x3 matrix type features convenience methods for creating and using linear and
34/// affine transformations. If you are primarily dealing with 2D affine transformations the
35/// [`Affine2`](crate::Affine2) type is much faster and more space efficient than
36/// using a 3x3 matrix.
37///
38/// Linear transformations including 3D rotation and scale can be created using methods
39/// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`],
40/// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or
41/// [`Self::from_rotation_z()`].
42///
43/// The resulting matrices can be use to transform 3D vectors using regular vector
44/// multiplication.
45///
46/// Affine transformations including 2D translation, rotation and scale can be created
47/// using methods such as [`Self::from_translation()`], [`Self::from_angle()`],
48/// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`].
49///
50/// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods
51/// are provided for performing affine transforms on 2D vectors and points. These multiply
52/// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for
53/// vectors respectively. These methods assume that `Self` contains a valid affine
54/// transform.
55#[derive(Clone, Copy)]
56#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
57#[cfg_attr(
58    feature = "zerocopy",
59    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
60)]
61#[repr(C)]
62pub struct Mat3A {
63    pub x_axis: Vec3A,
64    pub y_axis: Vec3A,
65    pub z_axis: Vec3A,
66}
67
68impl Mat3A {
69    /// A 3x3 matrix with all elements set to `0.0`.
70    pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO);
71
72    /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`.
73    pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z);
74
75    /// All NAN:s.
76    pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN);
77
78    #[allow(clippy::too_many_arguments)]
79    #[inline(always)]
80    #[must_use]
81    const fn new(
82        m00: f32,
83        m01: f32,
84        m02: f32,
85        m10: f32,
86        m11: f32,
87        m12: f32,
88        m20: f32,
89        m21: f32,
90        m22: f32,
91    ) -> Self {
92        Self {
93            x_axis: Vec3A::new(m00, m01, m02),
94            y_axis: Vec3A::new(m10, m11, m12),
95            z_axis: Vec3A::new(m20, m21, m22),
96        }
97    }
98
99    /// Creates a 3x3 matrix from three column vectors.
100    #[inline(always)]
101    #[must_use]
102    pub const fn from_cols(x_axis: Vec3A, y_axis: Vec3A, z_axis: Vec3A) -> Self {
103        Self {
104            x_axis,
105            y_axis,
106            z_axis,
107        }
108    }
109
110    /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order.
111    /// If your data is stored in row major you will need to `transpose` the returned
112    /// matrix.
113    #[inline]
114    #[must_use]
115    pub const fn from_cols_array(m: &[f32; 9]) -> Self {
116        Self::new(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8])
117    }
118
119    /// Creates a `[f32; 9]` array storing data in column major order.
120    /// If you require data in row major order `transpose` the matrix first.
121    #[inline]
122    #[must_use]
123    pub const fn to_cols_array(&self) -> [f32; 9] {
124        let [x_axis_x, x_axis_y, x_axis_z] = self.x_axis.to_array();
125        let [y_axis_x, y_axis_y, y_axis_z] = self.y_axis.to_array();
126        let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array();
127
128        [
129            x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y,
130            z_axis_z,
131        ]
132    }
133
134    /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order.
135    /// If your data is in row major order you will need to `transpose` the returned
136    /// matrix.
137    #[inline]
138    #[must_use]
139    pub const fn from_cols_array_2d(m: &[[f32; 3]; 3]) -> Self {
140        Self::from_cols(
141            Vec3A::from_array(m[0]),
142            Vec3A::from_array(m[1]),
143            Vec3A::from_array(m[2]),
144        )
145    }
146
147    /// Creates a `[[f32; 3]; 3]` 3D array storing data in column major order.
148    /// If you require data in row major order `transpose` the matrix first.
149    #[inline]
150    #[must_use]
151    pub const fn to_cols_array_2d(&self) -> [[f32; 3]; 3] {
152        [
153            self.x_axis.to_array(),
154            self.y_axis.to_array(),
155            self.z_axis.to_array(),
156        ]
157    }
158
159    /// Creates a 3x3 matrix with its diagonal set to `diagonal` and all other entries set to 0.
160    #[doc(alias = "scale")]
161    #[inline]
162    #[must_use]
163    pub const fn from_diagonal(diagonal: Vec3) -> Self {
164        Self::new(
165            diagonal.x, 0.0, 0.0, 0.0, diagonal.y, 0.0, 0.0, 0.0, diagonal.z,
166        )
167    }
168
169    /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column.
170    #[inline]
171    #[must_use]
172    pub fn from_mat4(m: Mat4) -> Self {
173        Self::from_cols(
174            Vec3A::from_vec4(m.x_axis),
175            Vec3A::from_vec4(m.y_axis),
176            Vec3A::from_vec4(m.z_axis),
177        )
178    }
179
180    /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column
181    /// and `j`th row.
182    ///
183    /// # Panics
184    ///
185    /// Panics if `i` or `j` is greater than 3.
186    #[inline]
187    #[must_use]
188    pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self {
189        match (i, j) {
190            (0, 0) => Self::from_cols(
191                Vec3A::from_vec4(m.y_axis.yzww()),
192                Vec3A::from_vec4(m.z_axis.yzww()),
193                Vec3A::from_vec4(m.w_axis.yzww()),
194            ),
195            (0, 1) => Self::from_cols(
196                Vec3A::from_vec4(m.y_axis.xzww()),
197                Vec3A::from_vec4(m.z_axis.xzww()),
198                Vec3A::from_vec4(m.w_axis.xzww()),
199            ),
200            (0, 2) => Self::from_cols(
201                Vec3A::from_vec4(m.y_axis.xyww()),
202                Vec3A::from_vec4(m.z_axis.xyww()),
203                Vec3A::from_vec4(m.w_axis.xyww()),
204            ),
205            (0, 3) => Self::from_cols(
206                Vec3A::from_vec4(m.y_axis.xyzw()),
207                Vec3A::from_vec4(m.z_axis.xyzw()),
208                Vec3A::from_vec4(m.w_axis.xyzw()),
209            ),
210            (1, 0) => Self::from_cols(
211                Vec3A::from_vec4(m.x_axis.yzww()),
212                Vec3A::from_vec4(m.z_axis.yzww()),
213                Vec3A::from_vec4(m.w_axis.yzww()),
214            ),
215            (1, 1) => Self::from_cols(
216                Vec3A::from_vec4(m.x_axis.xzww()),
217                Vec3A::from_vec4(m.z_axis.xzww()),
218                Vec3A::from_vec4(m.w_axis.xzww()),
219            ),
220            (1, 2) => Self::from_cols(
221                Vec3A::from_vec4(m.x_axis.xyww()),
222                Vec3A::from_vec4(m.z_axis.xyww()),
223                Vec3A::from_vec4(m.w_axis.xyww()),
224            ),
225            (1, 3) => Self::from_cols(
226                Vec3A::from_vec4(m.x_axis.xyzw()),
227                Vec3A::from_vec4(m.z_axis.xyzw()),
228                Vec3A::from_vec4(m.w_axis.xyzw()),
229            ),
230            (2, 0) => Self::from_cols(
231                Vec3A::from_vec4(m.x_axis.yzww()),
232                Vec3A::from_vec4(m.y_axis.yzww()),
233                Vec3A::from_vec4(m.w_axis.yzww()),
234            ),
235            (2, 1) => Self::from_cols(
236                Vec3A::from_vec4(m.x_axis.xzww()),
237                Vec3A::from_vec4(m.y_axis.xzww()),
238                Vec3A::from_vec4(m.w_axis.xzww()),
239            ),
240            (2, 2) => Self::from_cols(
241                Vec3A::from_vec4(m.x_axis.xyww()),
242                Vec3A::from_vec4(m.y_axis.xyww()),
243                Vec3A::from_vec4(m.w_axis.xyww()),
244            ),
245            (2, 3) => Self::from_cols(
246                Vec3A::from_vec4(m.x_axis.xyzw()),
247                Vec3A::from_vec4(m.y_axis.xyzw()),
248                Vec3A::from_vec4(m.w_axis.xyzw()),
249            ),
250            (3, 0) => Self::from_cols(
251                Vec3A::from_vec4(m.x_axis.yzww()),
252                Vec3A::from_vec4(m.y_axis.yzww()),
253                Vec3A::from_vec4(m.z_axis.yzww()),
254            ),
255            (3, 1) => Self::from_cols(
256                Vec3A::from_vec4(m.x_axis.xzww()),
257                Vec3A::from_vec4(m.y_axis.xzww()),
258                Vec3A::from_vec4(m.z_axis.xzww()),
259            ),
260            (3, 2) => Self::from_cols(
261                Vec3A::from_vec4(m.x_axis.xyww()),
262                Vec3A::from_vec4(m.y_axis.xyww()),
263                Vec3A::from_vec4(m.z_axis.xyww()),
264            ),
265            (3, 3) => Self::from_cols(
266                Vec3A::from_vec4(m.x_axis.xyzw()),
267                Vec3A::from_vec4(m.y_axis.xyzw()),
268                Vec3A::from_vec4(m.z_axis.xyzw()),
269            ),
270            _ => panic!("index out of bounds"),
271        }
272    }
273
274    /// Creates a 3D rotation matrix from the given quaternion.
275    ///
276    /// # Panics
277    ///
278    /// Will panic if `rotation` is not normalized when `glam_assert` is enabled.
279    #[inline]
280    #[must_use]
281    pub fn from_quat(rotation: Quat) -> Self {
282        glam_assert!(rotation.is_normalized());
283
284        let x2 = rotation.x + rotation.x;
285        let y2 = rotation.y + rotation.y;
286        let z2 = rotation.z + rotation.z;
287        let xx = rotation.x * x2;
288        let xy = rotation.x * y2;
289        let xz = rotation.x * z2;
290        let yy = rotation.y * y2;
291        let yz = rotation.y * z2;
292        let zz = rotation.z * z2;
293        let wx = rotation.w * x2;
294        let wy = rotation.w * y2;
295        let wz = rotation.w * z2;
296
297        Self::from_cols(
298            Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy),
299            Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx),
300            Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)),
301        )
302    }
303
304    /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in
305    /// radians).
306    ///
307    /// # Panics
308    ///
309    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
310    #[inline]
311    #[must_use]
312    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
313        glam_assert!(axis.is_normalized());
314
315        let (sin, cos) = math::sin_cos(angle);
316        let (xsin, ysin, zsin) = axis.mul(sin).into();
317        let (x, y, z) = axis.into();
318        let (x2, y2, z2) = axis.mul(axis).into();
319        let omc = 1.0 - cos;
320        let xyomc = x * y * omc;
321        let xzomc = x * z * omc;
322        let yzomc = y * z * omc;
323        Self::from_cols(
324            Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin),
325            Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin),
326            Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos),
327        )
328    }
329
330    /// Creates a 3D rotation matrix from the given euler rotation sequence and the angles (in
331    /// radians).
332    #[inline]
333    #[must_use]
334    pub fn from_euler(order: EulerRot, a: f32, b: f32, c: f32) -> Self {
335        Self::from_euler_angles(order, a, b, c)
336    }
337
338    /// Extract Euler angles with the given Euler rotation order.
339    ///
340    /// Note if the input matrix contains scales, shears, or other non-rotation transformations then
341    /// the resulting Euler angles will be ill-defined.
342    ///
343    /// # Panics
344    ///
345    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
346    #[inline]
347    #[must_use]
348    pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) {
349        glam_assert!(
350            self.x_axis.is_normalized()
351                && self.y_axis.is_normalized()
352                && self.z_axis.is_normalized()
353        );
354        self.to_euler_angles(order)
355    }
356
357    /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis.
358    #[inline]
359    #[must_use]
360    pub fn from_rotation_x(angle: f32) -> Self {
361        let (sina, cosa) = math::sin_cos(angle);
362        Self::from_cols(
363            Vec3A::X,
364            Vec3A::new(0.0, cosa, sina),
365            Vec3A::new(0.0, -sina, cosa),
366        )
367    }
368
369    /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis.
370    #[inline]
371    #[must_use]
372    pub fn from_rotation_y(angle: f32) -> Self {
373        let (sina, cosa) = math::sin_cos(angle);
374        Self::from_cols(
375            Vec3A::new(cosa, 0.0, -sina),
376            Vec3A::Y,
377            Vec3A::new(sina, 0.0, cosa),
378        )
379    }
380
381    /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis.
382    #[inline]
383    #[must_use]
384    pub fn from_rotation_z(angle: f32) -> Self {
385        let (sina, cosa) = math::sin_cos(angle);
386        Self::from_cols(
387            Vec3A::new(cosa, sina, 0.0),
388            Vec3A::new(-sina, cosa, 0.0),
389            Vec3A::Z,
390        )
391    }
392
393    /// Creates an affine transformation matrix from the given 2D `translation`.
394    ///
395    /// The resulting matrix can be used to transform 2D points and vectors. See
396    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
397    #[inline]
398    #[must_use]
399    pub fn from_translation(translation: Vec2) -> Self {
400        Self::from_cols(
401            Vec3A::X,
402            Vec3A::Y,
403            Vec3A::new(translation.x, translation.y, 1.0),
404        )
405    }
406
407    /// Creates an affine transformation matrix from the given 2D rotation `angle` (in
408    /// radians).
409    ///
410    /// The resulting matrix can be used to transform 2D points and vectors. See
411    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
412    #[inline]
413    #[must_use]
414    pub fn from_angle(angle: f32) -> Self {
415        let (sin, cos) = math::sin_cos(angle);
416        Self::from_cols(
417            Vec3A::new(cos, sin, 0.0),
418            Vec3A::new(-sin, cos, 0.0),
419            Vec3A::Z,
420        )
421    }
422
423    /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in
424    /// radians) and `translation`.
425    ///
426    /// The resulting matrix can be used to transform 2D points and vectors. See
427    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
428    #[inline]
429    #[must_use]
430    pub fn from_scale_angle_translation(scale: Vec2, angle: f32, translation: Vec2) -> Self {
431        let (sin, cos) = math::sin_cos(angle);
432        Self::from_cols(
433            Vec3A::new(cos * scale.x, sin * scale.x, 0.0),
434            Vec3A::new(-sin * scale.y, cos * scale.y, 0.0),
435            Vec3A::new(translation.x, translation.y, 1.0),
436        )
437    }
438
439    /// Creates an affine transformation matrix from the given non-uniform 2D `scale`.
440    ///
441    /// The resulting matrix can be used to transform 2D points and vectors. See
442    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
443    ///
444    /// # Panics
445    ///
446    /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled.
447    #[inline]
448    #[must_use]
449    pub fn from_scale(scale: Vec2) -> Self {
450        // Do not panic as long as any component is non-zero
451        glam_assert!(scale.cmpne(Vec2::ZERO).any());
452
453        Self::from_cols(
454            Vec3A::new(scale.x, 0.0, 0.0),
455            Vec3A::new(0.0, scale.y, 0.0),
456            Vec3A::Z,
457        )
458    }
459
460    /// Creates an affine transformation matrix from the given 2x2 matrix.
461    ///
462    /// The resulting matrix can be used to transform 2D points and vectors. See
463    /// [`Self::transform_point2()`] and [`Self::transform_vector2()`].
464    #[inline]
465    pub fn from_mat2(m: Mat2) -> Self {
466        Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z)
467    }
468
469    /// Creates a 3x3 matrix from the first 9 values in `slice`.
470    ///
471    /// # Panics
472    ///
473    /// Panics if `slice` is less than 9 elements long.
474    #[inline]
475    #[must_use]
476    pub const fn from_cols_slice(slice: &[f32]) -> Self {
477        Self::new(
478            slice[0], slice[1], slice[2], slice[3], slice[4], slice[5], slice[6], slice[7],
479            slice[8],
480        )
481    }
482
483    /// Writes the columns of `self` to the first 9 elements in `slice`.
484    ///
485    /// # Panics
486    ///
487    /// Panics if `slice` is less than 9 elements long.
488    #[inline]
489    pub fn write_cols_to_slice(&self, slice: &mut [f32]) {
490        slice[0] = self.x_axis.x;
491        slice[1] = self.x_axis.y;
492        slice[2] = self.x_axis.z;
493        slice[3] = self.y_axis.x;
494        slice[4] = self.y_axis.y;
495        slice[5] = self.y_axis.z;
496        slice[6] = self.z_axis.x;
497        slice[7] = self.z_axis.y;
498        slice[8] = self.z_axis.z;
499    }
500
501    /// Returns the matrix column for the given `index`.
502    ///
503    /// # Panics
504    ///
505    /// Panics if `index` is greater than 2.
506    #[inline]
507    #[must_use]
508    pub fn col(&self, index: usize) -> Vec3A {
509        match index {
510            0 => self.x_axis,
511            1 => self.y_axis,
512            2 => self.z_axis,
513            _ => panic!("index out of bounds"),
514        }
515    }
516
517    /// Returns a mutable reference to the matrix column for the given `index`.
518    ///
519    /// # Panics
520    ///
521    /// Panics if `index` is greater than 2.
522    #[inline]
523    pub fn col_mut(&mut self, index: usize) -> &mut Vec3A {
524        match index {
525            0 => &mut self.x_axis,
526            1 => &mut self.y_axis,
527            2 => &mut self.z_axis,
528            _ => panic!("index out of bounds"),
529        }
530    }
531
532    /// Returns the matrix row for the given `index`.
533    ///
534    /// # Panics
535    ///
536    /// Panics if `index` is greater than 2.
537    #[inline]
538    #[must_use]
539    pub fn row(&self, index: usize) -> Vec3A {
540        match index {
541            0 => Vec3A::new(self.x_axis.x, self.y_axis.x, self.z_axis.x),
542            1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y),
543            2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z),
544            _ => panic!("index out of bounds"),
545        }
546    }
547
548    /// Returns `true` if, and only if, all elements are finite.
549    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
550    #[inline]
551    #[must_use]
552    pub fn is_finite(&self) -> bool {
553        self.x_axis.is_finite() && self.y_axis.is_finite() && self.z_axis.is_finite()
554    }
555
556    /// Returns `true` if any elements are `NaN`.
557    #[inline]
558    #[must_use]
559    pub fn is_nan(&self) -> bool {
560        self.x_axis.is_nan() || self.y_axis.is_nan() || self.z_axis.is_nan()
561    }
562
563    /// Returns the transpose of `self`.
564    #[inline]
565    #[must_use]
566    pub fn transpose(&self) -> Self {
567        unsafe {
568            let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00);
569            let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10);
570
571            Self {
572                x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)),
573                y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)),
574                z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)),
575            }
576        }
577    }
578
579    /// Returns the diagonal of `self`.
580    #[inline]
581    #[must_use]
582    pub fn diagonal(&self) -> Vec3A {
583        Vec3A::new(self.x_axis.x, self.y_axis.y, self.z_axis.z)
584    }
585
586    /// Returns the determinant of `self`.
587    #[inline]
588    #[must_use]
589    pub fn determinant(&self) -> f32 {
590        self.z_axis.dot(self.x_axis.cross(self.y_axis))
591    }
592
593    /// If `CHECKED` is true then if the determinant is zero this function will return a tuple
594    /// containing a zero matrix and false. If the determinant is non zero a tuple containing the
595    /// inverted matrix and true is returned.
596    ///
597    /// If `CHECKED` is false then the determinant is not checked and if it is zero the resulting
598    /// inverted matrix will be invalid. Will panic if the determinant of `self` is zero when
599    /// `glam_assert` is enabled.
600    ///
601    /// A tuple containing the inverted matrix and a bool is used instead of an option here as
602    /// regular Rust enums put the discriminant first which can result in a lot of padding if the
603    /// matrix is aligned.
604    #[inline(always)]
605    #[must_use]
606    fn inverse_checked<const CHECKED: bool>(&self) -> (Self, bool) {
607        let tmp0 = self.y_axis.cross(self.z_axis);
608        let tmp1 = self.z_axis.cross(self.x_axis);
609        let tmp2 = self.x_axis.cross(self.y_axis);
610        let det = self.z_axis.dot(tmp2);
611        if CHECKED {
612            if det == 0.0 {
613                return (Self::ZERO, false);
614            }
615        } else {
616            glam_assert!(det != 0.0);
617        }
618        let inv_det = Vec3A::splat(det.recip());
619        (
620            Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose(),
621            true,
622        )
623    }
624
625    /// Returns the inverse of `self`.
626    ///
627    /// If the matrix is not invertible the returned matrix will be invalid.
628    ///
629    /// # Panics
630    ///
631    /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled.
632    #[inline]
633    #[must_use]
634    pub fn inverse(&self) -> Self {
635        self.inverse_checked::<false>().0
636    }
637
638    /// Returns the inverse of `self` or `None` if the matrix is not invertible.
639    #[inline]
640    #[must_use]
641    pub fn try_inverse(&self) -> Option<Self> {
642        let (m, is_valid) = self.inverse_checked::<true>();
643        if is_valid {
644            Some(m)
645        } else {
646            None
647        }
648    }
649
650    /// Returns the inverse of `self` or `Mat3A::ZERO` if the matrix is not invertible.
651    #[inline]
652    #[must_use]
653    pub fn inverse_or_zero(&self) -> Self {
654        self.inverse_checked::<true>().0
655    }
656
657    /// Transforms the given 2D vector as a point.
658    ///
659    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.
660    ///
661    /// This method assumes that `self` contains a valid affine transform.
662    ///
663    /// # Panics
664    ///
665    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
666    #[inline]
667    #[must_use]
668    pub fn transform_point2(&self, rhs: Vec2) -> Vec2 {
669        glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
670        Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy()
671    }
672
673    /// Rotates the given 2D vector.
674    ///
675    /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.
676    ///
677    /// This method assumes that `self` contains a valid affine transform.
678    ///
679    /// # Panics
680    ///
681    /// Will panic if the 2nd row of `self` is not `(0, 0, 1)` when `glam_assert` is enabled.
682    #[inline]
683    #[must_use]
684    pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 {
685        glam_assert!(self.row(2).abs_diff_eq(Vec3A::Z, 1e-6));
686        Mat2::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs
687    }
688
689    /// Creates a left-handed view matrix using a facing direction and an up direction.
690    ///
691    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
692    ///
693    /// # Panics
694    ///
695    /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
696    #[deprecated(
697        since = "0.33.1",
698        note = "use the `glam::camera::lh::view::look_to_mat3` function instead"
699    )]
700    #[inline]
701    #[must_use]
702    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
703        #[allow(deprecated)]
704        Self::look_to_rh(-dir, up)
705    }
706
707    /// Creates a right-handed view matrix using a facing direction and an up direction.
708    ///
709    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
710    ///
711    /// # Panics
712    ///
713    /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled.
714    #[deprecated(
715        since = "0.33.1",
716        note = "use the `glam::camera::rh::view::look_to_mat3` function instead"
717    )]
718    #[inline]
719    #[must_use]
720    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
721        glam_assert!(dir.is_normalized());
722        glam_assert!(up.is_normalized());
723        let f = dir;
724        let s = f.cross(up).normalize();
725        let u = s.cross(f);
726
727        Self::from_cols(
728            Vec3A::new(s.x, u.x, -f.x),
729            Vec3A::new(s.y, u.y, -f.y),
730            Vec3A::new(s.z, u.z, -f.z),
731        )
732    }
733
734    /// Creates a left-handed view matrix using a camera position, a focal point and an up
735    /// direction.
736    ///
737    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
738    ///
739    /// # Panics
740    ///
741    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
742    #[deprecated(
743        since = "0.33.1",
744        note = "use the `glam::camera::lh::view::look_at_mat3` function instead"
745    )]
746    #[inline]
747    #[must_use]
748    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
749        #[allow(deprecated)]
750        Self::look_to_lh(center.sub(eye).normalize(), up)
751    }
752
753    /// Creates a right-handed view matrix using a camera position, a focal point and an up
754    /// direction.
755    ///
756    /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
757    ///
758    /// # Panics
759    ///
760    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
761    #[deprecated(
762        since = "0.33.1",
763        note = "use the `glam::camera::rh::view::look_at_mat3` function instead"
764    )]
765    #[inline]
766    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
767        #[allow(deprecated)]
768        Self::look_to_rh(center.sub(eye).normalize(), up)
769    }
770
771    /// Transforms a 3D vector.
772    #[inline]
773    #[must_use]
774    pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 {
775        self.mul_vec3a(rhs.into()).into()
776    }
777
778    /// Transforms a [`Vec3A`].
779    #[inline]
780    #[must_use]
781    pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A {
782        let mut res = self.x_axis.mul(rhs.xxx());
783        res = res.add(self.y_axis.mul(rhs.yyy()));
784        res = res.add(self.z_axis.mul(rhs.zzz()));
785        res
786    }
787
788    /// Transforms a 3D vector by the transpose of `self`.
789    #[inline]
790    #[must_use]
791    pub fn mul_transpose_vec3(&self, rhs: Vec3) -> Vec3 {
792        self.mul_transpose_vec3a(rhs.into()).into()
793    }
794
795    /// Transforms a [`Vec3A`] by the transpose of `self`.
796    #[inline]
797    #[must_use]
798    pub fn mul_transpose_vec3a(&self, rhs: Vec3A) -> Vec3A {
799        Vec3A::new(
800            self.x_axis.dot(rhs),
801            self.y_axis.dot(rhs),
802            self.z_axis.dot(rhs),
803        )
804    }
805
806    /// Multiplies two 3x3 matrices.
807    #[inline]
808    #[must_use]
809    pub fn mul_mat3(&self, rhs: &Self) -> Self {
810        self.mul(rhs)
811    }
812
813    /// Adds two 3x3 matrices.
814    #[inline]
815    #[must_use]
816    pub fn add_mat3(&self, rhs: &Self) -> Self {
817        self.add(rhs)
818    }
819
820    /// Subtracts two 3x3 matrices.
821    #[inline]
822    #[must_use]
823    pub fn sub_mat3(&self, rhs: &Self) -> Self {
824        self.sub(rhs)
825    }
826
827    /// Multiplies a 3x3 matrix by a scalar.
828    #[inline]
829    #[must_use]
830    pub fn mul_scalar(&self, rhs: f32) -> Self {
831        Self::from_cols(
832            self.x_axis.mul(rhs),
833            self.y_axis.mul(rhs),
834            self.z_axis.mul(rhs),
835        )
836    }
837
838    /// Multiply `self` by a scaling vector `scale`.
839    /// This is faster than creating a whole diagonal scaling matrix and then multiplying that.
840    /// This operation is commutative.
841    #[inline]
842    #[must_use]
843    pub fn mul_diagonal_scale(&self, scale: Vec3) -> Self {
844        Self::from_cols(
845            self.x_axis * scale.x,
846            self.y_axis * scale.y,
847            self.z_axis * scale.z,
848        )
849    }
850
851    /// Divides a 3x3 matrix by a scalar.
852    #[inline]
853    #[must_use]
854    pub fn div_scalar(&self, rhs: f32) -> Self {
855        let rhs = Vec3A::splat(rhs);
856        Self::from_cols(
857            self.x_axis.div(rhs),
858            self.y_axis.div(rhs),
859            self.z_axis.div(rhs),
860        )
861    }
862
863    /// Returns a matrix containing the reciprocal `1.0/n` of each element of `self`.
864    #[inline]
865    #[must_use]
866    pub fn recip(&self) -> Self {
867        Self::from_cols(
868            self.x_axis.recip(),
869            self.y_axis.recip(),
870            self.z_axis.recip(),
871        )
872    }
873
874    /// Returns true if the absolute difference of all elements between `self` and `rhs`
875    /// is less than or equal to `max_abs_diff`.
876    ///
877    /// This can be used to compare if two matrices contain similar elements. It works best
878    /// when comparing with a known value. The `max_abs_diff` that should be used used
879    /// depends on the values being compared against.
880    ///
881    /// For more see
882    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
883    #[inline]
884    #[must_use]
885    pub fn abs_diff_eq(&self, rhs: Self, max_abs_diff: f32) -> bool {
886        self.x_axis.abs_diff_eq(rhs.x_axis, max_abs_diff)
887            && self.y_axis.abs_diff_eq(rhs.y_axis, max_abs_diff)
888            && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff)
889    }
890
891    /// Takes the absolute value of each element in `self`
892    #[inline]
893    #[must_use]
894    pub fn abs(&self) -> Self {
895        Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs())
896    }
897
898    #[cfg(feature = "f64")]
899    #[inline]
900    #[must_use]
901    pub fn as_dmat3(&self) -> DMat3 {
902        DMat3::from_cols(
903            self.x_axis.as_dvec3(),
904            self.y_axis.as_dvec3(),
905            self.z_axis.as_dvec3(),
906        )
907    }
908}
909
910impl Default for Mat3A {
911    #[inline]
912    fn default() -> Self {
913        Self::IDENTITY
914    }
915}
916
917impl Add for Mat3A {
918    type Output = Self;
919    #[inline]
920    fn add(self, rhs: Self) -> Self {
921        Self::from_cols(
922            self.x_axis.add(rhs.x_axis),
923            self.y_axis.add(rhs.y_axis),
924            self.z_axis.add(rhs.z_axis),
925        )
926    }
927}
928
929impl Add<&Self> for Mat3A {
930    type Output = Self;
931    #[inline]
932    fn add(self, rhs: &Self) -> Self {
933        self.add(*rhs)
934    }
935}
936
937impl Add<&Mat3A> for &Mat3A {
938    type Output = Mat3A;
939    #[inline]
940    fn add(self, rhs: &Mat3A) -> Mat3A {
941        (*self).add(*rhs)
942    }
943}
944
945impl Add<Mat3A> for &Mat3A {
946    type Output = Mat3A;
947    #[inline]
948    fn add(self, rhs: Mat3A) -> Mat3A {
949        (*self).add(rhs)
950    }
951}
952
953impl AddAssign for Mat3A {
954    #[inline]
955    fn add_assign(&mut self, rhs: Self) {
956        *self = self.add(rhs);
957    }
958}
959
960impl AddAssign<&Self> for Mat3A {
961    #[inline]
962    fn add_assign(&mut self, rhs: &Self) {
963        self.add_assign(*rhs);
964    }
965}
966
967impl Sub for Mat3A {
968    type Output = Self;
969    #[inline]
970    fn sub(self, rhs: Self) -> Self {
971        Self::from_cols(
972            self.x_axis.sub(rhs.x_axis),
973            self.y_axis.sub(rhs.y_axis),
974            self.z_axis.sub(rhs.z_axis),
975        )
976    }
977}
978
979impl Sub<&Self> for Mat3A {
980    type Output = Self;
981    #[inline]
982    fn sub(self, rhs: &Self) -> Self {
983        self.sub(*rhs)
984    }
985}
986
987impl Sub<&Mat3A> for &Mat3A {
988    type Output = Mat3A;
989    #[inline]
990    fn sub(self, rhs: &Mat3A) -> Mat3A {
991        (*self).sub(*rhs)
992    }
993}
994
995impl Sub<Mat3A> for &Mat3A {
996    type Output = Mat3A;
997    #[inline]
998    fn sub(self, rhs: Mat3A) -> Mat3A {
999        (*self).sub(rhs)
1000    }
1001}
1002
1003impl SubAssign for Mat3A {
1004    #[inline]
1005    fn sub_assign(&mut self, rhs: Self) {
1006        *self = self.sub(rhs);
1007    }
1008}
1009
1010impl SubAssign<&Self> for Mat3A {
1011    #[inline]
1012    fn sub_assign(&mut self, rhs: &Self) {
1013        self.sub_assign(*rhs);
1014    }
1015}
1016
1017impl Neg for Mat3A {
1018    type Output = Self;
1019    #[inline]
1020    fn neg(self) -> Self::Output {
1021        Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg())
1022    }
1023}
1024
1025impl Neg for &Mat3A {
1026    type Output = Mat3A;
1027    #[inline]
1028    fn neg(self) -> Mat3A {
1029        (*self).neg()
1030    }
1031}
1032
1033impl Mul for Mat3A {
1034    type Output = Self;
1035    #[inline]
1036    fn mul(self, rhs: Self) -> Self {
1037        Self::from_cols(
1038            self.mul(rhs.x_axis),
1039            self.mul(rhs.y_axis),
1040            self.mul(rhs.z_axis),
1041        )
1042    }
1043}
1044
1045impl Mul<&Self> for Mat3A {
1046    type Output = Self;
1047    #[inline]
1048    fn mul(self, rhs: &Self) -> Self {
1049        self.mul(*rhs)
1050    }
1051}
1052
1053impl Mul<&Mat3A> for &Mat3A {
1054    type Output = Mat3A;
1055    #[inline]
1056    fn mul(self, rhs: &Mat3A) -> Mat3A {
1057        (*self).mul(*rhs)
1058    }
1059}
1060
1061impl Mul<Mat3A> for &Mat3A {
1062    type Output = Mat3A;
1063    #[inline]
1064    fn mul(self, rhs: Mat3A) -> Mat3A {
1065        (*self).mul(rhs)
1066    }
1067}
1068
1069impl MulAssign for Mat3A {
1070    #[inline]
1071    fn mul_assign(&mut self, rhs: Self) {
1072        *self = self.mul(rhs);
1073    }
1074}
1075
1076impl MulAssign<&Self> for Mat3A {
1077    #[inline]
1078    fn mul_assign(&mut self, rhs: &Self) {
1079        self.mul_assign(*rhs);
1080    }
1081}
1082
1083impl Mul<Vec3A> for Mat3A {
1084    type Output = Vec3A;
1085    #[inline]
1086    fn mul(self, rhs: Vec3A) -> Self::Output {
1087        self.mul_vec3a(rhs)
1088    }
1089}
1090
1091impl Mul<&Vec3A> for Mat3A {
1092    type Output = Vec3A;
1093    #[inline]
1094    fn mul(self, rhs: &Vec3A) -> Vec3A {
1095        self.mul(*rhs)
1096    }
1097}
1098
1099impl Mul<&Vec3A> for &Mat3A {
1100    type Output = Vec3A;
1101    #[inline]
1102    fn mul(self, rhs: &Vec3A) -> Vec3A {
1103        (*self).mul(*rhs)
1104    }
1105}
1106
1107impl Mul<Vec3A> for &Mat3A {
1108    type Output = Vec3A;
1109    #[inline]
1110    fn mul(self, rhs: Vec3A) -> Vec3A {
1111        (*self).mul(rhs)
1112    }
1113}
1114
1115impl Mul<Mat3A> for f32 {
1116    type Output = Mat3A;
1117    #[inline]
1118    fn mul(self, rhs: Mat3A) -> Self::Output {
1119        rhs.mul_scalar(self)
1120    }
1121}
1122
1123impl Mul<&Mat3A> for f32 {
1124    type Output = Mat3A;
1125    #[inline]
1126    fn mul(self, rhs: &Mat3A) -> Mat3A {
1127        self.mul(*rhs)
1128    }
1129}
1130
1131impl Mul<&Mat3A> for &f32 {
1132    type Output = Mat3A;
1133    #[inline]
1134    fn mul(self, rhs: &Mat3A) -> Mat3A {
1135        (*self).mul(*rhs)
1136    }
1137}
1138
1139impl Mul<Mat3A> for &f32 {
1140    type Output = Mat3A;
1141    #[inline]
1142    fn mul(self, rhs: Mat3A) -> Mat3A {
1143        (*self).mul(rhs)
1144    }
1145}
1146
1147impl Mul<f32> for Mat3A {
1148    type Output = Self;
1149    #[inline]
1150    fn mul(self, rhs: f32) -> Self {
1151        self.mul_scalar(rhs)
1152    }
1153}
1154
1155impl Mul<&f32> for Mat3A {
1156    type Output = Self;
1157    #[inline]
1158    fn mul(self, rhs: &f32) -> Self {
1159        self.mul(*rhs)
1160    }
1161}
1162
1163impl Mul<&f32> for &Mat3A {
1164    type Output = Mat3A;
1165    #[inline]
1166    fn mul(self, rhs: &f32) -> Mat3A {
1167        (*self).mul(*rhs)
1168    }
1169}
1170
1171impl Mul<f32> for &Mat3A {
1172    type Output = Mat3A;
1173    #[inline]
1174    fn mul(self, rhs: f32) -> Mat3A {
1175        (*self).mul(rhs)
1176    }
1177}
1178
1179impl MulAssign<f32> for Mat3A {
1180    #[inline]
1181    fn mul_assign(&mut self, rhs: f32) {
1182        *self = self.mul(rhs);
1183    }
1184}
1185
1186impl MulAssign<&f32> for Mat3A {
1187    #[inline]
1188    fn mul_assign(&mut self, rhs: &f32) {
1189        self.mul_assign(*rhs);
1190    }
1191}
1192
1193impl Div<Mat3A> for f32 {
1194    type Output = Mat3A;
1195    #[inline]
1196    fn div(self, rhs: Mat3A) -> Self::Output {
1197        Mat3A::from_cols(
1198            self.div(rhs.x_axis),
1199            self.div(rhs.y_axis),
1200            self.div(rhs.z_axis),
1201        )
1202    }
1203}
1204
1205impl Div<&Mat3A> for f32 {
1206    type Output = Mat3A;
1207    #[inline]
1208    fn div(self, rhs: &Mat3A) -> Mat3A {
1209        self.div(*rhs)
1210    }
1211}
1212
1213impl Div<&Mat3A> for &f32 {
1214    type Output = Mat3A;
1215    #[inline]
1216    fn div(self, rhs: &Mat3A) -> Mat3A {
1217        (*self).div(*rhs)
1218    }
1219}
1220
1221impl Div<Mat3A> for &f32 {
1222    type Output = Mat3A;
1223    #[inline]
1224    fn div(self, rhs: Mat3A) -> Mat3A {
1225        (*self).div(rhs)
1226    }
1227}
1228
1229impl Div<f32> for Mat3A {
1230    type Output = Self;
1231    #[inline]
1232    fn div(self, rhs: f32) -> Self {
1233        self.div_scalar(rhs)
1234    }
1235}
1236
1237impl Div<&f32> for Mat3A {
1238    type Output = Self;
1239    #[inline]
1240    fn div(self, rhs: &f32) -> Self {
1241        self.div(*rhs)
1242    }
1243}
1244
1245impl Div<&f32> for &Mat3A {
1246    type Output = Mat3A;
1247    #[inline]
1248    fn div(self, rhs: &f32) -> Mat3A {
1249        (*self).div(*rhs)
1250    }
1251}
1252
1253impl Div<f32> for &Mat3A {
1254    type Output = Mat3A;
1255    #[inline]
1256    fn div(self, rhs: f32) -> Mat3A {
1257        (*self).div(rhs)
1258    }
1259}
1260
1261impl DivAssign<f32> for Mat3A {
1262    #[inline]
1263    fn div_assign(&mut self, rhs: f32) {
1264        *self = self.div(rhs);
1265    }
1266}
1267
1268impl DivAssign<&f32> for Mat3A {
1269    #[inline]
1270    fn div_assign(&mut self, rhs: &f32) {
1271        self.div_assign(*rhs);
1272    }
1273}
1274
1275impl Mul<Vec3> for Mat3A {
1276    type Output = Vec3;
1277    #[inline]
1278    fn mul(self, rhs: Vec3) -> Vec3 {
1279        self.mul_vec3a(rhs.into()).into()
1280    }
1281}
1282
1283impl Mul<&Vec3> for Mat3A {
1284    type Output = Vec3;
1285    #[inline]
1286    fn mul(self, rhs: &Vec3) -> Vec3 {
1287        self.mul(*rhs)
1288    }
1289}
1290
1291impl Mul<&Vec3> for &Mat3A {
1292    type Output = Vec3;
1293    #[inline]
1294    fn mul(self, rhs: &Vec3) -> Vec3 {
1295        (*self).mul(*rhs)
1296    }
1297}
1298
1299impl Mul<Vec3> for &Mat3A {
1300    type Output = Vec3;
1301    #[inline]
1302    fn mul(self, rhs: Vec3) -> Vec3 {
1303        (*self).mul(rhs)
1304    }
1305}
1306
1307impl From<Mat3> for Mat3A {
1308    #[inline]
1309    fn from(m: Mat3) -> Self {
1310        Self {
1311            x_axis: m.x_axis.into(),
1312            y_axis: m.y_axis.into(),
1313            z_axis: m.z_axis.into(),
1314        }
1315    }
1316}
1317
1318impl Sum<Self> for Mat3A {
1319    fn sum<I>(iter: I) -> Self
1320    where
1321        I: Iterator<Item = Self>,
1322    {
1323        iter.fold(Self::ZERO, Self::add)
1324    }
1325}
1326
1327impl<'a> Sum<&'a Self> for Mat3A {
1328    fn sum<I>(iter: I) -> Self
1329    where
1330        I: Iterator<Item = &'a Self>,
1331    {
1332        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1333    }
1334}
1335
1336impl Product for Mat3A {
1337    fn product<I>(iter: I) -> Self
1338    where
1339        I: Iterator<Item = Self>,
1340    {
1341        iter.fold(Self::IDENTITY, Self::mul)
1342    }
1343}
1344
1345impl<'a> Product<&'a Self> for Mat3A {
1346    fn product<I>(iter: I) -> Self
1347    where
1348        I: Iterator<Item = &'a Self>,
1349    {
1350        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1351    }
1352}
1353
1354impl PartialEq for Mat3A {
1355    #[inline]
1356    fn eq(&self, rhs: &Self) -> bool {
1357        self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis)
1358    }
1359}
1360
1361impl fmt::Debug for Mat3A {
1362    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1363        fmt.debug_struct(stringify!(Mat3A))
1364            .field("x_axis", &self.x_axis)
1365            .field("y_axis", &self.y_axis)
1366            .field("z_axis", &self.z_axis)
1367            .finish()
1368    }
1369}
1370
1371impl fmt::Display for Mat3A {
1372    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373        if let Some(p) = f.precision() {
1374            write!(
1375                f,
1376                "[{:.*}, {:.*}, {:.*}]",
1377                p, self.x_axis, p, self.y_axis, p, self.z_axis
1378            )
1379        } else {
1380            write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis)
1381        }
1382    }
1383}