Skip to main content

glam/f32/neon/
quat.rs

1// Generated from quat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    euler::{EulerRot, FromEuler, ToEuler},
5    f32::math,
6    neon::*,
7    Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8};
9
10#[cfg(feature = "f64")]
11use crate::DQuat;
12
13use core::arch::aarch64::*;
14
15use core::fmt;
16use core::iter::{Product, Sum};
17use core::ops::{
18    Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
19};
20
21#[cfg(feature = "zerocopy")]
22use zerocopy_derive::*;
23
24#[repr(C)]
25union UnionCast {
26    a: [f32; 4],
27    v: Quat,
28}
29
30/// Creates a quaternion from `x`, `y`, `z` and `w` values.
31///
32/// This should generally not be called manually unless you know what you are doing. Use
33/// one of the other constructors instead such as `identity` or `from_axis_angle`.
34#[inline]
35#[must_use]
36pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
37    Quat::from_xyzw(x, y, z, w)
38}
39
40/// A quaternion representing an orientation.
41///
42/// This quaternion is intended to be of unit length but may denormalize due to
43/// floating point "error creep" which can occur when successive quaternion
44/// operations are applied.
45///
46/// SIMD vector types are used for storage on supported platforms.
47///
48/// This type is 16 byte aligned.
49#[derive(Clone, Copy)]
50#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
51#[cfg_attr(
52    feature = "zerocopy",
53    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
54)]
55#[repr(transparent)]
56pub struct Quat(pub(crate) float32x4_t);
57
58impl Quat {
59    /// All zeros.
60    const ZERO: Self = Self::from_array([0.0; 4]);
61
62    /// The identity quaternion. Corresponds to no rotation.
63    pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
64
65    /// All NANs.
66    pub const NAN: Self = Self::from_array([f32::NAN; 4]);
67
68    /// Creates a new rotation quaternion.
69    ///
70    /// This should generally not be called manually unless you know what you are doing.
71    /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
72    ///
73    /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
74    ///
75    /// # Preconditions
76    ///
77    /// This function does not check if the input is normalized, it is up to the user to
78    /// provide normalized input or to normalized the resulting quaternion.
79    #[inline(always)]
80    #[must_use]
81    pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
82        unsafe { UnionCast { a: [x, y, z, w] }.v }
83    }
84
85    /// Creates a rotation quaternion from an array.
86    ///
87    /// # Preconditions
88    ///
89    /// This function does not check if the input is normalized, it is up to the user to
90    /// provide normalized input or to normalized the resulting quaternion.
91    #[inline]
92    #[must_use]
93    pub const fn from_array(a: [f32; 4]) -> Self {
94        Self::from_xyzw(a[0], a[1], a[2], a[3])
95    }
96
97    /// Creates a new rotation quaternion from a 4D vector.
98    ///
99    /// # Preconditions
100    ///
101    /// This function does not check if the input is normalized, it is up to the user to
102    /// provide normalized input or to normalized the resulting quaternion.
103    #[inline]
104    #[must_use]
105    pub const fn from_vec4(v: Vec4) -> Self {
106        Self(v.0)
107    }
108
109    /// Creates a rotation quaternion from a slice.
110    ///
111    /// # Preconditions
112    ///
113    /// This function does not check if the input is normalized, it is up to the user to
114    /// provide normalized input or to normalized the resulting quaternion.
115    ///
116    /// # Panics
117    ///
118    /// Panics if `slice` length is less than 4.
119    #[inline]
120    #[must_use]
121    pub fn from_slice(slice: &[f32]) -> Self {
122        assert!(slice.len() >= 4);
123        Self(unsafe { vld1q_f32(slice.as_ptr()) })
124    }
125
126    /// Writes the quaternion to an unaligned slice.
127    ///
128    /// # Panics
129    ///
130    /// Panics if `slice` length is less than 4.
131    #[inline]
132    pub fn write_to_slice(self, slice: &mut [f32]) {
133        assert!(slice.len() >= 4);
134        unsafe { vst1q_f32(slice.as_mut_ptr(), self.0) }
135    }
136
137    /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
138    ///
139    /// The axis must be a unit vector.
140    ///
141    /// # Panics
142    ///
143    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
144    #[inline]
145    #[must_use]
146    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
147        glam_assert!(axis.is_normalized());
148        let (s, c) = math::sin_cos(angle * 0.5);
149        let v = axis * s;
150        Self::from_xyzw(v.x, v.y, v.z, c)
151    }
152
153    /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
154    ///
155    /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
156    #[inline]
157    #[must_use]
158    pub fn from_scaled_axis(v: Vec3) -> Self {
159        let length = v.length();
160        if length == 0.0 {
161            Self::IDENTITY
162        } else {
163            Self::from_axis_angle(v / length, length)
164        }
165    }
166
167    /// Creates a quaternion from the `angle` (in radians) around the x axis.
168    #[inline]
169    #[must_use]
170    pub fn from_rotation_x(angle: f32) -> Self {
171        let (s, c) = math::sin_cos(angle * 0.5);
172        Self::from_xyzw(s, 0.0, 0.0, c)
173    }
174
175    /// Creates a quaternion from the `angle` (in radians) around the y axis.
176    #[inline]
177    #[must_use]
178    pub fn from_rotation_y(angle: f32) -> Self {
179        let (s, c) = math::sin_cos(angle * 0.5);
180        Self::from_xyzw(0.0, s, 0.0, c)
181    }
182
183    /// Creates a quaternion from the `angle` (in radians) around the z axis.
184    #[inline]
185    #[must_use]
186    pub fn from_rotation_z(angle: f32) -> Self {
187        let (s, c) = math::sin_cos(angle * 0.5);
188        Self::from_xyzw(0.0, 0.0, s, c)
189    }
190
191    /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
192    #[inline]
193    #[must_use]
194    pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
195        Self::from_euler_angles(euler, a, b, c)
196    }
197
198    /// From the columns of a 3x3 rotation matrix.
199    ///
200    /// Note if the input axes contain scales, shears, or other non-rotation transformations then
201    /// the output of this function is ill-defined.
202    ///
203    /// # Panics
204    ///
205    /// Will panic if any axis is not normalized when `glam_assert` is enabled.
206    #[inline]
207    #[must_use]
208    pub fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
209        glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized());
210        // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix`
211        let (m00, m01, m02) = x_axis.into();
212        let (m10, m11, m12) = y_axis.into();
213        let (m20, m21, m22) = z_axis.into();
214        if m22 <= 0.0 {
215            // x^2 + y^2 >= z^2 + w^2
216            let dif10 = m11 - m00;
217            let omm22 = 1.0 - m22;
218            if dif10 <= 0.0 {
219                // x^2 >= y^2
220                let four_xsq = omm22 - dif10;
221                let inv4x = 0.5 / math::sqrt(four_xsq);
222                Self::from_xyzw(
223                    four_xsq * inv4x,
224                    (m01 + m10) * inv4x,
225                    (m02 + m20) * inv4x,
226                    (m12 - m21) * inv4x,
227                )
228            } else {
229                // y^2 >= x^2
230                let four_ysq = omm22 + dif10;
231                let inv4y = 0.5 / math::sqrt(four_ysq);
232                Self::from_xyzw(
233                    (m01 + m10) * inv4y,
234                    four_ysq * inv4y,
235                    (m12 + m21) * inv4y,
236                    (m20 - m02) * inv4y,
237                )
238            }
239        } else {
240            // z^2 + w^2 >= x^2 + y^2
241            let sum10 = m11 + m00;
242            let opm22 = 1.0 + m22;
243            if sum10 <= 0.0 {
244                // z^2 >= w^2
245                let four_zsq = opm22 - sum10;
246                let inv4z = 0.5 / math::sqrt(four_zsq);
247                Self::from_xyzw(
248                    (m02 + m20) * inv4z,
249                    (m12 + m21) * inv4z,
250                    four_zsq * inv4z,
251                    (m01 - m10) * inv4z,
252                )
253            } else {
254                // w^2 >= z^2
255                let four_wsq = opm22 + sum10;
256                let inv4w = 0.5 / math::sqrt(four_wsq);
257                Self::from_xyzw(
258                    (m12 - m21) * inv4w,
259                    (m20 - m02) * inv4w,
260                    (m01 - m10) * inv4w,
261                    four_wsq * inv4w,
262                )
263            }
264        }
265    }
266
267    /// Creates a quaternion from a 3x3 rotation matrix.
268    ///
269    /// Note if the input matrix contain scales, shears, or other non-rotation transformations then
270    /// the resulting quaternion will be ill-defined.
271    ///
272    /// # Panics
273    ///
274    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
275    #[inline]
276    #[must_use]
277    pub fn from_mat3(mat: &Mat3) -> Self {
278        Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
279    }
280
281    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
282    ///
283    /// Note if the input matrix contain scales, shears, or other non-rotation transformations then
284    /// the resulting quaternion will be ill-defined.
285    ///
286    /// # Panics
287    ///
288    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
289    #[inline]
290    #[must_use]
291    pub fn from_mat3a(mat: &Mat3A) -> Self {
292        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
293    }
294
295    /// Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.
296    ///
297    /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
298    /// then the resulting quaternion will be ill-defined.
299    ///
300    /// # Panics
301    ///
302    /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
303    /// `glam_assert` is enabled.
304    #[inline]
305    #[must_use]
306    pub fn from_mat4(mat: &Mat4) -> Self {
307        Self::from_rotation_axes(
308            mat.x_axis.truncate(),
309            mat.y_axis.truncate(),
310            mat.z_axis.truncate(),
311        )
312    }
313
314    /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
315    /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
316    ///
317    /// The inputs must be unit vectors.
318    ///
319    /// `from_rotation_arc(from, to) * from ≈ to`.
320    ///
321    /// For near-singular cases (from≈to and from≈-to) the current implementation
322    /// is only accurate to about 0.001 (for `f32`).
323    ///
324    /// # Panics
325    ///
326    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
327    #[must_use]
328    pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
329        glam_assert!(from.is_normalized());
330        glam_assert!(to.is_normalized());
331
332        const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON;
333        let dot = from.dot(to);
334        if dot > ONE_MINUS_EPS {
335            // 0° singularity: from ≈ to
336            Self::IDENTITY
337        } else if dot < -ONE_MINUS_EPS {
338            // 180° singularity: from ≈ -to
339            use core::f32::consts::PI; // half a turn = 𝛕/2 = 180°
340            Self::from_axis_angle(from.any_orthonormal_vector(), PI)
341        } else {
342            let c = from.cross(to);
343            Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
344        }
345    }
346
347    /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
348    /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
349    ///
350    /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
351    /// degrees.
352    ///
353    /// The inputs must be unit vectors.
354    ///
355    /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
356    ///
357    /// # Panics
358    ///
359    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
360    #[inline]
361    #[must_use]
362    pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
363        if from.dot(to) < 0.0 {
364            Self::from_rotation_arc(from, -to)
365        } else {
366            Self::from_rotation_arc(from, to)
367        }
368    }
369
370    /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
371    /// around the z axis. Will rotate at most 180 degrees.
372    ///
373    /// The inputs must be unit vectors.
374    ///
375    /// `from_rotation_arc_2d(from, to) * from ≈ to`.
376    ///
377    /// For near-singular cases (from≈to and from≈-to) the current implementation
378    /// is only accurate to about 0.001 (for `f32`).
379    ///
380    /// # Panics
381    ///
382    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
383    #[must_use]
384    pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
385        glam_assert!(from.is_normalized());
386        glam_assert!(to.is_normalized());
387
388        const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON;
389        let dot = from.dot(to);
390        if dot > ONE_MINUS_EPSILON {
391            // 0° singularity: from ≈ to
392            Self::IDENTITY
393        } else if dot < -ONE_MINUS_EPSILON {
394            // 180° singularity: from ≈ -to
395            const COS_FRAC_PI_2: f32 = 0.0;
396            const SIN_FRAC_PI_2: f32 = 1.0;
397            // rotation around z by PI radians
398            Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
399        } else {
400            // vector3 cross where z=0
401            let z = from.x * to.y - to.x * from.y;
402            let w = 1.0 + dot;
403            // calculate length with x=0 and y=0 to normalize
404            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
405            Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
406        }
407    }
408
409    /// Creates a quaterion rotation from a facing direction and an up direction.
410    ///
411    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
412    ///
413    /// # Panics
414    ///
415    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
416    #[deprecated(
417        since = "0.33.1",
418        note = "use the `glam::camera::lh::view::look_to_quat` function instead"
419    )]
420    #[inline]
421    #[must_use]
422    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
423        #[allow(deprecated)]
424        Self::look_to_rh(-dir, up)
425    }
426
427    /// Creates a quaterion rotation from facing direction and an up direction.
428    ///
429    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
430    ///
431    /// # Panics
432    ///
433    /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled.
434    #[deprecated(
435        since = "0.33.1",
436        note = "use the `glam::camera::rh::view::look_to_quat` function instead"
437    )]
438    #[inline]
439    #[must_use]
440    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
441        glam_assert!(dir.is_normalized());
442        glam_assert!(up.is_normalized());
443        let f = dir;
444        let s = f.cross(up).normalize();
445        let u = s.cross(f);
446
447        Self::from_rotation_axes(
448            Vec3::new(s.x, u.x, -f.x),
449            Vec3::new(s.y, u.y, -f.y),
450            Vec3::new(s.z, u.z, -f.z),
451        )
452    }
453
454    /// Creates a quaternion rotation from a camera position, a focal point, and an up
455    /// direction.
456    ///
457    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
458    ///
459    /// # Panics
460    ///
461    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
462    #[deprecated(
463        since = "0.33.1",
464        note = "use the `glam::camera::lh::view::look_at_quat` function instead"
465    )]
466    #[inline]
467    #[must_use]
468    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
469        #[allow(deprecated)]
470        Self::look_to_lh(center.sub(eye).normalize(), up)
471    }
472
473    /// Creates a quaternion rotation using a camera position, an up direction, and a focal
474    /// point.
475    ///
476    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
477    ///
478    /// # Panics
479    ///
480    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
481    #[deprecated(
482        since = "0.33.1",
483        note = "use the `glam::camera::rh::view::look_at_quat` function instead"
484    )]
485    #[inline]
486    #[must_use]
487    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
488        #[allow(deprecated)]
489        Self::look_to_rh(center.sub(eye).normalize(), up)
490    }
491
492    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
493    #[inline]
494    #[must_use]
495    pub fn to_axis_angle(self) -> (Vec3, f32) {
496        const EPSILON: f32 = 1.0e-8;
497        let v = Vec3::new(self.x, self.y, self.z);
498        let length = v.length();
499        if length >= EPSILON {
500            let angle = 2.0 * math::atan2(length, self.w);
501            let axis = v / length;
502            (axis, angle)
503        } else {
504            (Vec3::X, 0.0)
505        }
506    }
507
508    /// Returns the rotation axis scaled by the rotation in radians.
509    #[inline]
510    #[must_use]
511    pub fn to_scaled_axis(self) -> Vec3 {
512        let (axis, angle) = self.to_axis_angle();
513        axis * angle
514    }
515
516    /// Returns the rotation angles for the given euler rotation sequence.
517    #[inline]
518    #[must_use]
519    pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) {
520        self.to_euler_angles(order)
521    }
522
523    /// `[x, y, z, w]`
524    #[inline]
525    #[must_use]
526    pub fn to_array(self) -> [f32; 4] {
527        [self.x, self.y, self.z, self.w]
528    }
529
530    /// Returns the vector part of the quaternion.
531    #[inline]
532    #[must_use]
533    pub fn xyz(self) -> Vec3 {
534        Vec3::new(self.x, self.y, self.z)
535    }
536
537    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
538    /// conjugate is also the inverse.
539    #[inline]
540    #[must_use]
541    pub fn conjugate(self) -> Self {
542        const SIGN: float32x4_t = f32x4_from_array([-1.0, -1.0, -1.0, 1.0]);
543        Self(unsafe { vmulq_f32(self.0, SIGN) })
544    }
545
546    /// Returns the inverse of a normalized quaternion.
547    ///
548    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
549    /// Because `self` is assumed to already be unit length this method *does not* normalize
550    /// before returning the conjugate.
551    ///
552    /// # Panics
553    ///
554    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
555    #[inline]
556    #[must_use]
557    pub fn inverse(self) -> Self {
558        glam_assert!(self.is_normalized());
559        self.conjugate()
560    }
561
562    /// Computes the dot product of `self` and `rhs`. The dot product is
563    /// equal to the cosine of the angle between two quaternion rotations.
564    #[inline]
565    #[must_use]
566    pub fn dot(self, rhs: Self) -> f32 {
567        Vec4::from(self).dot(Vec4::from(rhs))
568    }
569
570    /// Computes the length of `self`.
571    #[doc(alias = "magnitude")]
572    #[inline]
573    #[must_use]
574    pub fn length(self) -> f32 {
575        Vec4::from(self).length()
576    }
577
578    /// Computes the squared length of `self`.
579    ///
580    /// This is generally faster than `length()` as it avoids a square
581    /// root operation.
582    #[doc(alias = "magnitude2")]
583    #[inline]
584    #[must_use]
585    pub fn length_squared(self) -> f32 {
586        Vec4::from(self).length_squared()
587    }
588
589    /// Computes `1.0 / length()`.
590    ///
591    /// For valid results, `self` must _not_ be of length zero.
592    #[inline]
593    #[must_use]
594    pub fn length_recip(self) -> f32 {
595        Vec4::from(self).length_recip()
596    }
597
598    /// Returns `self` normalized to length 1.0.
599    ///
600    /// For valid results, `self` must _not_ be of length zero.
601    ///
602    /// Panics
603    ///
604    /// Will panic if `self` is zero length when `glam_assert` is enabled.
605    #[inline]
606    #[must_use]
607    pub fn normalize(self) -> Self {
608        Self::from_vec4(Vec4::from(self).normalize())
609    }
610
611    /// Returns `true` if, and only if, all elements are finite.
612    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
613    #[inline]
614    #[must_use]
615    pub fn is_finite(self) -> bool {
616        Vec4::from(self).is_finite()
617    }
618
619    /// Returns `true` if any elements are `NAN`.
620    #[inline]
621    #[must_use]
622    pub fn is_nan(self) -> bool {
623        Vec4::from(self).is_nan()
624    }
625
626    /// Returns whether `self` of length `1.0` or not.
627    ///
628    /// Uses a precision threshold of `1e-6`.
629    #[inline]
630    #[must_use]
631    pub fn is_normalized(self) -> bool {
632        Vec4::from(self).is_normalized()
633    }
634
635    #[inline]
636    #[must_use]
637    pub fn is_near_identity(self) -> bool {
638        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
639        // Because of floating point precision, we cannot represent very small rotations.
640        // The closest f32 to 1.0 that is not 1.0 itself yields:
641        // 0.99999994.acos() * 2.0  = 0.000690533954 rad
642        //
643        // An error threshold of 1.e-6 is used by default.
644        // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
645        // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
646        //
647        // We don't really care about the angle value itself, only if it's close to 0.
648        // This will happen whenever quat.w is close to 1.0.
649        // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
650        // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
651        // the shortest path.
652        //
653        // For f64 we're using a threshhold of
654        // (1.0 - 1e-14).acos() * 2.0
655        const THRESHOLD_ANGLE: f32 = 0.002_847_144_6;
656        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
657        positive_w_angle < THRESHOLD_ANGLE
658    }
659
660    /// Returns the angle (in radians) for the minimal rotation
661    /// for transforming this quaternion into another.
662    ///
663    /// Both quaternions must be normalized.
664    ///
665    /// # Panics
666    ///
667    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
668    #[inline]
669    #[must_use]
670    pub fn angle_between(self, rhs: Self) -> f32 {
671        glam_assert!(self.is_normalized() && rhs.is_normalized());
672        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
673    }
674
675    /// Rotates towards `rhs` up to `max_angle` (in radians).
676    ///
677    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
678    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
679    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
680    ///
681    /// Both quaternions must be normalized.
682    ///
683    /// # Panics
684    ///
685    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
686    #[inline]
687    #[must_use]
688    pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self {
689        glam_assert!(self.is_normalized() && rhs.is_normalized());
690        let angle = self.angle_between(rhs);
691        if angle <= 1e-4 {
692            return rhs;
693        }
694        let s = (max_angle / angle).clamp(-1.0, 1.0);
695        self.slerp(rhs, s)
696    }
697
698    /// Returns true if the absolute difference of all elements between `self` and `rhs`
699    /// is less than or equal to `max_abs_diff`.
700    ///
701    /// This can be used to compare if two quaternions contain similar elements. It works
702    /// best when comparing with a known value. The `max_abs_diff` that should be used used
703    /// depends on the values being compared against.
704    ///
705    /// For more see
706    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
707    #[inline]
708    #[must_use]
709    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
710        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
711    }
712
713    #[inline(always)]
714    #[must_use]
715    fn lerp_impl(self, end: Self, s: f32) -> Self {
716        (self * (1.0 - s) + end * s).normalize()
717    }
718
719    /// Performs a linear interpolation between `self` and `rhs` based on
720    /// the value `s`.
721    ///
722    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
723    /// is `1.0`, the result will be equal to `rhs`.
724    ///
725    /// # Panics
726    ///
727    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
728    #[doc(alias = "mix")]
729    #[inline]
730    #[must_use]
731    pub fn lerp(self, end: Self, s: f32) -> Self {
732        glam_assert!(self.is_normalized());
733        glam_assert!(end.is_normalized());
734
735        const NEG_ZERO: float32x4_t = f32x4_from_array([-0.0; 4]);
736        unsafe {
737            let dot = dot4_into_f32x4(self.0, end.0);
738            // Calculate the bias, if the dot product is positive or zero, there is no bias
739            // but if it is negative, we want to flip the 'end' rotation XYZW components
740            let bias = vandq_u32(vreinterpretq_u32_f32(dot), vreinterpretq_u32_f32(NEG_ZERO));
741            self.lerp_impl(
742                Self(vreinterpretq_f32_u32(veorq_u32(
743                    vreinterpretq_u32_f32(end.0),
744                    bias,
745                ))),
746                s,
747            )
748        }
749    }
750
751    #[inline(always)]
752    #[must_use]
753    fn slerp_impl(self, end: Self, dot: f32, s: f32) -> Self {
754        let theta = math::acos_approx(dot);
755
756        let scale1 = math::sin(theta * (1.0 - s));
757        let scale2 = math::sin(theta * s);
758        let theta_sin = math::sin(theta);
759        ((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
760    }
761
762    /// Performs a spherical linear interpolation between `self` and `end`
763    /// based on the value `s`.
764    ///
765    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
766    /// is `1.0`, the result will be equal to `end`.
767    ///
768    /// # Panics
769    ///
770    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
771    #[inline]
772    #[must_use]
773    pub fn slerp(self, mut end: Self, s: f32) -> Self {
774        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
775        glam_assert!(self.is_normalized());
776        glam_assert!(end.is_normalized());
777
778        // Note that a rotation can be represented by two quaternions: `q` and
779        // `-q`. The slerp path between `q` and `end` will be different from the
780        // path between `-q` and `end`. One path will take the long way around and
781        // one will take the short way. In order to correct for this, the `dot`
782        // product between `self` and `end` should be positive. If the `dot`
783        // product is negative, slerp between `self` and `-end`.
784        let mut dot = self.dot(end);
785        if dot < 0.0 {
786            end = -end;
787            dot = -dot;
788        }
789
790        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
791        if dot > DOT_THRESHOLD {
792            // if above threshold perform linear interpolation to avoid divide by zero
793            self.lerp_impl(end, s)
794        } else {
795            self.slerp_impl(end, dot, s)
796        }
797    }
798
799    /// Performs a spherical linear interpolation between `self` and `end` based on the value `s`,
800    /// preserving the rotation direction.
801    ///
802    /// When `s` is `0.0`, the result will be equal to `self`.  When `s` is `1.0`, the result will
803    /// be equal to `end`.
804    ///
805    /// When the dot product of `self` and `end` is negative, the standard [`slerp`](Self::slerp)
806    /// will flip the end quaternion to take the shortest path, while this method will take the
807    /// longer arc. This is useful when the intended rotation direction must be preserved.
808    ///
809    /// # Panics
810    ///
811    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
812    #[inline]
813    #[must_use]
814    pub fn slerp_long(self, end: Self, s: f32) -> Self {
815        glam_assert!(self.is_normalized());
816        glam_assert!(end.is_normalized());
817
818        let dot = self.dot(end);
819
820        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
821        if dot.abs() > DOT_THRESHOLD {
822            // if above threshold perform linear interpolation to avoid divide by zero
823            self.lerp_impl(end, s)
824        } else {
825            self.slerp_impl(end, dot, s)
826        }
827    }
828
829    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
830    ///
831    /// # Panics
832    ///
833    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
834    #[inline]
835    #[must_use]
836    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
837        glam_assert!(self.is_normalized());
838
839        self.mul_vec3a(rhs.into()).into()
840    }
841
842    /// Multiplies two quaternions. If they each represent a rotation, the result will
843    /// represent the combined rotation.
844    ///
845    /// Note that due to floating point rounding the result may not be perfectly normalized.
846    ///
847    /// # Panics
848    ///
849    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
850    #[inline]
851    #[must_use]
852    pub fn mul_quat(self, rhs: Self) -> Self {
853        unsafe {
854            let lhs = self.0;
855            let rhs = rhs.0;
856
857            const CONTROL_WZYX: float32x4_t = f32x4_from_array([1.0, -1.0, 1.0, -1.0]);
858            const CONTROL_ZWXY: float32x4_t = f32x4_from_array([1.0, 1.0, -1.0, -1.0]);
859            const CONTROL_YXWZ: float32x4_t = f32x4_from_array([-1.0, 1.0, 1.0, -1.0]);
860
861            let r_xxxx = vdupq_laneq_f32(lhs, 0);
862            let r_yyyy = vdupq_laneq_f32(lhs, 1);
863            let r_zzzz = vdupq_laneq_f32(lhs, 2);
864            let r_wwww = vdupq_laneq_f32(lhs, 3);
865
866            let lxrw_lyrw_lzrw_lwrw = vmulq_f32(r_wwww, rhs);
867            //let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]);
868            let l_wzyx = vrev64q_f32(rhs);
869            let l_wzyx = vextq_f32(l_wzyx, l_wzyx, 2);
870
871            let lwrx_lzrx_lyrx_lxrx = vmulq_f32(r_xxxx, l_wzyx);
872            //let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]);
873            let l_zwxy = vrev64q_f32(l_wzyx);
874
875            let lwrx_nlzrx_lyrx_nlxrx = vmulq_f32(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
876
877            let lzry_lwry_lxry_lyry = vmulq_f32(r_yyyy, l_zwxy);
878            // let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]);
879            let l_yxwz = vrev64q_f32(l_zwxy);
880            let l_yxwz = vextq_f32(l_yxwz, l_yxwz, 2);
881
882            let lzry_lwry_nlxry_nlyry = vmulq_f32(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
883
884            let lyrz_lxrz_lwrz_lzrz = vmulq_f32(r_zzzz, l_yxwz);
885            let result0 = vaddq_f32(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
886
887            let nlyrz_lxrz_lwrz_wlzrz = vmulq_f32(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
888            let result1 = vaddq_f32(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
889            Self(vaddq_f32(result0, result1))
890        }
891    }
892
893    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
894    ///
895    /// Note if the input affine matrix contain scales, shears, or other non-rotation
896    /// transformations then the resulting quaternion will be ill-defined.
897    ///
898    /// # Panics
899    ///
900    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
901    /// enabled.
902    #[inline]
903    #[must_use]
904    pub fn from_affine3(a: &crate::Affine3) -> Self {
905        Self::from_rotation_axes(a.matrix3.x_axis, a.matrix3.y_axis, a.matrix3.z_axis)
906    }
907
908    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
909    ///
910    /// Note if the input affine matrix contain scales, shears, or other non-rotation
911    /// transformations then the resulting quaternion will be ill-defined.
912    ///
913    /// # Panics
914    ///
915    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
916    /// enabled.
917    #[inline]
918    #[must_use]
919    pub fn from_affine3a(a: &crate::Affine3A) -> Self {
920        Self::from_rotation_axes(
921            a.matrix3.x_axis.into(),
922            a.matrix3.y_axis.into(),
923            a.matrix3.z_axis.into(),
924        )
925    }
926
927    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
928    #[inline]
929    #[must_use]
930    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
931        unsafe {
932            let w = self.w;
933            let b = Vec3A::from(self.0);
934            let b2 = b.length_squared();
935            Vec3A(vaddq_f32(
936                vaddq_f32(
937                    vmulq_n_f32(rhs.0, (w * w) - b2),
938                    vmulq_n_f32(b.0, rhs.dot(b) * 2.0),
939                ),
940                vmulq_n_f32(b.cross(rhs).0, w * 2.0),
941            ))
942        }
943    }
944
945    #[cfg(feature = "f64")]
946    #[inline]
947    #[must_use]
948    pub fn as_dquat(self) -> DQuat {
949        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
950    }
951}
952
953impl fmt::Debug for Quat {
954    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
955        fmt.debug_tuple(stringify!(Quat))
956            .field(&self.x)
957            .field(&self.y)
958            .field(&self.z)
959            .field(&self.w)
960            .finish()
961    }
962}
963
964impl fmt::Display for Quat {
965    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
966        if let Some(p) = f.precision() {
967            write!(
968                f,
969                "[{:.*}, {:.*}, {:.*}, {:.*}]",
970                p, self.x, p, self.y, p, self.z, p, self.w
971            )
972        } else {
973            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
974        }
975    }
976}
977
978impl Add for Quat {
979    type Output = Self;
980    /// Adds two quaternions.
981    ///
982    /// The sum is not guaranteed to be normalized.
983    ///
984    /// Note that addition is not the same as combining the rotations represented by the
985    /// two quaternions! That corresponds to multiplication.
986    #[inline]
987    fn add(self, rhs: Self) -> Self {
988        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
989    }
990}
991
992impl Add<&Self> for Quat {
993    type Output = Self;
994    #[inline]
995    fn add(self, rhs: &Self) -> Self {
996        self.add(*rhs)
997    }
998}
999
1000impl Add<&Quat> for &Quat {
1001    type Output = Quat;
1002    #[inline]
1003    fn add(self, rhs: &Quat) -> Quat {
1004        (*self).add(*rhs)
1005    }
1006}
1007
1008impl Add<Quat> for &Quat {
1009    type Output = Quat;
1010    #[inline]
1011    fn add(self, rhs: Quat) -> Quat {
1012        (*self).add(rhs)
1013    }
1014}
1015
1016impl AddAssign for Quat {
1017    #[inline]
1018    fn add_assign(&mut self, rhs: Self) {
1019        *self = self.add(rhs);
1020    }
1021}
1022
1023impl AddAssign<&Self> for Quat {
1024    #[inline]
1025    fn add_assign(&mut self, rhs: &Self) {
1026        self.add_assign(*rhs);
1027    }
1028}
1029
1030impl Sub for Quat {
1031    type Output = Self;
1032    /// Subtracts the `rhs` quaternion from `self`.
1033    ///
1034    /// The difference is not guaranteed to be normalized.
1035    #[inline]
1036    fn sub(self, rhs: Self) -> Self {
1037        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
1038    }
1039}
1040
1041impl Sub<&Self> for Quat {
1042    type Output = Self;
1043    #[inline]
1044    fn sub(self, rhs: &Self) -> Self {
1045        self.sub(*rhs)
1046    }
1047}
1048
1049impl Sub<&Quat> for &Quat {
1050    type Output = Quat;
1051    #[inline]
1052    fn sub(self, rhs: &Quat) -> Quat {
1053        (*self).sub(*rhs)
1054    }
1055}
1056
1057impl Sub<Quat> for &Quat {
1058    type Output = Quat;
1059    #[inline]
1060    fn sub(self, rhs: Quat) -> Quat {
1061        (*self).sub(rhs)
1062    }
1063}
1064
1065impl SubAssign for Quat {
1066    #[inline]
1067    fn sub_assign(&mut self, rhs: Self) {
1068        *self = self.sub(rhs);
1069    }
1070}
1071
1072impl SubAssign<&Self> for Quat {
1073    #[inline]
1074    fn sub_assign(&mut self, rhs: &Self) {
1075        self.sub_assign(*rhs);
1076    }
1077}
1078
1079impl Mul<f32> for Quat {
1080    type Output = Self;
1081    /// Multiplies a quaternion by a scalar value.
1082    ///
1083    /// The product is not guaranteed to be normalized.
1084    #[inline]
1085    fn mul(self, rhs: f32) -> Self {
1086        Self::from_vec4(Vec4::from(self) * rhs)
1087    }
1088}
1089
1090impl Mul<&f32> for Quat {
1091    type Output = Self;
1092    #[inline]
1093    fn mul(self, rhs: &f32) -> Self {
1094        self.mul(*rhs)
1095    }
1096}
1097
1098impl Mul<&f32> for &Quat {
1099    type Output = Quat;
1100    #[inline]
1101    fn mul(self, rhs: &f32) -> Quat {
1102        (*self).mul(*rhs)
1103    }
1104}
1105
1106impl Mul<f32> for &Quat {
1107    type Output = Quat;
1108    #[inline]
1109    fn mul(self, rhs: f32) -> Quat {
1110        (*self).mul(rhs)
1111    }
1112}
1113
1114impl MulAssign<f32> for Quat {
1115    #[inline]
1116    fn mul_assign(&mut self, rhs: f32) {
1117        *self = self.mul(rhs);
1118    }
1119}
1120
1121impl MulAssign<&f32> for Quat {
1122    #[inline]
1123    fn mul_assign(&mut self, rhs: &f32) {
1124        self.mul_assign(*rhs);
1125    }
1126}
1127
1128impl Div<f32> for Quat {
1129    type Output = Self;
1130    /// Divides a quaternion by a scalar value.
1131    /// The quotient is not guaranteed to be normalized.
1132    #[inline]
1133    fn div(self, rhs: f32) -> Self {
1134        Self::from_vec4(Vec4::from(self) / rhs)
1135    }
1136}
1137
1138impl Div<&f32> for Quat {
1139    type Output = Self;
1140    #[inline]
1141    fn div(self, rhs: &f32) -> Self {
1142        self.div(*rhs)
1143    }
1144}
1145
1146impl Div<&f32> for &Quat {
1147    type Output = Quat;
1148    #[inline]
1149    fn div(self, rhs: &f32) -> Quat {
1150        (*self).div(*rhs)
1151    }
1152}
1153
1154impl Div<f32> for &Quat {
1155    type Output = Quat;
1156    #[inline]
1157    fn div(self, rhs: f32) -> Quat {
1158        (*self).div(rhs)
1159    }
1160}
1161
1162impl DivAssign<f32> for Quat {
1163    #[inline]
1164    fn div_assign(&mut self, rhs: f32) {
1165        *self = self.div(rhs);
1166    }
1167}
1168
1169impl DivAssign<&f32> for Quat {
1170    #[inline]
1171    fn div_assign(&mut self, rhs: &f32) {
1172        self.div_assign(*rhs);
1173    }
1174}
1175
1176impl Mul for Quat {
1177    type Output = Self;
1178    /// Multiplies two quaternions. If they each represent a rotation, the result will
1179    /// represent the combined rotation.
1180    ///
1181    /// Note that due to floating point rounding the result may not be perfectly
1182    /// normalized.
1183    ///
1184    /// # Panics
1185    ///
1186    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1187    #[inline]
1188    fn mul(self, rhs: Self) -> Self {
1189        self.mul_quat(rhs)
1190    }
1191}
1192
1193impl Mul<&Self> for Quat {
1194    type Output = Self;
1195    #[inline]
1196    fn mul(self, rhs: &Self) -> Self {
1197        self.mul(*rhs)
1198    }
1199}
1200
1201impl Mul<&Quat> for &Quat {
1202    type Output = Quat;
1203    #[inline]
1204    fn mul(self, rhs: &Quat) -> Quat {
1205        (*self).mul(*rhs)
1206    }
1207}
1208
1209impl Mul<Quat> for &Quat {
1210    type Output = Quat;
1211    #[inline]
1212    fn mul(self, rhs: Quat) -> Quat {
1213        (*self).mul(rhs)
1214    }
1215}
1216
1217impl MulAssign for Quat {
1218    #[inline]
1219    fn mul_assign(&mut self, rhs: Self) {
1220        *self = self.mul(rhs);
1221    }
1222}
1223
1224impl MulAssign<&Self> for Quat {
1225    #[inline]
1226    fn mul_assign(&mut self, rhs: &Self) {
1227        self.mul_assign(*rhs);
1228    }
1229}
1230
1231impl Mul<Vec3> for Quat {
1232    type Output = Vec3;
1233    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1234    ///
1235    /// # Panics
1236    ///
1237    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1238    #[inline]
1239    fn mul(self, rhs: Vec3) -> Self::Output {
1240        self.mul_vec3(rhs)
1241    }
1242}
1243
1244impl Mul<&Vec3> for Quat {
1245    type Output = Vec3;
1246    #[inline]
1247    fn mul(self, rhs: &Vec3) -> Vec3 {
1248        self.mul(*rhs)
1249    }
1250}
1251
1252impl Mul<&Vec3> for &Quat {
1253    type Output = Vec3;
1254    #[inline]
1255    fn mul(self, rhs: &Vec3) -> Vec3 {
1256        (*self).mul(*rhs)
1257    }
1258}
1259
1260impl Mul<Vec3> for &Quat {
1261    type Output = Vec3;
1262    #[inline]
1263    fn mul(self, rhs: Vec3) -> Vec3 {
1264        (*self).mul(rhs)
1265    }
1266}
1267
1268impl Mul<Vec3A> for Quat {
1269    type Output = Vec3A;
1270    #[inline]
1271    fn mul(self, rhs: Vec3A) -> Self::Output {
1272        self.mul_vec3a(rhs)
1273    }
1274}
1275
1276impl Mul<&Vec3A> for Quat {
1277    type Output = Vec3A;
1278    #[inline]
1279    fn mul(self, rhs: &Vec3A) -> Vec3A {
1280        self.mul(*rhs)
1281    }
1282}
1283
1284impl Mul<&Vec3A> for &Quat {
1285    type Output = Vec3A;
1286    #[inline]
1287    fn mul(self, rhs: &Vec3A) -> Vec3A {
1288        (*self).mul(*rhs)
1289    }
1290}
1291
1292impl Mul<Vec3A> for &Quat {
1293    type Output = Vec3A;
1294    #[inline]
1295    fn mul(self, rhs: Vec3A) -> Vec3A {
1296        (*self).mul(rhs)
1297    }
1298}
1299
1300impl Neg for Quat {
1301    type Output = Self;
1302    #[inline]
1303    fn neg(self) -> Self {
1304        self * -1.0
1305    }
1306}
1307
1308impl Neg for &Quat {
1309    type Output = Quat;
1310    #[inline]
1311    fn neg(self) -> Quat {
1312        (*self).neg()
1313    }
1314}
1315
1316impl Default for Quat {
1317    #[inline]
1318    fn default() -> Self {
1319        Self::IDENTITY
1320    }
1321}
1322
1323impl PartialEq for Quat {
1324    #[inline]
1325    fn eq(&self, rhs: &Self) -> bool {
1326        Vec4::from(*self).eq(&Vec4::from(*rhs))
1327    }
1328}
1329
1330impl AsRef<[f32; 4]> for Quat {
1331    #[inline]
1332    fn as_ref(&self) -> &[f32; 4] {
1333        unsafe { &*(self as *const Self as *const [f32; 4]) }
1334    }
1335}
1336
1337impl Sum<Self> for Quat {
1338    fn sum<I>(iter: I) -> Self
1339    where
1340        I: Iterator<Item = Self>,
1341    {
1342        iter.fold(Self::ZERO, Self::add)
1343    }
1344}
1345
1346impl<'a> Sum<&'a Self> for Quat {
1347    fn sum<I>(iter: I) -> Self
1348    where
1349        I: Iterator<Item = &'a Self>,
1350    {
1351        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1352    }
1353}
1354
1355impl Product for Quat {
1356    fn product<I>(iter: I) -> Self
1357    where
1358        I: Iterator<Item = Self>,
1359    {
1360        iter.fold(Self::IDENTITY, Self::mul)
1361    }
1362}
1363
1364impl<'a> Product<&'a Self> for Quat {
1365    fn product<I>(iter: I) -> Self
1366    where
1367        I: Iterator<Item = &'a Self>,
1368    {
1369        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1370    }
1371}
1372
1373impl From<Quat> for Vec4 {
1374    #[inline]
1375    fn from(q: Quat) -> Self {
1376        Self(q.0)
1377    }
1378}
1379
1380impl From<Quat> for (f32, f32, f32, f32) {
1381    #[inline]
1382    fn from(q: Quat) -> Self {
1383        Vec4::from(q).into()
1384    }
1385}
1386
1387impl From<Quat> for [f32; 4] {
1388    #[inline]
1389    fn from(q: Quat) -> Self {
1390        Vec4::from(q).into()
1391    }
1392}
1393
1394impl From<Quat> for float32x4_t {
1395    #[inline]
1396    fn from(q: Quat) -> Self {
1397        q.0
1398    }
1399}
1400
1401impl Deref for Quat {
1402    type Target = crate::deref::Vec4<f32>;
1403    #[inline]
1404    fn deref(&self) -> &Self::Target {
1405        unsafe { &*(self as *const Self).cast() }
1406    }
1407}
1408
1409impl DerefMut for Quat {
1410    #[inline]
1411    fn deref_mut(&mut self) -> &mut Self::Target {
1412        unsafe { &mut *(self as *mut Self).cast() }
1413    }
1414}