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")]
25use zerocopy_derive::*;
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",
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    /// `[x, y, z, w]`
527    #[inline]
528    #[must_use]
529    pub fn to_array(self) -> [f32; 4] {
530        [self.x, self.y, self.z, self.w]
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    #[inline]
639    #[must_use]
640    pub fn is_near_identity(self) -> bool {
641        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
642        // Because of floating point precision, we cannot represent very small rotations.
643        // The closest f32 to 1.0 that is not 1.0 itself yields:
644        // 0.99999994.acos() * 2.0  = 0.000690533954 rad
645        //
646        // An error threshold of 1.e-6 is used by default.
647        // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
648        // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
649        //
650        // We don't really care about the angle value itself, only if it's close to 0.
651        // This will happen whenever quat.w is close to 1.0.
652        // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
653        // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
654        // the shortest path.
655        //
656        // For f64 we're using a threshhold of
657        // (1.0 - 1e-14).acos() * 2.0
658        const THRESHOLD_ANGLE: f32 = 0.002_847_144_6;
659        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
660        positive_w_angle < THRESHOLD_ANGLE
661    }
662
663    /// Returns the angle (in radians) for the minimal rotation
664    /// for transforming this quaternion into another.
665    ///
666    /// Both quaternions must be normalized.
667    ///
668    /// # Panics
669    ///
670    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
671    #[inline]
672    #[must_use]
673    pub fn angle_between(self, rhs: Self) -> f32 {
674        glam_assert!(self.is_normalized() && rhs.is_normalized());
675        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
676    }
677
678    /// Rotates towards `rhs` up to `max_angle` (in radians).
679    ///
680    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
681    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
682    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
683    ///
684    /// Both quaternions must be normalized.
685    ///
686    /// # Panics
687    ///
688    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
689    #[inline]
690    #[must_use]
691    pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self {
692        glam_assert!(self.is_normalized() && rhs.is_normalized());
693        let angle = self.angle_between(rhs);
694        if angle <= 1e-4 {
695            return rhs;
696        }
697        let s = (max_angle / angle).clamp(-1.0, 1.0);
698        self.slerp(rhs, s)
699    }
700
701    /// Returns true if the absolute difference of all elements between `self` and `rhs`
702    /// is less than or equal to `max_abs_diff`.
703    ///
704    /// This can be used to compare if two quaternions contain similar elements. It works
705    /// best when comparing with a known value. The `max_abs_diff` that should be used used
706    /// depends on the values being compared against.
707    ///
708    /// For more see
709    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
710    #[inline]
711    #[must_use]
712    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
713        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
714    }
715
716    #[inline(always)]
717    #[must_use]
718    fn lerp_impl(self, end: Self, s: f32) -> Self {
719        (self * (1.0 - s) + end * s).normalize()
720    }
721
722    /// Performs a linear interpolation between `self` and `rhs` based on
723    /// the value `s`.
724    ///
725    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
726    /// is `1.0`, the result will be equal to `rhs`.
727    ///
728    /// # Panics
729    ///
730    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
731    #[doc(alias = "mix")]
732    #[inline]
733    #[must_use]
734    pub fn lerp(self, end: Self, s: f32) -> Self {
735        glam_assert!(self.is_normalized());
736        glam_assert!(end.is_normalized());
737
738        const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]);
739        unsafe {
740            let dot = dot4_into_m128(self.0, end.0);
741            // Calculate the bias, if the dot product is positive or zero, there is no bias
742            // but if it is negative, we want to flip the 'end' rotation XYZW components
743            let bias = _mm_and_ps(dot, NEG_ZERO);
744            self.lerp_impl(Self(_mm_xor_ps(end.0, bias)), s)
745        }
746    }
747
748    #[inline(always)]
749    #[must_use]
750    fn slerp_impl(self, end: Self, dot: f32, s: f32) -> Self {
751        let theta = math::acos_approx(dot);
752
753        let x = 1.0 - s;
754        let y = s;
755        let z = 1.0;
756
757        unsafe {
758            let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x));
759            let tmp = m128_sin(tmp);
760
761            let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00);
762            let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01);
763            let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10);
764
765            Self(_mm_div_ps(
766                _mm_add_ps(_mm_mul_ps(self.0, scale1), _mm_mul_ps(end.0, scale2)),
767                theta_sin,
768            ))
769        }
770    }
771
772    /// Performs a spherical linear interpolation between `self` and `end`
773    /// based on the value `s`.
774    ///
775    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
776    /// is `1.0`, the result will be equal to `end`.
777    ///
778    /// # Panics
779    ///
780    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
781    #[inline]
782    #[must_use]
783    pub fn slerp(self, mut end: Self, s: f32) -> Self {
784        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
785        glam_assert!(self.is_normalized());
786        glam_assert!(end.is_normalized());
787
788        // Note that a rotation can be represented by two quaternions: `q` and
789        // `-q`. The slerp path between `q` and `end` will be different from the
790        // path between `-q` and `end`. One path will take the long way around and
791        // one will take the short way. In order to correct for this, the `dot`
792        // product between `self` and `end` should be positive. If the `dot`
793        // product is negative, slerp between `self` and `-end`.
794        let mut dot = self.dot(end);
795        if dot < 0.0 {
796            end = -end;
797            dot = -dot;
798        }
799
800        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
801        if dot > DOT_THRESHOLD {
802            // if above threshold perform linear interpolation to avoid divide by zero
803            self.lerp_impl(end, s)
804        } else {
805            self.slerp_impl(end, dot, s)
806        }
807    }
808
809    /// Performs a spherical linear interpolation between `self` and `end` based on the value `s`,
810    /// preserving the rotation direction.
811    ///
812    /// When `s` is `0.0`, the result will be equal to `self`.  When `s` is `1.0`, the result will
813    /// be equal to `end`.
814    ///
815    /// When the dot product of `self` and `end` is negative, the standard [`slerp`](Self::slerp)
816    /// will flip the end quaternion to take the shortest path, while this method will take the
817    /// longer arc. This is useful when the intended rotation direction must be preserved.
818    ///
819    /// # Panics
820    ///
821    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
822    #[inline]
823    #[must_use]
824    pub fn slerp_long(self, end: Self, s: f32) -> Self {
825        glam_assert!(self.is_normalized());
826        glam_assert!(end.is_normalized());
827
828        let dot = self.dot(end);
829
830        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
831        if dot.abs() > DOT_THRESHOLD {
832            // if above threshold perform linear interpolation to avoid divide by zero
833            self.lerp_impl(end, s)
834        } else {
835            self.slerp_impl(end, dot, s)
836        }
837    }
838
839    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
840    ///
841    /// # Panics
842    ///
843    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
844    #[inline]
845    #[must_use]
846    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
847        glam_assert!(self.is_normalized());
848
849        self.mul_vec3a(rhs.into()).into()
850    }
851
852    /// Multiplies two quaternions. If they each represent a rotation, the result will
853    /// represent the combined rotation.
854    ///
855    /// Note that due to floating point rounding the result may not be perfectly normalized.
856    ///
857    /// # Panics
858    ///
859    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
860    #[inline]
861    #[must_use]
862    pub fn mul_quat(self, rhs: Self) -> Self {
863        // Based on https://github.com/nfrechette/rtm `rtm::quat_mul`
864        const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
865        const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
866        const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]);
867
868        let lhs = self.0;
869        let rhs = rhs.0;
870
871        unsafe {
872            let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00);
873            let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01);
874            let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10);
875            let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11);
876
877            let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs);
878            let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11);
879
880            let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx);
881            let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01);
882
883            let lwrx_nlzrx_lyrx_nlxrx = _mm_mul_ps(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
884
885            let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy);
886            let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11);
887
888            let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
889
890            let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz);
891            let result0 = _mm_add_ps(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
892
893            let nlyrz_lxrz_lwrz_wlzrz = _mm_mul_ps(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
894            let result1 = _mm_add_ps(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
895
896            Self(_mm_add_ps(result0, result1))
897        }
898    }
899
900    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
901    ///
902    /// Note if the input affine matrix contain scales, shears, or other non-rotation
903    /// transformations then the resulting quaternion will be ill-defined.
904    ///
905    /// # Panics
906    ///
907    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
908    /// enabled.
909    #[inline]
910    #[must_use]
911    pub fn from_affine3(a: &crate::Affine3) -> Self {
912        Self::from_rotation_axes(a.matrix3.x_axis, a.matrix3.y_axis, a.matrix3.z_axis)
913    }
914
915    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
916    ///
917    /// Note if the input affine matrix contain scales, shears, or other non-rotation
918    /// transformations then the resulting quaternion will be ill-defined.
919    ///
920    /// # Panics
921    ///
922    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
923    /// enabled.
924    #[inline]
925    #[must_use]
926    pub fn from_affine3a(a: &crate::Affine3A) -> Self {
927        Self::from_rotation_axes(
928            a.matrix3.x_axis.into(),
929            a.matrix3.y_axis.into(),
930            a.matrix3.z_axis.into(),
931        )
932    }
933
934    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
935    #[inline]
936    #[must_use]
937    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
938        unsafe {
939            const TWO: __m128 = m128_from_f32x4([2.0; 4]);
940            let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11);
941            let b = self.0;
942            let b2 = dot3_into_m128(b, b);
943            Vec3A(_mm_add_ps(
944                _mm_add_ps(
945                    _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)),
946                    _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)),
947                ),
948                _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)),
949            ))
950        }
951    }
952
953    #[cfg(feature = "f64")]
954    #[inline]
955    #[must_use]
956    pub fn as_dquat(self) -> DQuat {
957        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
958    }
959}
960
961impl fmt::Debug for Quat {
962    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
963        fmt.debug_tuple(stringify!(Quat))
964            .field(&self.x)
965            .field(&self.y)
966            .field(&self.z)
967            .field(&self.w)
968            .finish()
969    }
970}
971
972impl fmt::Display for Quat {
973    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
974        if let Some(p) = f.precision() {
975            write!(
976                f,
977                "[{:.*}, {:.*}, {:.*}, {:.*}]",
978                p, self.x, p, self.y, p, self.z, p, self.w
979            )
980        } else {
981            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
982        }
983    }
984}
985
986impl Add for Quat {
987    type Output = Self;
988    /// Adds two quaternions.
989    ///
990    /// The sum is not guaranteed to be normalized.
991    ///
992    /// Note that addition is not the same as combining the rotations represented by the
993    /// two quaternions! That corresponds to multiplication.
994    #[inline]
995    fn add(self, rhs: Self) -> Self {
996        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
997    }
998}
999
1000impl Add<&Self> for Quat {
1001    type Output = Self;
1002    #[inline]
1003    fn add(self, rhs: &Self) -> Self {
1004        self.add(*rhs)
1005    }
1006}
1007
1008impl Add<&Quat> for &Quat {
1009    type Output = Quat;
1010    #[inline]
1011    fn add(self, rhs: &Quat) -> Quat {
1012        (*self).add(*rhs)
1013    }
1014}
1015
1016impl Add<Quat> for &Quat {
1017    type Output = Quat;
1018    #[inline]
1019    fn add(self, rhs: Quat) -> Quat {
1020        (*self).add(rhs)
1021    }
1022}
1023
1024impl AddAssign for Quat {
1025    #[inline]
1026    fn add_assign(&mut self, rhs: Self) {
1027        *self = self.add(rhs);
1028    }
1029}
1030
1031impl AddAssign<&Self> for Quat {
1032    #[inline]
1033    fn add_assign(&mut self, rhs: &Self) {
1034        self.add_assign(*rhs);
1035    }
1036}
1037
1038impl Sub for Quat {
1039    type Output = Self;
1040    /// Subtracts the `rhs` quaternion from `self`.
1041    ///
1042    /// The difference is not guaranteed to be normalized.
1043    #[inline]
1044    fn sub(self, rhs: Self) -> Self {
1045        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
1046    }
1047}
1048
1049impl Sub<&Self> for Quat {
1050    type Output = Self;
1051    #[inline]
1052    fn sub(self, rhs: &Self) -> Self {
1053        self.sub(*rhs)
1054    }
1055}
1056
1057impl Sub<&Quat> for &Quat {
1058    type Output = Quat;
1059    #[inline]
1060    fn sub(self, rhs: &Quat) -> Quat {
1061        (*self).sub(*rhs)
1062    }
1063}
1064
1065impl Sub<Quat> for &Quat {
1066    type Output = Quat;
1067    #[inline]
1068    fn sub(self, rhs: Quat) -> Quat {
1069        (*self).sub(rhs)
1070    }
1071}
1072
1073impl SubAssign for Quat {
1074    #[inline]
1075    fn sub_assign(&mut self, rhs: Self) {
1076        *self = self.sub(rhs);
1077    }
1078}
1079
1080impl SubAssign<&Self> for Quat {
1081    #[inline]
1082    fn sub_assign(&mut self, rhs: &Self) {
1083        self.sub_assign(*rhs);
1084    }
1085}
1086
1087impl Mul<f32> for Quat {
1088    type Output = Self;
1089    /// Multiplies a quaternion by a scalar value.
1090    ///
1091    /// The product is not guaranteed to be normalized.
1092    #[inline]
1093    fn mul(self, rhs: f32) -> Self {
1094        Self::from_vec4(Vec4::from(self) * rhs)
1095    }
1096}
1097
1098impl Mul<&f32> for Quat {
1099    type Output = Self;
1100    #[inline]
1101    fn mul(self, rhs: &f32) -> Self {
1102        self.mul(*rhs)
1103    }
1104}
1105
1106impl Mul<&f32> for &Quat {
1107    type Output = Quat;
1108    #[inline]
1109    fn mul(self, rhs: &f32) -> Quat {
1110        (*self).mul(*rhs)
1111    }
1112}
1113
1114impl Mul<f32> for &Quat {
1115    type Output = Quat;
1116    #[inline]
1117    fn mul(self, rhs: f32) -> Quat {
1118        (*self).mul(rhs)
1119    }
1120}
1121
1122impl MulAssign<f32> for Quat {
1123    #[inline]
1124    fn mul_assign(&mut self, rhs: f32) {
1125        *self = self.mul(rhs);
1126    }
1127}
1128
1129impl MulAssign<&f32> for Quat {
1130    #[inline]
1131    fn mul_assign(&mut self, rhs: &f32) {
1132        self.mul_assign(*rhs);
1133    }
1134}
1135
1136impl Div<f32> for Quat {
1137    type Output = Self;
1138    /// Divides a quaternion by a scalar value.
1139    /// The quotient is not guaranteed to be normalized.
1140    #[inline]
1141    fn div(self, rhs: f32) -> Self {
1142        Self::from_vec4(Vec4::from(self) / rhs)
1143    }
1144}
1145
1146impl Div<&f32> for Quat {
1147    type Output = Self;
1148    #[inline]
1149    fn div(self, rhs: &f32) -> Self {
1150        self.div(*rhs)
1151    }
1152}
1153
1154impl Div<&f32> for &Quat {
1155    type Output = Quat;
1156    #[inline]
1157    fn div(self, rhs: &f32) -> Quat {
1158        (*self).div(*rhs)
1159    }
1160}
1161
1162impl Div<f32> for &Quat {
1163    type Output = Quat;
1164    #[inline]
1165    fn div(self, rhs: f32) -> Quat {
1166        (*self).div(rhs)
1167    }
1168}
1169
1170impl DivAssign<f32> for Quat {
1171    #[inline]
1172    fn div_assign(&mut self, rhs: f32) {
1173        *self = self.div(rhs);
1174    }
1175}
1176
1177impl DivAssign<&f32> for Quat {
1178    #[inline]
1179    fn div_assign(&mut self, rhs: &f32) {
1180        self.div_assign(*rhs);
1181    }
1182}
1183
1184impl Mul for Quat {
1185    type Output = Self;
1186    /// Multiplies two quaternions. If they each represent a rotation, the result will
1187    /// represent the combined rotation.
1188    ///
1189    /// Note that due to floating point rounding the result may not be perfectly
1190    /// normalized.
1191    ///
1192    /// # Panics
1193    ///
1194    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
1195    #[inline]
1196    fn mul(self, rhs: Self) -> Self {
1197        self.mul_quat(rhs)
1198    }
1199}
1200
1201impl Mul<&Self> for Quat {
1202    type Output = Self;
1203    #[inline]
1204    fn mul(self, rhs: &Self) -> Self {
1205        self.mul(*rhs)
1206    }
1207}
1208
1209impl Mul<&Quat> for &Quat {
1210    type Output = Quat;
1211    #[inline]
1212    fn mul(self, rhs: &Quat) -> Quat {
1213        (*self).mul(*rhs)
1214    }
1215}
1216
1217impl Mul<Quat> for &Quat {
1218    type Output = Quat;
1219    #[inline]
1220    fn mul(self, rhs: Quat) -> Quat {
1221        (*self).mul(rhs)
1222    }
1223}
1224
1225impl MulAssign for Quat {
1226    #[inline]
1227    fn mul_assign(&mut self, rhs: Self) {
1228        *self = self.mul(rhs);
1229    }
1230}
1231
1232impl MulAssign<&Self> for Quat {
1233    #[inline]
1234    fn mul_assign(&mut self, rhs: &Self) {
1235        self.mul_assign(*rhs);
1236    }
1237}
1238
1239impl Mul<Vec3> for Quat {
1240    type Output = Vec3;
1241    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1242    ///
1243    /// # Panics
1244    ///
1245    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1246    #[inline]
1247    fn mul(self, rhs: Vec3) -> Self::Output {
1248        self.mul_vec3(rhs)
1249    }
1250}
1251
1252impl Mul<&Vec3> for Quat {
1253    type Output = Vec3;
1254    #[inline]
1255    fn mul(self, rhs: &Vec3) -> Vec3 {
1256        self.mul(*rhs)
1257    }
1258}
1259
1260impl Mul<&Vec3> for &Quat {
1261    type Output = Vec3;
1262    #[inline]
1263    fn mul(self, rhs: &Vec3) -> Vec3 {
1264        (*self).mul(*rhs)
1265    }
1266}
1267
1268impl Mul<Vec3> for &Quat {
1269    type Output = Vec3;
1270    #[inline]
1271    fn mul(self, rhs: Vec3) -> Vec3 {
1272        (*self).mul(rhs)
1273    }
1274}
1275
1276impl Mul<Vec3A> for Quat {
1277    type Output = Vec3A;
1278    #[inline]
1279    fn mul(self, rhs: Vec3A) -> Self::Output {
1280        self.mul_vec3a(rhs)
1281    }
1282}
1283
1284impl Mul<&Vec3A> for Quat {
1285    type Output = Vec3A;
1286    #[inline]
1287    fn mul(self, rhs: &Vec3A) -> Vec3A {
1288        self.mul(*rhs)
1289    }
1290}
1291
1292impl Mul<&Vec3A> for &Quat {
1293    type Output = Vec3A;
1294    #[inline]
1295    fn mul(self, rhs: &Vec3A) -> Vec3A {
1296        (*self).mul(*rhs)
1297    }
1298}
1299
1300impl Mul<Vec3A> for &Quat {
1301    type Output = Vec3A;
1302    #[inline]
1303    fn mul(self, rhs: Vec3A) -> Vec3A {
1304        (*self).mul(rhs)
1305    }
1306}
1307
1308impl Neg for Quat {
1309    type Output = Self;
1310    #[inline]
1311    fn neg(self) -> Self {
1312        self * -1.0
1313    }
1314}
1315
1316impl Neg for &Quat {
1317    type Output = Quat;
1318    #[inline]
1319    fn neg(self) -> Quat {
1320        (*self).neg()
1321    }
1322}
1323
1324impl Default for Quat {
1325    #[inline]
1326    fn default() -> Self {
1327        Self::IDENTITY
1328    }
1329}
1330
1331impl PartialEq for Quat {
1332    #[inline]
1333    fn eq(&self, rhs: &Self) -> bool {
1334        Vec4::from(*self).eq(&Vec4::from(*rhs))
1335    }
1336}
1337
1338impl AsRef<[f32; 4]> for Quat {
1339    #[inline]
1340    fn as_ref(&self) -> &[f32; 4] {
1341        unsafe { &*(self as *const Self as *const [f32; 4]) }
1342    }
1343}
1344
1345impl Sum<Self> for Quat {
1346    fn sum<I>(iter: I) -> Self
1347    where
1348        I: Iterator<Item = Self>,
1349    {
1350        iter.fold(Self::ZERO, Self::add)
1351    }
1352}
1353
1354impl<'a> Sum<&'a Self> for Quat {
1355    fn sum<I>(iter: I) -> Self
1356    where
1357        I: Iterator<Item = &'a Self>,
1358    {
1359        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1360    }
1361}
1362
1363impl Product for Quat {
1364    fn product<I>(iter: I) -> Self
1365    where
1366        I: Iterator<Item = Self>,
1367    {
1368        iter.fold(Self::IDENTITY, Self::mul)
1369    }
1370}
1371
1372impl<'a> Product<&'a Self> for Quat {
1373    fn product<I>(iter: I) -> Self
1374    where
1375        I: Iterator<Item = &'a Self>,
1376    {
1377        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1378    }
1379}
1380
1381impl From<Quat> for Vec4 {
1382    #[inline]
1383    fn from(q: Quat) -> Self {
1384        Self(q.0)
1385    }
1386}
1387
1388impl From<Quat> for (f32, f32, f32, f32) {
1389    #[inline]
1390    fn from(q: Quat) -> Self {
1391        Vec4::from(q).into()
1392    }
1393}
1394
1395impl From<Quat> for [f32; 4] {
1396    #[inline]
1397    fn from(q: Quat) -> Self {
1398        Vec4::from(q).into()
1399    }
1400}
1401
1402impl From<Quat> for __m128 {
1403    #[inline]
1404    fn from(q: Quat) -> Self {
1405        q.0
1406    }
1407}
1408
1409impl Deref for Quat {
1410    type Target = crate::deref::Vec4<f32>;
1411    #[inline]
1412    fn deref(&self) -> &Self::Target {
1413        unsafe { &*(self as *const Self).cast() }
1414    }
1415}
1416
1417impl DerefMut for Quat {
1418    #[inline]
1419    fn deref_mut(&mut self) -> &mut Self::Target {
1420        unsafe { &mut *(self as *mut Self).cast() }
1421    }
1422}