Skip to main content

glam/f32/sse2/
quat.rs

1// Generated from quat.rs.tera template. Edit the template, not the generated file.
2
3use crate::{
4    euler::{EulerRot, FromEuler, ToEuler},
5    f32::math,
6    sse2::*,
7    Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8};
9
10#[cfg(feature = "f64")]
11use crate::DQuat;
12
13#[cfg(target_arch = "x86")]
14use core::arch::x86::*;
15#[cfg(target_arch = "x86_64")]
16use core::arch::x86_64::*;
17
18use core::fmt;
19use core::iter::{Product, Sum};
20use core::ops::{
21    Add, AddAssign, Deref, DerefMut, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign,
22};
23
24#[cfg(feature = "zerocopy-08")]
25use zerocopy_derive_08::*;
26
27#[repr(C)]
28union UnionCast {
29    a: [f32; 4],
30    v: Quat,
31}
32
33/// Creates a quaternion from `x`, `y`, `z` and `w` values.
34///
35/// This should generally not be called manually unless you know what you are doing. Use
36/// one of the other constructors instead such as `identity` or `from_axis_angle`.
37#[inline]
38#[must_use]
39pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
40    Quat::from_xyzw(x, y, z, w)
41}
42
43/// A quaternion representing an orientation.
44///
45/// This quaternion is intended to be of unit length but may denormalize due to
46/// floating point "error creep" which can occur when successive quaternion
47/// operations are applied.
48///
49/// SIMD vector types are used for storage on supported platforms.
50///
51/// This type is 16 byte aligned.
52#[derive(Clone, Copy)]
53#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
54#[cfg_attr(
55    feature = "zerocopy-08",
56    derive(FromBytes, Immutable, IntoBytes, KnownLayout)
57)]
58#[repr(transparent)]
59pub struct Quat(pub(crate) __m128);
60
61impl Quat {
62    /// All zeros.
63    const ZERO: Self = Self::from_array([0.0; 4]);
64
65    /// The identity quaternion. Corresponds to no rotation.
66    pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
67
68    /// All NANs.
69    pub const NAN: Self = Self::from_array([f32::NAN; 4]);
70
71    /// Creates a new rotation quaternion.
72    ///
73    /// This should generally not be called manually unless you know what you are doing.
74    /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
75    ///
76    /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
77    ///
78    /// # Preconditions
79    ///
80    /// This function does not check if the input is normalized, it is up to the user to
81    /// provide normalized input or to normalized the resulting quaternion.
82    #[inline(always)]
83    #[must_use]
84    pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
85        unsafe { UnionCast { a: [x, y, z, w] }.v }
86    }
87
88    /// Creates a rotation quaternion from an array.
89    ///
90    /// # Preconditions
91    ///
92    /// This function does not check if the input is normalized, it is up to the user to
93    /// provide normalized input or to normalized the resulting quaternion.
94    #[inline]
95    #[must_use]
96    pub const fn from_array(a: [f32; 4]) -> Self {
97        Self::from_xyzw(a[0], a[1], a[2], a[3])
98    }
99
100    /// Creates a new rotation quaternion from a 4D vector.
101    ///
102    /// # Preconditions
103    ///
104    /// This function does not check if the input is normalized, it is up to the user to
105    /// provide normalized input or to normalized the resulting quaternion.
106    #[inline]
107    #[must_use]
108    pub const fn from_vec4(v: Vec4) -> Self {
109        Self(v.0)
110    }
111
112    /// Creates a rotation quaternion from a slice.
113    ///
114    /// # Preconditions
115    ///
116    /// This function does not check if the input is normalized, it is up to the user to
117    /// provide normalized input or to normalized the resulting quaternion.
118    ///
119    /// # Panics
120    ///
121    /// Panics if `slice` length is less than 4.
122    #[inline]
123    #[must_use]
124    #[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    /// Creates a quaterion rotation from a facing direction and an up direction.
428    ///
429    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
430    ///
431    /// # Panics
432    ///
433    /// Will panic if `dir` or `up` are not normalized, or if `dir` and `up` are parallel,
434    /// when `glam_assert` is enabled.
435    #[deprecated(
436        since = "0.33.1",
437        note = "use the `glam::camera::lh::view::look_to_quat` function instead"
438    )]
439    #[inline]
440    #[must_use]
441    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
442    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
443        #[allow(deprecated)]
444        Self::look_to_rh(-dir, up)
445    }
446
447    /// Creates a quaterion rotation from facing direction and an up direction.
448    ///
449    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
450    ///
451    /// # Panics
452    ///
453    /// Will panic if `dir` or `up` are not normalized, or if `dir` and `up` are parallel,
454    /// when `glam_assert` is enabled.
455    #[deprecated(
456        since = "0.33.1",
457        note = "use the `glam::camera::rh::view::look_to_quat` function instead"
458    )]
459    #[inline]
460    #[must_use]
461    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
462    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
463        glam_assert!(dir.is_normalized());
464        glam_assert!(up.is_normalized());
465        let f = dir;
466        let s = f.cross(up).normalize();
467        let u = s.cross(f);
468
469        Self::from_rotation_axes(
470            Vec3::new(s.x, u.x, -f.x),
471            Vec3::new(s.y, u.y, -f.y),
472            Vec3::new(s.z, u.z, -f.z),
473        )
474    }
475
476    /// Creates a quaternion rotation from a camera position, a focal point, and an up
477    /// direction.
478    ///
479    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
480    ///
481    /// # Panics
482    ///
483    /// Will panic if `up` is not normalized, if `center` is equal to `eye`, or if the view
484    /// direction is parallel to `up`, when `glam_assert` is enabled.
485    #[deprecated(
486        since = "0.33.1",
487        note = "use the `glam::camera::lh::view::look_at_quat` function instead"
488    )]
489    #[inline]
490    #[must_use]
491    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
492    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
493        #[allow(deprecated)]
494        Self::look_to_lh(center.sub(eye).normalize(), up)
495    }
496
497    /// Creates a quaternion rotation using a camera position, an up direction, and a focal
498    /// point.
499    ///
500    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
501    ///
502    /// # Panics
503    ///
504    /// Will panic if `up` is not normalized, if `center` is equal to `eye`, or if the view
505    /// direction is parallel to `up`, when `glam_assert` is enabled.
506    #[deprecated(
507        since = "0.33.1",
508        note = "use the `glam::camera::rh::view::look_at_quat` function instead"
509    )]
510    #[inline]
511    #[must_use]
512    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
513    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
514        #[allow(deprecated)]
515        Self::look_to_rh(center.sub(eye).normalize(), up)
516    }
517
518    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
519    #[inline]
520    #[must_use]
521    pub fn to_axis_angle(self) -> (Vec3, f32) {
522        const EPSILON: f32 = 1.0e-8;
523        let v = Vec3::new(self.x, self.y, self.z);
524        let length = v.length();
525        if length >= EPSILON {
526            let angle = 2.0 * math::atan2(length, self.w);
527            let axis = v / length;
528            (axis, angle)
529        } else {
530            (Vec3::X, 0.0)
531        }
532    }
533
534    /// Returns the rotation axis scaled by the rotation in radians.
535    #[inline]
536    #[must_use]
537    pub fn to_scaled_axis(self) -> Vec3 {
538        let (axis, angle) = self.to_axis_angle();
539        axis * angle
540    }
541
542    /// Returns the rotation angles for the given euler rotation sequence.
543    ///
544    /// # Panics
545    ///
546    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
547    #[inline]
548    #[must_use]
549    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
550    pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) {
551        Mat3::from_quat(self).to_euler_angles(order)
552    }
553
554    /// Converts `self` to `[x, y, z, w]`
555    #[inline]
556    #[must_use]
557    pub const fn to_array(&self) -> [f32; 4] {
558        unsafe { *(self as *const Self as *const [f32; 4]) }
559    }
560
561    /// Returns the vector part of the quaternion.
562    #[inline]
563    #[must_use]
564    pub fn xyz(self) -> Vec3 {
565        Vec3::new(self.x, self.y, self.z)
566    }
567
568    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
569    /// conjugate is also the inverse.
570    #[inline]
571    #[must_use]
572    pub fn conjugate(self) -> Self {
573        const SIGN: __m128 = m128_from_f32x4([-0.0, -0.0, -0.0, 0.0]);
574        Self(unsafe { _mm_xor_ps(self.0, SIGN) })
575    }
576
577    /// Returns the inverse of a normalized quaternion.
578    ///
579    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
580    /// Because `self` is assumed to already be unit length this method *does not* normalize
581    /// before returning the conjugate.
582    ///
583    /// # Panics
584    ///
585    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
586    #[inline]
587    #[must_use]
588    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
589    pub fn inverse(self) -> Self {
590        glam_assert!(self.is_normalized());
591        self.conjugate()
592    }
593
594    /// Computes the dot product of `self` and `rhs`. The dot product is
595    /// equal to the cosine of the angle between two quaternion rotations.
596    #[inline]
597    #[must_use]
598    pub fn dot(self, rhs: Self) -> f32 {
599        Vec4::from(self).dot(Vec4::from(rhs))
600    }
601
602    /// Computes the length of `self`.
603    #[doc(alias = "magnitude")]
604    #[inline]
605    #[must_use]
606    pub fn length(self) -> f32 {
607        Vec4::from(self).length()
608    }
609
610    /// Computes the squared length of `self`.
611    ///
612    /// This is generally faster than `length()` as it avoids a square
613    /// root operation.
614    #[doc(alias = "magnitude2")]
615    #[inline]
616    #[must_use]
617    pub fn length_squared(self) -> f32 {
618        Vec4::from(self).length_squared()
619    }
620
621    /// Computes `1.0 / length()`.
622    ///
623    /// For valid results, `self` must _not_ be of length zero.
624    #[inline]
625    #[must_use]
626    pub fn length_recip(self) -> f32 {
627        Vec4::from(self).length_recip()
628    }
629
630    /// Returns `self` normalized to length 1.0.
631    ///
632    /// For valid results, `self` must _not_ be of length zero.
633    ///
634    /// # Panics
635    ///
636    /// Will panic if `self` is zero length when `glam_assert` is enabled.
637    #[inline]
638    #[must_use]
639    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
640    pub fn normalize(self) -> Self {
641        Self::from_vec4(Vec4::from(self).normalize())
642    }
643
644    /// Returns `true` if, and only if, all elements are finite.
645    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
646    #[inline]
647    #[must_use]
648    pub fn is_finite(self) -> bool {
649        Vec4::from(self).is_finite()
650    }
651
652    /// Returns `true` if any elements are `NAN`.
653    #[inline]
654    #[must_use]
655    pub fn is_nan(self) -> bool {
656        Vec4::from(self).is_nan()
657    }
658
659    /// Returns whether `self` of length `1.0` or not.
660    ///
661    /// Uses a precision threshold of `1e-6`.
662    #[inline]
663    #[must_use]
664    pub fn is_normalized(self) -> bool {
665        Vec4::from(self).is_normalized()
666    }
667
668    /// Returns `true` if `self` represents a rotation near the identity.
669    #[inline]
670    #[must_use]
671    pub fn is_near_identity(self) -> bool {
672        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
673        // The shortest rotation angle is `2 * acos(abs(w))`. Since `acos` is monotonically
674        // decreasing, comparing `abs(w)` to the cosine threshold avoids calculating the angle.
675        // Equivalent to an angular threshold of `(1.0 - 1e-6).acos() * 2.0`.
676        const THRESHOLD: f32 = 1.0 - 1e-6;
677        math::abs(self.w) > THRESHOLD
678    }
679
680    /// Returns the angle (in radians) for the minimal rotation between two quaternions
681    /// in the range `[0, +π]`.
682    ///
683    /// Both quaternions must be normalized.
684    ///
685    /// # Panics
686    ///
687    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
688    #[inline]
689    #[must_use]
690    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
691    pub fn angle_between(self, rhs: Self) -> f32 {
692        glam_assert!(self.is_normalized() && rhs.is_normalized());
693        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
694    }
695
696    /// Rotates towards `rhs` up to `max_angle` (in radians).
697    ///
698    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
699    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
700    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
701    ///
702    /// Both quaternions must be normalized.
703    ///
704    /// # Panics
705    ///
706    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
707    #[inline]
708    #[must_use]
709    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
710    pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self {
711        glam_assert!(self.is_normalized() && rhs.is_normalized());
712        let angle = self.angle_between(rhs);
713        if angle <= 1e-4 {
714            return rhs;
715        }
716        let s = (max_angle / angle).clamp(-1.0, 1.0);
717        self.slerp(rhs, s)
718    }
719
720    /// Returns true if the absolute difference of all elements between `self` and `rhs`
721    /// is less than or equal to `max_abs_diff`.
722    ///
723    /// This can be used to compare if two quaternions contain similar elements. It works
724    /// best when comparing with a known value. The `max_abs_diff` that should be used used
725    /// depends on the values being compared against.
726    ///
727    /// For more see
728    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
729    #[inline]
730    #[must_use]
731    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
732        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
733    }
734
735    #[inline(always)]
736    #[must_use]
737    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
738    fn lerp_impl(self, end: Self, s: f32) -> Self {
739        (self * (1.0 - s) + end * s).normalize()
740    }
741
742    /// Performs a linear interpolation between `self` and `rhs` based on
743    /// the value `s`, using the form `self * (1.0 - s) + end * s` before normalizing.
744    ///
745    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
746    /// is `1.0`, the result will be equal to `rhs`.
747    ///
748    /// This interpolates linearly between the two rotations and does not rotate at a constant
749    /// angular velocity; see [`slerp`](Self::slerp) if that is required.
750    ///
751    /// # Panics
752    ///
753    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
754    #[doc(alias = "mix")]
755    #[inline]
756    #[must_use]
757    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
758    pub fn lerp(self, end: Self, s: f32) -> Self {
759        glam_assert!(self.is_normalized());
760        glam_assert!(end.is_normalized());
761
762        const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]);
763        unsafe {
764            let dot = dot4_into_m128(self.0, end.0);
765            // Calculate the bias, if the dot product is positive or zero, there is no bias
766            // but if it is negative, we want to flip the 'end' rotation XYZW components
767            let bias = _mm_and_ps(dot, NEG_ZERO);
768            self.lerp_impl(Self(_mm_xor_ps(end.0, bias)), s)
769        }
770    }
771
772    #[inline(always)]
773    #[must_use]
774    fn slerp_impl(self, end: Self, dot: f32, s: f32) -> Self {
775        let theta = math::acos_approx(dot);
776
777        let x = 1.0 - s;
778        let y = s;
779        let z = 1.0;
780
781        unsafe {
782            let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x));
783            let tmp = m128_sin(tmp);
784
785            let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00);
786            let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01);
787            let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10);
788
789            Self(_mm_div_ps(
790                m128_mul_add(end.0, scale2, _mm_mul_ps(self.0, scale1)),
791                theta_sin,
792            ))
793        }
794    }
795
796    /// Performs a spherical linear interpolation between `self` and `end`
797    /// based on the value `s`.
798    ///
799    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
800    /// is `1.0`, the result will be equal to `end`.
801    ///
802    /// # Panics
803    ///
804    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
805    #[inline]
806    #[must_use]
807    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
808    pub fn slerp(self, mut end: Self, s: f32) -> Self {
809        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
810        glam_assert!(self.is_normalized());
811        glam_assert!(end.is_normalized());
812
813        // Note that a rotation can be represented by two quaternions: `q` and
814        // `-q`. The slerp path between `q` and `end` will be different from the
815        // path between `-q` and `end`. One path will take the long way around and
816        // one will take the short way. In order to correct for this, the `dot`
817        // product between `self` and `end` should be positive. If the `dot`
818        // product is negative, slerp between `self` and `-end`.
819        let mut dot = self.dot(end);
820        if dot < 0.0 {
821            end = -end;
822            dot = -dot;
823        }
824
825        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
826        if dot > DOT_THRESHOLD {
827            // if above threshold perform linear interpolation to avoid divide by zero
828            self.lerp_impl(end, s)
829        } else {
830            self.slerp_impl(end, dot, s)
831        }
832    }
833
834    /// Performs a spherical linear interpolation between `self` and `end` based on the value `s`,
835    /// preserving the rotation direction.
836    ///
837    /// When `s` is `0.0`, the result will be equal to `self`.  When `s` is `1.0`, the result will
838    /// be equal to `end`.
839    ///
840    /// When the dot product of `self` and `end` is negative, the standard [`slerp`](Self::slerp)
841    /// will flip the end quaternion to take the shortest path, while this method will take the
842    /// longer arc. This is useful when the intended rotation direction must be preserved.
843    ///
844    /// # Panics
845    ///
846    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
847    #[inline]
848    #[must_use]
849    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
850    pub fn slerp_long(self, end: Self, s: f32) -> Self {
851        glam_assert!(self.is_normalized());
852        glam_assert!(end.is_normalized());
853
854        let dot = self.dot(end);
855
856        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
857        if math::abs(dot) > DOT_THRESHOLD {
858            // if above threshold perform linear interpolation to avoid divide by zero
859            self.lerp_impl(end, s)
860        } else {
861            self.slerp_impl(end, dot, s)
862        }
863    }
864
865    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
866    ///
867    /// # Panics
868    ///
869    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
870    #[inline]
871    #[must_use]
872    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
873    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
874        glam_assert!(self.is_normalized());
875
876        self.mul_vec3a(rhs.into()).into()
877    }
878
879    /// Multiplies two quaternions. If they each represent a rotation, the result will
880    /// represent the combined rotation.
881    ///
882    /// Note that due to floating point rounding the result may not be perfectly normalized.
883    #[inline]
884    #[must_use]
885    pub fn mul_quat(self, rhs: Self) -> Self {
886        // Based on https://github.com/nfrechette/rtm `rtm::quat_mul`
887        const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
888        const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
889        const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]);
890
891        let lhs = self.0;
892        let rhs = rhs.0;
893
894        unsafe {
895            let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00);
896            let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01);
897            let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10);
898            let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11);
899
900            let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs);
901            let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11);
902
903            let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx);
904            let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01);
905
906            let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy);
907            let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11);
908
909            let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
910
911            let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz);
912            let result0 = m128_mul_add(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX, lxrw_lyrw_lzrw_lwrw);
913
914            let result1 = m128_mul_add(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ, lzry_lwry_nlxry_nlyry);
915
916            Self(_mm_add_ps(result0, result1))
917        }
918    }
919
920    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
921    ///
922    /// Note if the input affine matrix contain scales, shears, or other non-rotation
923    /// transformations then the resulting quaternion will be ill-defined.
924    ///
925    /// # Panics
926    ///
927    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
928    /// enabled.
929    #[inline]
930    #[must_use]
931    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
932    pub fn from_affine3(a: &crate::Affine3) -> Self {
933        Self::from_rotation_axes(a.matrix3.x_axis, a.matrix3.y_axis, a.matrix3.z_axis)
934    }
935
936    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
937    ///
938    /// Note if the input affine matrix contain scales, shears, or other non-rotation
939    /// transformations then the resulting quaternion will be ill-defined.
940    ///
941    /// # Panics
942    ///
943    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
944    /// enabled.
945    #[inline]
946    #[must_use]
947    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
948    pub fn from_affine3a(a: &crate::Affine3A) -> Self {
949        Self::from_rotation_axes(
950            a.matrix3.x_axis.into(),
951            a.matrix3.y_axis.into(),
952            a.matrix3.z_axis.into(),
953        )
954    }
955
956    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
957    ///
958    /// # Panics
959    ///
960    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
961    #[inline]
962    #[must_use]
963    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
964    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
965        glam_assert!(self.is_normalized());
966
967        unsafe {
968            const TWO: __m128 = m128_from_f32x4([2.0; 4]);
969            let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11);
970            let b = self.0;
971            let b2 = dot3_into_m128(b, b);
972            Vec3A(_mm_add_ps(
973                _mm_add_ps(
974                    _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)),
975                    _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)),
976                ),
977                _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)),
978            ))
979        }
980    }
981
982    #[cfg(feature = "f64")]
983    #[inline]
984    #[must_use]
985    pub fn as_dquat(self) -> DQuat {
986        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
987    }
988}
989
990impl fmt::Debug for Quat {
991    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
992        fmt.debug_tuple(stringify!(Quat))
993            .field(&self.x)
994            .field(&self.y)
995            .field(&self.z)
996            .field(&self.w)
997            .finish()
998    }
999}
1000
1001impl fmt::Display for Quat {
1002    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1003        if let Some(p) = f.precision() {
1004            write!(
1005                f,
1006                "[{:.*}, {:.*}, {:.*}, {:.*}]",
1007                p, self.x, p, self.y, p, self.z, p, self.w
1008            )
1009        } else {
1010            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
1011        }
1012    }
1013}
1014
1015impl Add for Quat {
1016    type Output = Self;
1017    /// Adds two quaternions.
1018    ///
1019    /// The sum is not guaranteed to be normalized.
1020    ///
1021    /// Note that addition is not the same as combining the rotations represented by the
1022    /// two quaternions! That corresponds to multiplication.
1023    #[inline]
1024    fn add(self, rhs: Self) -> Self {
1025        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
1026    }
1027}
1028
1029impl Add<&Self> for Quat {
1030    type Output = Self;
1031    #[inline]
1032    fn add(self, rhs: &Self) -> Self {
1033        self.add(*rhs)
1034    }
1035}
1036
1037impl Add<&Quat> for &Quat {
1038    type Output = Quat;
1039    #[inline]
1040    fn add(self, rhs: &Quat) -> Quat {
1041        (*self).add(*rhs)
1042    }
1043}
1044
1045impl Add<Quat> for &Quat {
1046    type Output = Quat;
1047    #[inline]
1048    fn add(self, rhs: Quat) -> Quat {
1049        (*self).add(rhs)
1050    }
1051}
1052
1053impl AddAssign for Quat {
1054    #[inline]
1055    fn add_assign(&mut self, rhs: Self) {
1056        *self = self.add(rhs);
1057    }
1058}
1059
1060impl AddAssign<&Self> for Quat {
1061    #[inline]
1062    fn add_assign(&mut self, rhs: &Self) {
1063        self.add_assign(*rhs);
1064    }
1065}
1066
1067impl Sub for Quat {
1068    type Output = Self;
1069    /// Subtracts the `rhs` quaternion from `self`.
1070    ///
1071    /// The difference is not guaranteed to be normalized.
1072    #[inline]
1073    fn sub(self, rhs: Self) -> Self {
1074        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
1075    }
1076}
1077
1078impl Sub<&Self> for Quat {
1079    type Output = Self;
1080    #[inline]
1081    fn sub(self, rhs: &Self) -> Self {
1082        self.sub(*rhs)
1083    }
1084}
1085
1086impl Sub<&Quat> for &Quat {
1087    type Output = Quat;
1088    #[inline]
1089    fn sub(self, rhs: &Quat) -> Quat {
1090        (*self).sub(*rhs)
1091    }
1092}
1093
1094impl Sub<Quat> for &Quat {
1095    type Output = Quat;
1096    #[inline]
1097    fn sub(self, rhs: Quat) -> Quat {
1098        (*self).sub(rhs)
1099    }
1100}
1101
1102impl SubAssign for Quat {
1103    #[inline]
1104    fn sub_assign(&mut self, rhs: Self) {
1105        *self = self.sub(rhs);
1106    }
1107}
1108
1109impl SubAssign<&Self> for Quat {
1110    #[inline]
1111    fn sub_assign(&mut self, rhs: &Self) {
1112        self.sub_assign(*rhs);
1113    }
1114}
1115
1116impl Mul<f32> for Quat {
1117    type Output = Self;
1118    /// Multiplies a quaternion by a scalar value.
1119    ///
1120    /// The product is not guaranteed to be normalized.
1121    #[inline]
1122    fn mul(self, rhs: f32) -> Self {
1123        Self::from_vec4(Vec4::from(self) * rhs)
1124    }
1125}
1126
1127impl Mul<&f32> for Quat {
1128    type Output = Self;
1129    #[inline]
1130    fn mul(self, rhs: &f32) -> Self {
1131        self.mul(*rhs)
1132    }
1133}
1134
1135impl Mul<&f32> for &Quat {
1136    type Output = Quat;
1137    #[inline]
1138    fn mul(self, rhs: &f32) -> Quat {
1139        (*self).mul(*rhs)
1140    }
1141}
1142
1143impl Mul<f32> for &Quat {
1144    type Output = Quat;
1145    #[inline]
1146    fn mul(self, rhs: f32) -> Quat {
1147        (*self).mul(rhs)
1148    }
1149}
1150
1151impl MulAssign<f32> for Quat {
1152    #[inline]
1153    fn mul_assign(&mut self, rhs: f32) {
1154        *self = self.mul(rhs);
1155    }
1156}
1157
1158impl MulAssign<&f32> for Quat {
1159    #[inline]
1160    fn mul_assign(&mut self, rhs: &f32) {
1161        self.mul_assign(*rhs);
1162    }
1163}
1164
1165impl Div<f32> for Quat {
1166    type Output = Self;
1167    /// Divides a quaternion by a scalar value.
1168    /// The quotient is not guaranteed to be normalized.
1169    #[inline]
1170    fn div(self, rhs: f32) -> Self {
1171        Self::from_vec4(Vec4::from(self) / rhs)
1172    }
1173}
1174
1175impl Div<&f32> for Quat {
1176    type Output = Self;
1177    #[inline]
1178    fn div(self, rhs: &f32) -> Self {
1179        self.div(*rhs)
1180    }
1181}
1182
1183impl Div<&f32> for &Quat {
1184    type Output = Quat;
1185    #[inline]
1186    fn div(self, rhs: &f32) -> Quat {
1187        (*self).div(*rhs)
1188    }
1189}
1190
1191impl Div<f32> for &Quat {
1192    type Output = Quat;
1193    #[inline]
1194    fn div(self, rhs: f32) -> Quat {
1195        (*self).div(rhs)
1196    }
1197}
1198
1199impl DivAssign<f32> for Quat {
1200    #[inline]
1201    fn div_assign(&mut self, rhs: f32) {
1202        *self = self.div(rhs);
1203    }
1204}
1205
1206impl DivAssign<&f32> for Quat {
1207    #[inline]
1208    fn div_assign(&mut self, rhs: &f32) {
1209        self.div_assign(*rhs);
1210    }
1211}
1212
1213impl Mul for Quat {
1214    type Output = Self;
1215    /// Multiplies two quaternions. If they each represent a rotation, the result will
1216    /// represent the combined rotation.
1217    ///
1218    /// Note that due to floating point rounding the result may not be perfectly
1219    /// normalized.
1220    #[inline]
1221    fn mul(self, rhs: Self) -> Self {
1222        self.mul_quat(rhs)
1223    }
1224}
1225
1226impl Mul<&Self> for Quat {
1227    type Output = Self;
1228    #[inline]
1229    fn mul(self, rhs: &Self) -> Self {
1230        self.mul(*rhs)
1231    }
1232}
1233
1234impl Mul<&Quat> for &Quat {
1235    type Output = Quat;
1236    #[inline]
1237    fn mul(self, rhs: &Quat) -> Quat {
1238        (*self).mul(*rhs)
1239    }
1240}
1241
1242impl Mul<Quat> for &Quat {
1243    type Output = Quat;
1244    #[inline]
1245    fn mul(self, rhs: Quat) -> Quat {
1246        (*self).mul(rhs)
1247    }
1248}
1249
1250impl MulAssign for Quat {
1251    #[inline]
1252    fn mul_assign(&mut self, rhs: Self) {
1253        *self = self.mul(rhs);
1254    }
1255}
1256
1257impl MulAssign<&Self> for Quat {
1258    #[inline]
1259    fn mul_assign(&mut self, rhs: &Self) {
1260        self.mul_assign(*rhs);
1261    }
1262}
1263
1264impl Mul<Vec3> for Quat {
1265    type Output = Vec3;
1266    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1267    ///
1268    /// # Panics
1269    ///
1270    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1271    #[inline]
1272    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1273    fn mul(self, rhs: Vec3) -> Self::Output {
1274        self.mul_vec3(rhs)
1275    }
1276}
1277
1278impl Mul<&Vec3> for Quat {
1279    type Output = Vec3;
1280    #[inline]
1281    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1282    fn mul(self, rhs: &Vec3) -> Vec3 {
1283        self.mul(*rhs)
1284    }
1285}
1286
1287impl Mul<&Vec3> for &Quat {
1288    type Output = Vec3;
1289    #[inline]
1290    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1291    fn mul(self, rhs: &Vec3) -> Vec3 {
1292        (*self).mul(*rhs)
1293    }
1294}
1295
1296impl Mul<Vec3> for &Quat {
1297    type Output = Vec3;
1298    #[inline]
1299    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1300    fn mul(self, rhs: Vec3) -> Vec3 {
1301        (*self).mul(rhs)
1302    }
1303}
1304
1305impl Mul<Vec3A> for Quat {
1306    type Output = Vec3A;
1307    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
1308    ///
1309    /// # Panics
1310    ///
1311    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
1312    #[inline]
1313    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1314    fn mul(self, rhs: Vec3A) -> Self::Output {
1315        self.mul_vec3a(rhs)
1316    }
1317}
1318
1319impl Mul<&Vec3A> for Quat {
1320    type Output = Vec3A;
1321    #[inline]
1322    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1323    fn mul(self, rhs: &Vec3A) -> Vec3A {
1324        self.mul(*rhs)
1325    }
1326}
1327
1328impl Mul<&Vec3A> for &Quat {
1329    type Output = Vec3A;
1330    #[inline]
1331    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1332    fn mul(self, rhs: &Vec3A) -> Vec3A {
1333        (*self).mul(*rhs)
1334    }
1335}
1336
1337impl Mul<Vec3A> for &Quat {
1338    type Output = Vec3A;
1339    #[inline]
1340    #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1341    fn mul(self, rhs: Vec3A) -> Vec3A {
1342        (*self).mul(rhs)
1343    }
1344}
1345
1346impl Neg for Quat {
1347    type Output = Self;
1348    #[inline]
1349    fn neg(self) -> Self {
1350        self * -1.0
1351    }
1352}
1353
1354impl Neg for &Quat {
1355    type Output = Quat;
1356    #[inline]
1357    fn neg(self) -> Quat {
1358        (*self).neg()
1359    }
1360}
1361
1362impl Default for Quat {
1363    #[inline]
1364    fn default() -> Self {
1365        Self::IDENTITY
1366    }
1367}
1368
1369impl PartialEq for Quat {
1370    #[inline]
1371    fn eq(&self, rhs: &Self) -> bool {
1372        Vec4::from(*self).eq(&Vec4::from(*rhs))
1373    }
1374}
1375
1376impl AsRef<[f32; 4]> for Quat {
1377    #[inline]
1378    fn as_ref(&self) -> &[f32; 4] {
1379        unsafe { &*(self as *const Self as *const [f32; 4]) }
1380    }
1381}
1382
1383impl Sum<Self> for Quat {
1384    fn sum<I>(iter: I) -> Self
1385    where
1386        I: Iterator<Item = Self>,
1387    {
1388        iter.fold(Self::ZERO, Self::add)
1389    }
1390}
1391
1392impl<'a> Sum<&'a Self> for Quat {
1393    fn sum<I>(iter: I) -> Self
1394    where
1395        I: Iterator<Item = &'a Self>,
1396    {
1397        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1398    }
1399}
1400
1401impl Product for Quat {
1402    fn product<I>(iter: I) -> Self
1403    where
1404        I: Iterator<Item = Self>,
1405    {
1406        iter.fold(Self::IDENTITY, Self::mul)
1407    }
1408}
1409
1410impl<'a> Product<&'a Self> for Quat {
1411    fn product<I>(iter: I) -> Self
1412    where
1413        I: Iterator<Item = &'a Self>,
1414    {
1415        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1416    }
1417}
1418
1419impl From<Quat> for Vec4 {
1420    #[inline]
1421    fn from(q: Quat) -> Self {
1422        Self(q.0)
1423    }
1424}
1425
1426impl From<Quat> for (f32, f32, f32, f32) {
1427    #[inline]
1428    fn from(q: Quat) -> Self {
1429        Vec4::from(q).into()
1430    }
1431}
1432
1433impl From<Quat> for [f32; 4] {
1434    #[inline]
1435    fn from(q: Quat) -> Self {
1436        Vec4::from(q).into()
1437    }
1438}
1439
1440impl From<Quat> for __m128 {
1441    #[inline]
1442    fn from(q: Quat) -> Self {
1443        q.0
1444    }
1445}
1446
1447impl Deref for Quat {
1448    type Target = crate::deref::Vec4<f32>;
1449    #[inline]
1450    fn deref(&self) -> &Self::Target {
1451        unsafe { &*(self as *const Self).cast() }
1452    }
1453}
1454
1455impl DerefMut for Quat {
1456    #[inline]
1457    fn deref_mut(&mut self) -> &mut Self::Target {
1458        unsafe { &mut *(self as *mut Self).cast() }
1459    }
1460}