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