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