Skip to main content

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