glam/f32/neon/
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    neon::*,
7    DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8};
9
10use core::arch::aarch64::*;
11
12use core::fmt;
13use core::iter::{Product, Sum};
14use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
15
16#[repr(C)]
17union UnionCast {
18    a: [f32; 4],
19    v: Quat,
20}
21
22/// Creates a quaternion from `x`, `y`, `z` and `w` values.
23///
24/// This should generally not be called manually unless you know what you are doing. Use
25/// one of the other constructors instead such as `identity` or `from_axis_angle`.
26#[inline]
27#[must_use]
28pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
29    Quat::from_xyzw(x, y, z, w)
30}
31
32/// A quaternion representing an orientation.
33///
34/// This quaternion is intended to be of unit length but may denormalize due to
35/// floating point "error creep" which can occur when successive quaternion
36/// operations are applied.
37///
38/// SIMD vector types are used for storage on supported platforms.
39///
40/// This type is 16 byte aligned.
41#[derive(Clone, Copy)]
42#[repr(transparent)]
43pub struct Quat(pub(crate) float32x4_t);
44
45impl Quat {
46    /// All zeros.
47    const ZERO: Self = Self::from_array([0.0; 4]);
48
49    /// The identity quaternion. Corresponds to no rotation.
50    pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
51
52    /// All NANs.
53    pub const NAN: Self = Self::from_array([f32::NAN; 4]);
54
55    /// Creates a new rotation quaternion.
56    ///
57    /// This should generally not be called manually unless you know what you are doing.
58    /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
59    ///
60    /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
61    ///
62    /// # Preconditions
63    ///
64    /// This function does not check if the input is normalized, it is up to the user to
65    /// provide normalized input or to normalized the resulting quaternion.
66    #[inline(always)]
67    #[must_use]
68    pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
69        unsafe { UnionCast { a: [x, y, z, w] }.v }
70    }
71
72    /// Creates a rotation quaternion from an array.
73    ///
74    /// # Preconditions
75    ///
76    /// This function does not check if the input is normalized, it is up to the user to
77    /// provide normalized input or to normalized the resulting quaternion.
78    #[inline]
79    #[must_use]
80    pub const fn from_array(a: [f32; 4]) -> Self {
81        Self::from_xyzw(a[0], a[1], a[2], a[3])
82    }
83
84    /// Creates a new rotation quaternion from a 4D vector.
85    ///
86    /// # Preconditions
87    ///
88    /// This function does not check if the input is normalized, it is up to the user to
89    /// provide normalized input or to normalized the resulting quaternion.
90    #[inline]
91    #[must_use]
92    pub const fn from_vec4(v: Vec4) -> Self {
93        Self(v.0)
94    }
95
96    /// Creates a rotation quaternion from a slice.
97    ///
98    /// # Preconditions
99    ///
100    /// This function does not check if the input is normalized, it is up to the user to
101    /// provide normalized input or to normalized the resulting quaternion.
102    ///
103    /// # Panics
104    ///
105    /// Panics if `slice` length is less than 4.
106    #[inline]
107    #[must_use]
108    pub fn from_slice(slice: &[f32]) -> Self {
109        assert!(slice.len() >= 4);
110        Self(unsafe { vld1q_f32(slice.as_ptr()) })
111    }
112
113    /// Writes the quaternion to an unaligned slice.
114    ///
115    /// # Panics
116    ///
117    /// Panics if `slice` length is less than 4.
118    #[inline]
119    pub fn write_to_slice(self, slice: &mut [f32]) {
120        assert!(slice.len() >= 4);
121        unsafe { vst1q_f32(slice.as_mut_ptr(), self.0) }
122    }
123
124    /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
125    ///
126    /// The axis must be a unit vector.
127    ///
128    /// # Panics
129    ///
130    /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
131    #[inline]
132    #[must_use]
133    pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
134        glam_assert!(axis.is_normalized());
135        let (s, c) = math::sin_cos(angle * 0.5);
136        let v = axis * s;
137        Self::from_xyzw(v.x, v.y, v.z, c)
138    }
139
140    /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
141    ///
142    /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
143    #[inline]
144    #[must_use]
145    pub fn from_scaled_axis(v: Vec3) -> Self {
146        let length = v.length();
147        if length == 0.0 {
148            Self::IDENTITY
149        } else {
150            Self::from_axis_angle(v / length, length)
151        }
152    }
153
154    /// Creates a quaternion from the `angle` (in radians) around the x axis.
155    #[inline]
156    #[must_use]
157    pub fn from_rotation_x(angle: f32) -> Self {
158        let (s, c) = math::sin_cos(angle * 0.5);
159        Self::from_xyzw(s, 0.0, 0.0, c)
160    }
161
162    /// Creates a quaternion from the `angle` (in radians) around the y axis.
163    #[inline]
164    #[must_use]
165    pub fn from_rotation_y(angle: f32) -> Self {
166        let (s, c) = math::sin_cos(angle * 0.5);
167        Self::from_xyzw(0.0, s, 0.0, c)
168    }
169
170    /// Creates a quaternion from the `angle` (in radians) around the z axis.
171    #[inline]
172    #[must_use]
173    pub fn from_rotation_z(angle: f32) -> Self {
174        let (s, c) = math::sin_cos(angle * 0.5);
175        Self::from_xyzw(0.0, 0.0, s, c)
176    }
177
178    /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
179    #[inline]
180    #[must_use]
181    pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
182        Self::from_euler_angles(euler, a, b, c)
183    }
184
185    /// From the columns of a 3x3 rotation matrix.
186    ///
187    /// Note if the input axes contain scales, shears, or other non-rotation transformations then
188    /// the output of this function is ill-defined.
189    ///
190    /// # Panics
191    ///
192    /// Will panic if any axis is not normalized when `glam_assert` is enabled.
193    #[inline]
194    #[must_use]
195    pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
196        glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized());
197        // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix`
198        let (m00, m01, m02) = x_axis.into();
199        let (m10, m11, m12) = y_axis.into();
200        let (m20, m21, m22) = z_axis.into();
201        if m22 <= 0.0 {
202            // x^2 + y^2 >= z^2 + w^2
203            let dif10 = m11 - m00;
204            let omm22 = 1.0 - m22;
205            if dif10 <= 0.0 {
206                // x^2 >= y^2
207                let four_xsq = omm22 - dif10;
208                let inv4x = 0.5 / math::sqrt(four_xsq);
209                Self::from_xyzw(
210                    four_xsq * inv4x,
211                    (m01 + m10) * inv4x,
212                    (m02 + m20) * inv4x,
213                    (m12 - m21) * inv4x,
214                )
215            } else {
216                // y^2 >= x^2
217                let four_ysq = omm22 + dif10;
218                let inv4y = 0.5 / math::sqrt(four_ysq);
219                Self::from_xyzw(
220                    (m01 + m10) * inv4y,
221                    four_ysq * inv4y,
222                    (m12 + m21) * inv4y,
223                    (m20 - m02) * inv4y,
224                )
225            }
226        } else {
227            // z^2 + w^2 >= x^2 + y^2
228            let sum10 = m11 + m00;
229            let opm22 = 1.0 + m22;
230            if sum10 <= 0.0 {
231                // z^2 >= w^2
232                let four_zsq = opm22 - sum10;
233                let inv4z = 0.5 / math::sqrt(four_zsq);
234                Self::from_xyzw(
235                    (m02 + m20) * inv4z,
236                    (m12 + m21) * inv4z,
237                    four_zsq * inv4z,
238                    (m01 - m10) * inv4z,
239                )
240            } else {
241                // w^2 >= z^2
242                let four_wsq = opm22 + sum10;
243                let inv4w = 0.5 / math::sqrt(four_wsq);
244                Self::from_xyzw(
245                    (m12 - m21) * inv4w,
246                    (m20 - m02) * inv4w,
247                    (m01 - m10) * inv4w,
248                    four_wsq * inv4w,
249                )
250            }
251        }
252    }
253
254    /// Creates a quaternion from a 3x3 rotation matrix.
255    ///
256    /// Note if the input matrix contain scales, shears, or other non-rotation transformations then
257    /// the resulting quaternion will be ill-defined.
258    ///
259    /// # Panics
260    ///
261    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
262    #[inline]
263    #[must_use]
264    pub fn from_mat3(mat: &Mat3) -> Self {
265        Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
266    }
267
268    /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
269    ///
270    /// Note if the input matrix contain scales, shears, or other non-rotation transformations then
271    /// the resulting quaternion will be ill-defined.
272    ///
273    /// # Panics
274    ///
275    /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled.
276    #[inline]
277    #[must_use]
278    pub fn from_mat3a(mat: &Mat3A) -> Self {
279        Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
280    }
281
282    /// Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix.
283    ///
284    /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations
285    /// then the resulting quaternion will be ill-defined.
286    ///
287    /// # Panics
288    ///
289    /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when
290    /// `glam_assert` is enabled.
291    #[inline]
292    #[must_use]
293    pub fn from_mat4(mat: &Mat4) -> Self {
294        Self::from_rotation_axes(
295            mat.x_axis.truncate(),
296            mat.y_axis.truncate(),
297            mat.z_axis.truncate(),
298        )
299    }
300
301    /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
302    /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
303    ///
304    /// The inputs must be unit vectors.
305    ///
306    /// `from_rotation_arc(from, to) * from ≈ to`.
307    ///
308    /// For near-singular cases (from≈to and from≈-to) the current implementation
309    /// is only accurate to about 0.001 (for `f32`).
310    ///
311    /// # Panics
312    ///
313    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
314    #[must_use]
315    pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
316        glam_assert!(from.is_normalized());
317        glam_assert!(to.is_normalized());
318
319        const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON;
320        let dot = from.dot(to);
321        if dot > ONE_MINUS_EPS {
322            // 0° singularity: from ≈ to
323            Self::IDENTITY
324        } else if dot < -ONE_MINUS_EPS {
325            // 180° singularity: from ≈ -to
326            use core::f32::consts::PI; // half a turn = 𝛕/2 = 180°
327            Self::from_axis_angle(from.any_orthonormal_vector(), PI)
328        } else {
329            let c = from.cross(to);
330            Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
331        }
332    }
333
334    /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
335    /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
336    ///
337    /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
338    /// degrees.
339    ///
340    /// The inputs must be unit vectors.
341    ///
342    /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
343    ///
344    /// # Panics
345    ///
346    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
347    #[inline]
348    #[must_use]
349    pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
350        if from.dot(to) < 0.0 {
351            Self::from_rotation_arc(from, -to)
352        } else {
353            Self::from_rotation_arc(from, to)
354        }
355    }
356
357    /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
358    /// around the z axis. Will rotate at most 180 degrees.
359    ///
360    /// The inputs must be unit vectors.
361    ///
362    /// `from_rotation_arc_2d(from, to) * from ≈ to`.
363    ///
364    /// For near-singular cases (from≈to and from≈-to) the current implementation
365    /// is only accurate to about 0.001 (for `f32`).
366    ///
367    /// # Panics
368    ///
369    /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
370    #[must_use]
371    pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
372        glam_assert!(from.is_normalized());
373        glam_assert!(to.is_normalized());
374
375        const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON;
376        let dot = from.dot(to);
377        if dot > ONE_MINUS_EPSILON {
378            // 0° singularity: from ≈ to
379            Self::IDENTITY
380        } else if dot < -ONE_MINUS_EPSILON {
381            // 180° singularity: from ≈ -to
382            const COS_FRAC_PI_2: f32 = 0.0;
383            const SIN_FRAC_PI_2: f32 = 1.0;
384            // rotation around z by PI radians
385            Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
386        } else {
387            // vector3 cross where z=0
388            let z = from.x * to.y - to.x * from.y;
389            let w = 1.0 + dot;
390            // calculate length with x=0 and y=0 to normalize
391            let len_rcp = 1.0 / math::sqrt(z * z + w * w);
392            Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
393        }
394    }
395
396    /// Creates a quaterion rotation from a facing direction and an up direction.
397    ///
398    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
399    ///
400    /// # Panics
401    ///
402    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
403    #[inline]
404    #[must_use]
405    pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self {
406        Self::look_to_rh(-dir, up)
407    }
408
409    /// Creates a quaterion rotation from facing direction and an up direction.
410    ///
411    /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.
412    ///
413    /// # Panics
414    ///
415    /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled.
416    #[inline]
417    #[must_use]
418    pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self {
419        glam_assert!(dir.is_normalized());
420        glam_assert!(up.is_normalized());
421        let f = dir;
422        let s = f.cross(up).normalize();
423        let u = s.cross(f);
424
425        Self::from_rotation_axes(
426            Vec3::new(s.x, u.x, -f.x),
427            Vec3::new(s.y, u.y, -f.y),
428            Vec3::new(s.z, u.z, -f.z),
429        )
430    }
431
432    /// Creates a left-handed view matrix using a camera position, a focal point, and an up
433    /// direction.
434    ///
435    /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.
436    ///
437    /// # Panics
438    ///
439    /// Will panic if `up` is not normalized when `glam_assert` is enabled.
440    #[inline]
441    #[must_use]
442    pub fn look_at_lh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
443        Self::look_to_lh(center.sub(eye).normalize(), up)
444    }
445
446    /// Creates a right-handed view matrix using a camera position, an up direction, and a focal
447    /// point.
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 `up` is not normalized when `glam_assert` is enabled.
454    #[inline]
455    pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self {
456        Self::look_to_rh(center.sub(eye).normalize(), up)
457    }
458
459    /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
460    #[inline]
461    #[must_use]
462    pub fn to_axis_angle(self) -> (Vec3, f32) {
463        const EPSILON: f32 = 1.0e-8;
464        let v = Vec3::new(self.x, self.y, self.z);
465        let length = v.length();
466        if length >= EPSILON {
467            let angle = 2.0 * math::atan2(length, self.w);
468            let axis = v / length;
469            (axis, angle)
470        } else {
471            (Vec3::X, 0.0)
472        }
473    }
474
475    /// Returns the rotation axis scaled by the rotation in radians.
476    #[inline]
477    #[must_use]
478    pub fn to_scaled_axis(self) -> Vec3 {
479        let (axis, angle) = self.to_axis_angle();
480        axis * angle
481    }
482
483    /// Returns the rotation angles for the given euler rotation sequence.
484    #[inline]
485    #[must_use]
486    pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) {
487        self.to_euler_angles(order)
488    }
489
490    /// `[x, y, z, w]`
491    #[inline]
492    #[must_use]
493    pub fn to_array(&self) -> [f32; 4] {
494        [self.x, self.y, self.z, self.w]
495    }
496
497    /// Returns the vector part of the quaternion.
498    #[inline]
499    #[must_use]
500    pub fn xyz(self) -> Vec3 {
501        Vec3::new(self.x, self.y, self.z)
502    }
503
504    /// Returns the quaternion conjugate of `self`. For a unit quaternion the
505    /// conjugate is also the inverse.
506    #[inline]
507    #[must_use]
508    pub fn conjugate(self) -> Self {
509        const SIGN: float32x4_t = f32x4_from_array([-1.0, -1.0, -1.0, 1.0]);
510        Self(unsafe { vmulq_f32(self.0, SIGN) })
511    }
512
513    /// Returns the inverse of a normalized quaternion.
514    ///
515    /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
516    /// Because `self` is assumed to already be unit length this method *does not* normalize
517    /// before returning the conjugate.
518    ///
519    /// # Panics
520    ///
521    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
522    #[inline]
523    #[must_use]
524    pub fn inverse(self) -> Self {
525        glam_assert!(self.is_normalized());
526        self.conjugate()
527    }
528
529    /// Computes the dot product of `self` and `rhs`. The dot product is
530    /// equal to the cosine of the angle between two quaternion rotations.
531    #[inline]
532    #[must_use]
533    pub fn dot(self, rhs: Self) -> f32 {
534        Vec4::from(self).dot(Vec4::from(rhs))
535    }
536
537    /// Computes the length of `self`.
538    #[doc(alias = "magnitude")]
539    #[inline]
540    #[must_use]
541    pub fn length(self) -> f32 {
542        Vec4::from(self).length()
543    }
544
545    /// Computes the squared length of `self`.
546    ///
547    /// This is generally faster than `length()` as it avoids a square
548    /// root operation.
549    #[doc(alias = "magnitude2")]
550    #[inline]
551    #[must_use]
552    pub fn length_squared(self) -> f32 {
553        Vec4::from(self).length_squared()
554    }
555
556    /// Computes `1.0 / length()`.
557    ///
558    /// For valid results, `self` must _not_ be of length zero.
559    #[inline]
560    #[must_use]
561    pub fn length_recip(self) -> f32 {
562        Vec4::from(self).length_recip()
563    }
564
565    /// Returns `self` normalized to length 1.0.
566    ///
567    /// For valid results, `self` must _not_ be of length zero.
568    ///
569    /// Panics
570    ///
571    /// Will panic if `self` is zero length when `glam_assert` is enabled.
572    #[inline]
573    #[must_use]
574    pub fn normalize(self) -> Self {
575        Self::from_vec4(Vec4::from(self).normalize())
576    }
577
578    /// Returns `true` if, and only if, all elements are finite.
579    /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
580    #[inline]
581    #[must_use]
582    pub fn is_finite(self) -> bool {
583        Vec4::from(self).is_finite()
584    }
585
586    /// Returns `true` if any elements are `NAN`.
587    #[inline]
588    #[must_use]
589    pub fn is_nan(self) -> bool {
590        Vec4::from(self).is_nan()
591    }
592
593    /// Returns whether `self` of length `1.0` or not.
594    ///
595    /// Uses a precision threshold of `1e-6`.
596    #[inline]
597    #[must_use]
598    pub fn is_normalized(self) -> bool {
599        Vec4::from(self).is_normalized()
600    }
601
602    #[inline]
603    #[must_use]
604    pub fn is_near_identity(self) -> bool {
605        // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
606        let threshold_angle = 0.002_847_144_6;
607        // Because of floating point precision, we cannot represent very small rotations.
608        // The closest f32 to 1.0 that is not 1.0 itself yields:
609        // 0.99999994.acos() * 2.0  = 0.000690533954 rad
610        //
611        // An error threshold of 1.e-6 is used by default.
612        // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
613        // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
614        //
615        // We don't really care about the angle value itself, only if it's close to 0.
616        // This will happen whenever quat.w is close to 1.0.
617        // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
618        // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
619        // the shortest path.
620        let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
621        positive_w_angle < threshold_angle
622    }
623
624    /// Returns the angle (in radians) for the minimal rotation
625    /// for transforming this quaternion into another.
626    ///
627    /// Both quaternions must be normalized.
628    ///
629    /// # Panics
630    ///
631    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
632    #[inline]
633    #[must_use]
634    pub fn angle_between(self, rhs: Self) -> f32 {
635        glam_assert!(self.is_normalized() && rhs.is_normalized());
636        math::acos_approx(math::abs(self.dot(rhs))) * 2.0
637    }
638
639    /// Rotates towards `rhs` up to `max_angle` (in radians).
640    ///
641    /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
642    /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative,
643    /// rotates towards the exact opposite of `rhs`. Will not go past the target.
644    ///
645    /// Both quaternions must be normalized.
646    ///
647    /// # Panics
648    ///
649    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
650    #[inline]
651    #[must_use]
652    pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self {
653        glam_assert!(self.is_normalized() && rhs.is_normalized());
654        let angle = self.angle_between(rhs);
655        if angle <= 1e-4 {
656            return rhs;
657        }
658        let s = (max_angle / angle).clamp(-1.0, 1.0);
659        self.slerp(rhs, s)
660    }
661
662    /// Returns true if the absolute difference of all elements between `self` and `rhs`
663    /// is less than or equal to `max_abs_diff`.
664    ///
665    /// This can be used to compare if two quaternions contain similar elements. It works
666    /// best when comparing with a known value. The `max_abs_diff` that should be used used
667    /// depends on the values being compared against.
668    ///
669    /// For more see
670    /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
671    #[inline]
672    #[must_use]
673    pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
674        Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
675    }
676
677    #[inline(always)]
678    #[must_use]
679    fn lerp_impl(self, end: Self, s: f32) -> Self {
680        (self * (1.0 - s) + end * s).normalize()
681    }
682
683    /// Performs a linear interpolation between `self` and `rhs` based on
684    /// the value `s`.
685    ///
686    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
687    /// is `1.0`, the result will be equal to `rhs`.
688    ///
689    /// # Panics
690    ///
691    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
692    #[doc(alias = "mix")]
693    #[inline]
694    #[must_use]
695    pub fn lerp(self, end: Self, s: f32) -> Self {
696        glam_assert!(self.is_normalized());
697        glam_assert!(end.is_normalized());
698
699        const NEG_ZERO: float32x4_t = f32x4_from_array([-0.0; 4]);
700        unsafe {
701            let dot = dot4_into_f32x4(self.0, end.0);
702            // Calculate the bias, if the dot product is positive or zero, there is no bias
703            // but if it is negative, we want to flip the 'end' rotation XYZW components
704            let bias = vandq_u32(vreinterpretq_u32_f32(dot), vreinterpretq_u32_f32(NEG_ZERO));
705            self.lerp_impl(
706                Self(vreinterpretq_f32_u32(veorq_u32(
707                    vreinterpretq_u32_f32(end.0),
708                    bias,
709                ))),
710                s,
711            )
712        }
713    }
714
715    /// Performs a spherical linear interpolation between `self` and `end`
716    /// based on the value `s`.
717    ///
718    /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
719    /// is `1.0`, the result will be equal to `end`.
720    ///
721    /// # Panics
722    ///
723    /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
724    #[inline]
725    #[must_use]
726    pub fn slerp(self, mut end: Self, s: f32) -> Self {
727        // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
728        glam_assert!(self.is_normalized());
729        glam_assert!(end.is_normalized());
730
731        // Note that a rotation can be represented by two quaternions: `q` and
732        // `-q`. The slerp path between `q` and `end` will be different from the
733        // path between `-q` and `end`. One path will take the long way around and
734        // one will take the short way. In order to correct for this, the `dot`
735        // product between `self` and `end` should be positive. If the `dot`
736        // product is negative, slerp between `self` and `-end`.
737        let mut dot = self.dot(end);
738        if dot < 0.0 {
739            end = -end;
740            dot = -dot;
741        }
742
743        const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON;
744        if dot > DOT_THRESHOLD {
745            // if above threshold perform linear interpolation to avoid divide by zero
746            self.lerp_impl(end, s)
747        } else {
748            let theta = math::acos_approx(dot);
749
750            let scale1 = math::sin(theta * (1.0 - s));
751            let scale2 = math::sin(theta * s);
752            let theta_sin = math::sin(theta);
753            ((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
754        }
755    }
756
757    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
758    ///
759    /// # Panics
760    ///
761    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
762    #[inline]
763    #[must_use]
764    pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
765        glam_assert!(self.is_normalized());
766
767        self.mul_vec3a(rhs.into()).into()
768    }
769
770    /// Multiplies two quaternions. If they each represent a rotation, the result will
771    /// represent the combined rotation.
772    ///
773    /// Note that due to floating point rounding the result may not be perfectly normalized.
774    ///
775    /// # Panics
776    ///
777    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
778    #[inline]
779    #[must_use]
780    pub fn mul_quat(self, rhs: Self) -> Self {
781        unsafe {
782            let lhs = self.0;
783            let rhs = rhs.0;
784
785            const CONTROL_WZYX: float32x4_t = f32x4_from_array([1.0, -1.0, 1.0, -1.0]);
786            const CONTROL_ZWXY: float32x4_t = f32x4_from_array([1.0, 1.0, -1.0, -1.0]);
787            const CONTROL_YXWZ: float32x4_t = f32x4_from_array([-1.0, 1.0, 1.0, -1.0]);
788
789            let r_xxxx = vdupq_laneq_f32(lhs, 0);
790            let r_yyyy = vdupq_laneq_f32(lhs, 1);
791            let r_zzzz = vdupq_laneq_f32(lhs, 2);
792            let r_wwww = vdupq_laneq_f32(lhs, 3);
793
794            let lxrw_lyrw_lzrw_lwrw = vmulq_f32(r_wwww, rhs);
795            //let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]);
796            let l_wzyx = vrev64q_f32(rhs);
797            let l_wzyx = vextq_f32(l_wzyx, l_wzyx, 2);
798
799            let lwrx_lzrx_lyrx_lxrx = vmulq_f32(r_xxxx, l_wzyx);
800            //let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]);
801            let l_zwxy = vrev64q_f32(l_wzyx);
802
803            let lwrx_nlzrx_lyrx_nlxrx = vmulq_f32(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
804
805            let lzry_lwry_lxry_lyry = vmulq_f32(r_yyyy, l_zwxy);
806            // let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]);
807            let l_yxwz = vrev64q_f32(l_zwxy);
808            let l_yxwz = vextq_f32(l_yxwz, l_yxwz, 2);
809
810            let lzry_lwry_nlxry_nlyry = vmulq_f32(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
811
812            let lyrz_lxrz_lwrz_lzrz = vmulq_f32(r_zzzz, l_yxwz);
813            let result0 = vaddq_f32(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
814
815            let nlyrz_lxrz_lwrz_wlzrz = vmulq_f32(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
816            let result1 = vaddq_f32(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
817            Self(vaddq_f32(result0, result1))
818        }
819    }
820
821    /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
822    ///
823    /// Note if the input affine matrix contain scales, shears, or other non-rotation
824    /// transformations then the resulting quaternion will be ill-defined.
825    ///
826    /// # Panics
827    ///
828    /// Will panic if any input affine matrix column is not normalized when `glam_assert` is
829    /// enabled.
830    #[inline]
831    #[must_use]
832    pub fn from_affine3(a: &crate::Affine3A) -> Self {
833        #[allow(clippy::useless_conversion)]
834        Self::from_rotation_axes(
835            a.matrix3.x_axis.into(),
836            a.matrix3.y_axis.into(),
837            a.matrix3.z_axis.into(),
838        )
839    }
840
841    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
842    #[inline]
843    #[must_use]
844    pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
845        unsafe {
846            let w = self.w;
847            let b = Vec3A::from(self.0);
848            let b2 = b.length_squared();
849            Vec3A(vaddq_f32(
850                vaddq_f32(
851                    vmulq_n_f32(rhs.0, (w * w) - b2),
852                    vmulq_n_f32(b.0, rhs.dot(b) * 2.0),
853                ),
854                vmulq_n_f32(b.cross(rhs).0, w * 2.0),
855            ))
856        }
857    }
858
859    #[inline]
860    #[must_use]
861    pub fn as_dquat(self) -> DQuat {
862        DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
863    }
864}
865
866impl fmt::Debug for Quat {
867    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
868        fmt.debug_tuple(stringify!(Quat))
869            .field(&self.x)
870            .field(&self.y)
871            .field(&self.z)
872            .field(&self.w)
873            .finish()
874    }
875}
876
877impl fmt::Display for Quat {
878    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
879        if let Some(p) = f.precision() {
880            write!(
881                f,
882                "[{:.*}, {:.*}, {:.*}, {:.*}]",
883                p, self.x, p, self.y, p, self.z, p, self.w
884            )
885        } else {
886            write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
887        }
888    }
889}
890
891impl Add<Quat> for Quat {
892    type Output = Self;
893    /// Adds two quaternions.
894    ///
895    /// The sum is not guaranteed to be normalized.
896    ///
897    /// Note that addition is not the same as combining the rotations represented by the
898    /// two quaternions! That corresponds to multiplication.
899    #[inline]
900    fn add(self, rhs: Self) -> Self {
901        Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
902    }
903}
904
905impl Sub<Quat> for Quat {
906    type Output = Self;
907    /// Subtracts the `rhs` quaternion from `self`.
908    ///
909    /// The difference is not guaranteed to be normalized.
910    #[inline]
911    fn sub(self, rhs: Self) -> Self {
912        Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
913    }
914}
915
916impl Mul<f32> for Quat {
917    type Output = Self;
918    /// Multiplies a quaternion by a scalar value.
919    ///
920    /// The product is not guaranteed to be normalized.
921    #[inline]
922    fn mul(self, rhs: f32) -> Self {
923        Self::from_vec4(Vec4::from(self) * rhs)
924    }
925}
926
927impl Div<f32> for Quat {
928    type Output = Self;
929    /// Divides a quaternion by a scalar value.
930    /// The quotient is not guaranteed to be normalized.
931    #[inline]
932    fn div(self, rhs: f32) -> Self {
933        Self::from_vec4(Vec4::from(self) / rhs)
934    }
935}
936
937impl Mul<Quat> for Quat {
938    type Output = Self;
939    /// Multiplies two quaternions. If they each represent a rotation, the result will
940    /// represent the combined rotation.
941    ///
942    /// Note that due to floating point rounding the result may not be perfectly
943    /// normalized.
944    ///
945    /// # Panics
946    ///
947    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
948    #[inline]
949    fn mul(self, rhs: Self) -> Self {
950        self.mul_quat(rhs)
951    }
952}
953
954impl MulAssign<Quat> for Quat {
955    /// Multiplies two quaternions. If they each represent a rotation, the result will
956    /// represent the combined rotation.
957    ///
958    /// Note that due to floating point rounding the result may not be perfectly
959    /// normalized.
960    ///
961    /// # Panics
962    ///
963    /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
964    #[inline]
965    fn mul_assign(&mut self, rhs: Self) {
966        *self = self.mul_quat(rhs);
967    }
968}
969
970impl Mul<Vec3> for Quat {
971    type Output = Vec3;
972    /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
973    ///
974    /// # Panics
975    ///
976    /// Will panic if `self` is not normalized when `glam_assert` is enabled.
977    #[inline]
978    fn mul(self, rhs: Vec3) -> Self::Output {
979        self.mul_vec3(rhs)
980    }
981}
982
983impl Neg for Quat {
984    type Output = Self;
985    #[inline]
986    fn neg(self) -> Self {
987        self * -1.0
988    }
989}
990
991impl Default for Quat {
992    #[inline]
993    fn default() -> Self {
994        Self::IDENTITY
995    }
996}
997
998impl PartialEq for Quat {
999    #[inline]
1000    fn eq(&self, rhs: &Self) -> bool {
1001        Vec4::from(*self).eq(&Vec4::from(*rhs))
1002    }
1003}
1004
1005#[cfg(not(target_arch = "spirv"))]
1006impl AsRef<[f32; 4]> for Quat {
1007    #[inline]
1008    fn as_ref(&self) -> &[f32; 4] {
1009        unsafe { &*(self as *const Self as *const [f32; 4]) }
1010    }
1011}
1012
1013impl Sum<Self> for Quat {
1014    fn sum<I>(iter: I) -> Self
1015    where
1016        I: Iterator<Item = Self>,
1017    {
1018        iter.fold(Self::ZERO, Self::add)
1019    }
1020}
1021
1022impl<'a> Sum<&'a Self> for Quat {
1023    fn sum<I>(iter: I) -> Self
1024    where
1025        I: Iterator<Item = &'a Self>,
1026    {
1027        iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1028    }
1029}
1030
1031impl Product for Quat {
1032    fn product<I>(iter: I) -> Self
1033    where
1034        I: Iterator<Item = Self>,
1035    {
1036        iter.fold(Self::IDENTITY, Self::mul)
1037    }
1038}
1039
1040impl<'a> Product<&'a Self> for Quat {
1041    fn product<I>(iter: I) -> Self
1042    where
1043        I: Iterator<Item = &'a Self>,
1044    {
1045        iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1046    }
1047}
1048
1049impl Mul<Vec3A> for Quat {
1050    type Output = Vec3A;
1051    #[inline]
1052    fn mul(self, rhs: Vec3A) -> Self::Output {
1053        self.mul_vec3a(rhs)
1054    }
1055}
1056
1057impl From<Quat> for Vec4 {
1058    #[inline]
1059    fn from(q: Quat) -> Self {
1060        Self(q.0)
1061    }
1062}
1063
1064impl From<Quat> for (f32, f32, f32, f32) {
1065    #[inline]
1066    fn from(q: Quat) -> Self {
1067        Vec4::from(q).into()
1068    }
1069}
1070
1071impl From<Quat> for [f32; 4] {
1072    #[inline]
1073    fn from(q: Quat) -> Self {
1074        Vec4::from(q).into()
1075    }
1076}
1077
1078impl From<Quat> for float32x4_t {
1079    #[inline]
1080    fn from(q: Quat) -> Self {
1081        q.0
1082    }
1083}
1084
1085impl Deref for Quat {
1086    type Target = crate::deref::Vec4<f32>;
1087    #[inline]
1088    fn deref(&self) -> &Self::Target {
1089        unsafe { &*(self as *const Self).cast() }
1090    }
1091}
1092
1093impl DerefMut for Quat {
1094    #[inline]
1095    fn deref_mut(&mut self) -> &mut Self::Target {
1096        unsafe { &mut *(self as *mut Self).cast() }
1097    }
1098}