1 // Generated from quat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{
4     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
5     f32::math,
6     sse2::*,
7     DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4,
8 };
9 
10 #[cfg(target_arch = "x86")]
11 use core::arch::x86::*;
12 #[cfg(target_arch = "x86_64")]
13 use core::arch::x86_64::*;
14 
15 #[cfg(not(target_arch = "spirv"))]
16 use core::fmt;
17 use core::iter::{Product, Sum};
18 use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
19 
20 #[repr(C)]
21 union UnionCast {
22     a: [f32; 4],
23     v: Quat,
24 }
25 
26 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
27 ///
28 /// This should generally not be called manually unless you know what you are doing. Use
29 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
30 #[inline]
31 #[must_use]
quat(x: f32, y: f32, z: f32, w: f32) -> Quat32 pub const fn quat(x: f32, y: f32, z: f32, w: f32) -> Quat {
33     Quat::from_xyzw(x, y, z, w)
34 }
35 
36 /// A quaternion representing an orientation.
37 ///
38 /// This quaternion is intended to be of unit length but may denormalize due to
39 /// floating point "error creep" which can occur when successive quaternion
40 /// operations are applied.
41 ///
42 /// SIMD vector types are used for storage on supported platforms.
43 ///
44 /// This type is 16 byte aligned.
45 #[derive(Clone, Copy)]
46 #[repr(transparent)]
47 pub struct Quat(pub(crate) __m128);
48 
49 impl Quat {
50     /// All zeros.
51     const ZERO: Self = Self::from_array([0.0; 4]);
52 
53     /// The identity quaternion. Corresponds to no rotation.
54     pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
55 
56     /// All NANs.
57     pub const NAN: Self = Self::from_array([f32::NAN; 4]);
58 
59     /// Creates a new rotation quaternion.
60     ///
61     /// This should generally not be called manually unless you know what you are doing.
62     /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
63     ///
64     /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
65     ///
66     /// # Preconditions
67     ///
68     /// This function does not check if the input is normalized, it is up to the user to
69     /// provide normalized input or to normalized the resulting quaternion.
70     #[inline(always)]
71     #[must_use]
from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self72     pub const fn from_xyzw(x: f32, y: f32, z: f32, w: f32) -> Self {
73         unsafe { UnionCast { a: [x, y, z, w] }.v }
74     }
75 
76     /// Creates a rotation quaternion from an array.
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]
83     #[must_use]
from_array(a: [f32; 4]) -> Self84     pub const fn from_array(a: [f32; 4]) -> Self {
85         Self::from_xyzw(a[0], a[1], a[2], a[3])
86     }
87 
88     /// Creates a new rotation quaternion from a 4D vector.
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]
from_vec4(v: Vec4) -> Self96     pub const fn from_vec4(v: Vec4) -> Self {
97         Self(v.0)
98     }
99 
100     /// Creates a rotation quaternion from a slice.
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     ///
107     /// # Panics
108     ///
109     /// Panics if `slice` length is less than 4.
110     #[inline]
111     #[must_use]
from_slice(slice: &[f32]) -> Self112     pub fn from_slice(slice: &[f32]) -> Self {
113         assert!(slice.len() >= 4);
114         Self(unsafe { _mm_loadu_ps(slice.as_ptr()) })
115     }
116 
117     /// Writes the quaternion to an unaligned slice.
118     ///
119     /// # Panics
120     ///
121     /// Panics if `slice` length is less than 4.
122     #[inline]
write_to_slice(self, slice: &mut [f32])123     pub fn write_to_slice(self, slice: &mut [f32]) {
124         assert!(slice.len() >= 4);
125         unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0) }
126     }
127 
128     /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians).
129     ///
130     /// The axis must be a unit vector.
131     ///
132     /// # Panics
133     ///
134     /// Will panic if `axis` is not normalized when `glam_assert` is enabled.
135     #[inline]
136     #[must_use]
from_axis_angle(axis: Vec3, angle: f32) -> Self137     pub fn from_axis_angle(axis: Vec3, angle: f32) -> Self {
138         glam_assert!(axis.is_normalized());
139         let (s, c) = math::sin_cos(angle * 0.5);
140         let v = axis * s;
141         Self::from_xyzw(v.x, v.y, v.z, c)
142     }
143 
144     /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`.
145     ///
146     /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion.
147     #[inline]
148     #[must_use]
from_scaled_axis(v: Vec3) -> Self149     pub fn from_scaled_axis(v: Vec3) -> Self {
150         let length = v.length();
151         if length == 0.0 {
152             Self::IDENTITY
153         } else {
154             Self::from_axis_angle(v / length, length)
155         }
156     }
157 
158     /// Creates a quaternion from the `angle` (in radians) around the x axis.
159     #[inline]
160     #[must_use]
from_rotation_x(angle: f32) -> Self161     pub fn from_rotation_x(angle: f32) -> Self {
162         let (s, c) = math::sin_cos(angle * 0.5);
163         Self::from_xyzw(s, 0.0, 0.0, c)
164     }
165 
166     /// Creates a quaternion from the `angle` (in radians) around the y axis.
167     #[inline]
168     #[must_use]
from_rotation_y(angle: f32) -> Self169     pub fn from_rotation_y(angle: f32) -> Self {
170         let (s, c) = math::sin_cos(angle * 0.5);
171         Self::from_xyzw(0.0, s, 0.0, c)
172     }
173 
174     /// Creates a quaternion from the `angle` (in radians) around the z axis.
175     #[inline]
176     #[must_use]
from_rotation_z(angle: f32) -> Self177     pub fn from_rotation_z(angle: f32) -> Self {
178         let (s, c) = math::sin_cos(angle * 0.5);
179         Self::from_xyzw(0.0, 0.0, s, c)
180     }
181 
182     /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians).
183     #[inline]
184     #[must_use]
from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self185     pub fn from_euler(euler: EulerRot, a: f32, b: f32, c: f32) -> Self {
186         euler.new_quat(a, b, c)
187     }
188 
189     /// From the columns of a 3x3 rotation matrix.
190     #[inline]
191     #[must_use]
from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self192     pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self {
193         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
194         let (m00, m01, m02) = x_axis.into();
195         let (m10, m11, m12) = y_axis.into();
196         let (m20, m21, m22) = z_axis.into();
197         if m22 <= 0.0 {
198             // x^2 + y^2 >= z^2 + w^2
199             let dif10 = m11 - m00;
200             let omm22 = 1.0 - m22;
201             if dif10 <= 0.0 {
202                 // x^2 >= y^2
203                 let four_xsq = omm22 - dif10;
204                 let inv4x = 0.5 / math::sqrt(four_xsq);
205                 Self::from_xyzw(
206                     four_xsq * inv4x,
207                     (m01 + m10) * inv4x,
208                     (m02 + m20) * inv4x,
209                     (m12 - m21) * inv4x,
210                 )
211             } else {
212                 // y^2 >= x^2
213                 let four_ysq = omm22 + dif10;
214                 let inv4y = 0.5 / math::sqrt(four_ysq);
215                 Self::from_xyzw(
216                     (m01 + m10) * inv4y,
217                     four_ysq * inv4y,
218                     (m12 + m21) * inv4y,
219                     (m20 - m02) * inv4y,
220                 )
221             }
222         } else {
223             // z^2 + w^2 >= x^2 + y^2
224             let sum10 = m11 + m00;
225             let opm22 = 1.0 + m22;
226             if sum10 <= 0.0 {
227                 // z^2 >= w^2
228                 let four_zsq = opm22 - sum10;
229                 let inv4z = 0.5 / math::sqrt(four_zsq);
230                 Self::from_xyzw(
231                     (m02 + m20) * inv4z,
232                     (m12 + m21) * inv4z,
233                     four_zsq * inv4z,
234                     (m01 - m10) * inv4z,
235                 )
236             } else {
237                 // w^2 >= z^2
238                 let four_wsq = opm22 + sum10;
239                 let inv4w = 0.5 / math::sqrt(four_wsq);
240                 Self::from_xyzw(
241                     (m12 - m21) * inv4w,
242                     (m20 - m02) * inv4w,
243                     (m01 - m10) * inv4w,
244                     four_wsq * inv4w,
245                 )
246             }
247         }
248     }
249 
250     /// Creates a quaternion from a 3x3 rotation matrix.
251     #[inline]
252     #[must_use]
from_mat3(mat: &Mat3) -> Self253     pub fn from_mat3(mat: &Mat3) -> Self {
254         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
255     }
256 
257     /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix.
258     #[inline]
259     #[must_use]
from_mat3a(mat: &Mat3A) -> Self260     pub fn from_mat3a(mat: &Mat3A) -> Self {
261         Self::from_rotation_axes(mat.x_axis.into(), mat.y_axis.into(), mat.z_axis.into())
262     }
263 
264     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
265     #[inline]
266     #[must_use]
from_mat4(mat: &Mat4) -> Self267     pub fn from_mat4(mat: &Mat4) -> Self {
268         Self::from_rotation_axes(
269             mat.x_axis.truncate(),
270             mat.y_axis.truncate(),
271             mat.z_axis.truncate(),
272         )
273     }
274 
275     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
276     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
277     ///
278     /// The inputs must be unit vectors.
279     ///
280     /// `from_rotation_arc(from, to) * from ≈ to`.
281     ///
282     /// For near-singular cases (from≈to and from≈-to) the current implementation
283     /// is only accurate to about 0.001 (for `f32`).
284     ///
285     /// # Panics
286     ///
287     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
288     #[must_use]
from_rotation_arc(from: Vec3, to: Vec3) -> Self289     pub fn from_rotation_arc(from: Vec3, to: Vec3) -> Self {
290         glam_assert!(from.is_normalized());
291         glam_assert!(to.is_normalized());
292 
293         const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * core::f32::EPSILON;
294         let dot = from.dot(to);
295         if dot > ONE_MINUS_EPS {
296             // 0° singulary: from ≈ to
297             Self::IDENTITY
298         } else if dot < -ONE_MINUS_EPS {
299             // 180° singulary: from ≈ -to
300             use core::f32::consts::PI; // half a turn = ��/2 = 180°
301             Self::from_axis_angle(from.any_orthonormal_vector(), PI)
302         } else {
303             let c = from.cross(to);
304             Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
305         }
306     }
307 
308     /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
309     /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
310     ///
311     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
312     /// degrees.
313     ///
314     /// The inputs must be unit vectors.
315     ///
316     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
317     ///
318     /// # Panics
319     ///
320     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
321     #[inline]
322     #[must_use]
from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self323     pub fn from_rotation_arc_colinear(from: Vec3, to: Vec3) -> Self {
324         if from.dot(to) < 0.0 {
325             Self::from_rotation_arc(from, -to)
326         } else {
327             Self::from_rotation_arc(from, to)
328         }
329     }
330 
331     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
332     /// around the z axis. Will rotate at most 180 degrees.
333     ///
334     /// The inputs must be unit vectors.
335     ///
336     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
337     ///
338     /// For near-singular cases (from≈to and from≈-to) the current implementation
339     /// is only accurate to about 0.001 (for `f32`).
340     ///
341     /// # Panics
342     ///
343     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
344     #[must_use]
from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self345     pub fn from_rotation_arc_2d(from: Vec2, to: Vec2) -> Self {
346         glam_assert!(from.is_normalized());
347         glam_assert!(to.is_normalized());
348 
349         const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * core::f32::EPSILON;
350         let dot = from.dot(to);
351         if dot > ONE_MINUS_EPSILON {
352             // 0° singulary: from ≈ to
353             Self::IDENTITY
354         } else if dot < -ONE_MINUS_EPSILON {
355             // 180° singulary: from ≈ -to
356             const COS_FRAC_PI_2: f32 = 0.0;
357             const SIN_FRAC_PI_2: f32 = 1.0;
358             // rotation around z by PI radians
359             Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
360         } else {
361             // vector3 cross where z=0
362             let z = from.x * to.y - to.x * from.y;
363             let w = 1.0 + dot;
364             // calculate length with x=0 and y=0 to normalize
365             let len_rcp = 1.0 / math::sqrt(z * z + w * w);
366             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
367         }
368     }
369 
370     /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
371     #[inline]
372     #[must_use]
to_axis_angle(self) -> (Vec3, f32)373     pub fn to_axis_angle(self) -> (Vec3, f32) {
374         const EPSILON: f32 = 1.0e-8;
375         let v = Vec3::new(self.x, self.y, self.z);
376         let length = v.length();
377         if length >= EPSILON {
378             let angle = 2.0 * math::atan2(length, self.w);
379             let axis = v / length;
380             (axis, angle)
381         } else {
382             (Vec3::X, 0.0)
383         }
384     }
385 
386     /// Returns the rotation axis scaled by the rotation in radians.
387     #[inline]
388     #[must_use]
to_scaled_axis(self) -> Vec3389     pub fn to_scaled_axis(self) -> Vec3 {
390         let (axis, angle) = self.to_axis_angle();
391         axis * angle
392     }
393 
394     /// Returns the rotation angles for the given euler rotation sequence.
395     #[inline]
396     #[must_use]
to_euler(self, euler: EulerRot) -> (f32, f32, f32)397     pub fn to_euler(self, euler: EulerRot) -> (f32, f32, f32) {
398         euler.convert_quat(self)
399     }
400 
401     /// `[x, y, z, w]`
402     #[inline]
403     #[must_use]
to_array(&self) -> [f32; 4]404     pub fn to_array(&self) -> [f32; 4] {
405         [self.x, self.y, self.z, self.w]
406     }
407 
408     /// Returns the vector part of the quaternion.
409     #[inline]
410     #[must_use]
xyz(self) -> Vec3411     pub fn xyz(self) -> Vec3 {
412         Vec3::new(self.x, self.y, self.z)
413     }
414 
415     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
416     /// conjugate is also the inverse.
417     #[inline]
418     #[must_use]
conjugate(self) -> Self419     pub fn conjugate(self) -> Self {
420         const SIGN: __m128 = m128_from_f32x4([-0.0, -0.0, -0.0, 0.0]);
421         Self(unsafe { _mm_xor_ps(self.0, SIGN) })
422     }
423 
424     /// Returns the inverse of a normalized quaternion.
425     ///
426     /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
427     /// Because `self` is assumed to already be unit length this method *does not* normalize
428     /// before returning the conjugate.
429     ///
430     /// # Panics
431     ///
432     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
433     #[inline]
434     #[must_use]
inverse(self) -> Self435     pub fn inverse(self) -> Self {
436         glam_assert!(self.is_normalized());
437         self.conjugate()
438     }
439 
440     /// Computes the dot product of `self` and `rhs`. The dot product is
441     /// equal to the cosine of the angle between two quaternion rotations.
442     #[inline]
443     #[must_use]
dot(self, rhs: Self) -> f32444     pub fn dot(self, rhs: Self) -> f32 {
445         Vec4::from(self).dot(Vec4::from(rhs))
446     }
447 
448     /// Computes the length of `self`.
449     #[doc(alias = "magnitude")]
450     #[inline]
451     #[must_use]
length(self) -> f32452     pub fn length(self) -> f32 {
453         Vec4::from(self).length()
454     }
455 
456     /// Computes the squared length of `self`.
457     ///
458     /// This is generally faster than `length()` as it avoids a square
459     /// root operation.
460     #[doc(alias = "magnitude2")]
461     #[inline]
462     #[must_use]
length_squared(self) -> f32463     pub fn length_squared(self) -> f32 {
464         Vec4::from(self).length_squared()
465     }
466 
467     /// Computes `1.0 / length()`.
468     ///
469     /// For valid results, `self` must _not_ be of length zero.
470     #[inline]
471     #[must_use]
length_recip(self) -> f32472     pub fn length_recip(self) -> f32 {
473         Vec4::from(self).length_recip()
474     }
475 
476     /// Returns `self` normalized to length 1.0.
477     ///
478     /// For valid results, `self` must _not_ be of length zero.
479     ///
480     /// Panics
481     ///
482     /// Will panic if `self` is zero length when `glam_assert` is enabled.
483     #[inline]
484     #[must_use]
normalize(self) -> Self485     pub fn normalize(self) -> Self {
486         Self::from_vec4(Vec4::from(self).normalize())
487     }
488 
489     /// Returns `true` if, and only if, all elements are finite.
490     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
491     #[inline]
492     #[must_use]
is_finite(self) -> bool493     pub fn is_finite(self) -> bool {
494         Vec4::from(self).is_finite()
495     }
496 
497     #[inline]
498     #[must_use]
is_nan(self) -> bool499     pub fn is_nan(self) -> bool {
500         Vec4::from(self).is_nan()
501     }
502 
503     /// Returns whether `self` of length `1.0` or not.
504     ///
505     /// Uses a precision threshold of `1e-6`.
506     #[inline]
507     #[must_use]
is_normalized(self) -> bool508     pub fn is_normalized(self) -> bool {
509         Vec4::from(self).is_normalized()
510     }
511 
512     #[inline]
513     #[must_use]
is_near_identity(self) -> bool514     pub fn is_near_identity(self) -> bool {
515         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
516         let threshold_angle = 0.002_847_144_6;
517         // Because of floating point precision, we cannot represent very small rotations.
518         // The closest f32 to 1.0 that is not 1.0 itself yields:
519         // 0.99999994.acos() * 2.0  = 0.000690533954 rad
520         //
521         // An error threshold of 1.e-6 is used by default.
522         // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
523         // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
524         //
525         // We don't really care about the angle value itself, only if it's close to 0.
526         // This will happen whenever quat.w is close to 1.0.
527         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
528         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
529         // the shortest path.
530         let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
531         positive_w_angle < threshold_angle
532     }
533 
534     /// Returns the angle (in radians) for the minimal rotation
535     /// for transforming this quaternion into another.
536     ///
537     /// Both quaternions must be normalized.
538     ///
539     /// # Panics
540     ///
541     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
542     #[inline]
543     #[must_use]
angle_between(self, rhs: Self) -> f32544     pub fn angle_between(self, rhs: Self) -> f32 {
545         glam_assert!(self.is_normalized() && rhs.is_normalized());
546         math::acos_approx(math::abs(self.dot(rhs))) * 2.0
547     }
548 
549     /// Returns true if the absolute difference of all elements between `self` and `rhs`
550     /// is less than or equal to `max_abs_diff`.
551     ///
552     /// This can be used to compare if two quaternions contain similar elements. It works
553     /// best when comparing with a known value. The `max_abs_diff` that should be used used
554     /// depends on the values being compared against.
555     ///
556     /// For more see
557     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
558     #[inline]
559     #[must_use]
abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool560     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f32) -> bool {
561         Vec4::from(self).abs_diff_eq(Vec4::from(rhs), max_abs_diff)
562     }
563 
564     /// Performs a linear interpolation between `self` and `rhs` based on
565     /// the value `s`.
566     ///
567     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
568     /// is `1.0`, the result will be equal to `rhs`.
569     ///
570     /// # Panics
571     ///
572     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
573     #[doc(alias = "mix")]
574     #[inline]
575     #[must_use]
lerp(self, end: Self, s: f32) -> Self576     pub fn lerp(self, end: Self, s: f32) -> Self {
577         glam_assert!(self.is_normalized());
578         glam_assert!(end.is_normalized());
579 
580         const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]);
581         let start = self.0;
582         let end = end.0;
583         unsafe {
584             let dot = dot4_into_m128(start, end);
585             // Calculate the bias, if the dot product is positive or zero, there is no bias
586             // but if it is negative, we want to flip the 'end' rotation XYZW components
587             let bias = _mm_and_ps(dot, NEG_ZERO);
588             let interpolated = _mm_add_ps(
589                 _mm_mul_ps(_mm_sub_ps(_mm_xor_ps(end, bias), start), _mm_set_ps1(s)),
590                 start,
591             );
592             Quat(interpolated).normalize()
593         }
594     }
595 
596     /// Performs a spherical linear interpolation between `self` and `end`
597     /// based on the value `s`.
598     ///
599     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
600     /// is `1.0`, the result will be equal to `end`.
601     ///
602     /// # Panics
603     ///
604     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
605     #[inline]
606     #[must_use]
slerp(self, mut end: Self, s: f32) -> Self607     pub fn slerp(self, mut end: Self, s: f32) -> Self {
608         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
609         glam_assert!(self.is_normalized());
610         glam_assert!(end.is_normalized());
611 
612         const DOT_THRESHOLD: f32 = 0.9995;
613 
614         // Note that a rotation can be represented by two quaternions: `q` and
615         // `-q`. The slerp path between `q` and `end` will be different from the
616         // path between `-q` and `end`. One path will take the long way around and
617         // one will take the short way. In order to correct for this, the `dot`
618         // product between `self` and `end` should be positive. If the `dot`
619         // product is negative, slerp between `self` and `-end`.
620         let mut dot = self.dot(end);
621         if dot < 0.0 {
622             end = -end;
623             dot = -dot;
624         }
625 
626         if dot > DOT_THRESHOLD {
627             // assumes lerp returns a normalized quaternion
628             self.lerp(end, s)
629         } else {
630             let theta = math::acos_approx(dot);
631 
632             let x = 1.0 - s;
633             let y = s;
634             let z = 1.0;
635 
636             unsafe {
637                 let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x));
638                 let tmp = m128_sin(tmp);
639 
640                 let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00);
641                 let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01);
642                 let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10);
643 
644                 Self(_mm_div_ps(
645                     _mm_add_ps(_mm_mul_ps(self.0, scale1), _mm_mul_ps(end.0, scale2)),
646                     theta_sin,
647                 ))
648             }
649         }
650     }
651 
652     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
653     ///
654     /// # Panics
655     ///
656     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
657     #[inline]
658     #[must_use]
mul_vec3(self, rhs: Vec3) -> Vec3659     pub fn mul_vec3(self, rhs: Vec3) -> Vec3 {
660         glam_assert!(self.is_normalized());
661 
662         self.mul_vec3a(rhs.into()).into()
663     }
664 
665     /// Multiplies two quaternions. If they each represent a rotation, the result will
666     /// represent the combined rotation.
667     ///
668     /// Note that due to floating point rounding the result may not be perfectly normalized.
669     ///
670     /// # Panics
671     ///
672     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
673     #[inline]
674     #[must_use]
mul_quat(self, rhs: Self) -> Self675     pub fn mul_quat(self, rhs: Self) -> Self {
676         glam_assert!(self.is_normalized());
677         glam_assert!(rhs.is_normalized());
678 
679         // Based on https://github.com/nfrechette/rtm `rtm::quat_mul`
680         const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
681         const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
682         const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]);
683 
684         let lhs = self.0;
685         let rhs = rhs.0;
686 
687         unsafe {
688             let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00);
689             let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01);
690             let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10);
691             let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11);
692 
693             let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs);
694             let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11);
695 
696             let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx);
697             let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01);
698 
699             let lwrx_nlzrx_lyrx_nlxrx = _mm_mul_ps(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX);
700 
701             let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy);
702             let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11);
703 
704             let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY);
705 
706             let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz);
707             let result0 = _mm_add_ps(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx);
708 
709             let nlyrz_lxrz_lwrz_wlzrz = _mm_mul_ps(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ);
710             let result1 = _mm_add_ps(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz);
711 
712             Self(_mm_add_ps(result0, result1))
713         }
714     }
715 
716     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
717     #[inline]
718     #[must_use]
from_affine3(a: &crate::Affine3A) -> Self719     pub fn from_affine3(a: &crate::Affine3A) -> Self {
720         #[allow(clippy::useless_conversion)]
721         Self::from_rotation_axes(
722             a.matrix3.x_axis.into(),
723             a.matrix3.y_axis.into(),
724             a.matrix3.z_axis.into(),
725         )
726     }
727 
728     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
729     #[inline]
730     #[must_use]
mul_vec3a(self, rhs: Vec3A) -> Vec3A731     pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A {
732         unsafe {
733             const TWO: __m128 = m128_from_f32x4([2.0; 4]);
734             let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11);
735             let b = self.0;
736             let b2 = dot3_into_m128(b, b);
737             Vec3A(_mm_add_ps(
738                 _mm_add_ps(
739                     _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)),
740                     _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)),
741                 ),
742                 _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)),
743             ))
744         }
745     }
746 
747     #[inline]
748     #[must_use]
as_dquat(self) -> DQuat749     pub fn as_dquat(self) -> DQuat {
750         DQuat::from_xyzw(self.x as f64, self.y as f64, self.z as f64, self.w as f64)
751     }
752 
753     #[inline]
754     #[must_use]
755     #[deprecated(since = "0.24.2", note = "Use as_dquat() instead")]
as_f64(self) -> DQuat756     pub fn as_f64(self) -> DQuat {
757         self.as_dquat()
758     }
759 }
760 
761 #[cfg(not(target_arch = "spirv"))]
762 impl fmt::Debug for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result763     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
764         fmt.debug_tuple(stringify!(Quat))
765             .field(&self.x)
766             .field(&self.y)
767             .field(&self.z)
768             .field(&self.w)
769             .finish()
770     }
771 }
772 
773 #[cfg(not(target_arch = "spirv"))]
774 impl fmt::Display for Quat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result775     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
776         write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
777     }
778 }
779 
780 impl Add<Quat> for Quat {
781     type Output = Self;
782     /// Adds two quaternions.
783     ///
784     /// The sum is not guaranteed to be normalized.
785     ///
786     /// Note that addition is not the same as combining the rotations represented by the
787     /// two quaternions! That corresponds to multiplication.
788     #[inline]
add(self, rhs: Self) -> Self789     fn add(self, rhs: Self) -> Self {
790         Self::from_vec4(Vec4::from(self) + Vec4::from(rhs))
791     }
792 }
793 
794 impl Sub<Quat> for Quat {
795     type Output = Self;
796     /// Subtracts the `rhs` quaternion from `self`.
797     ///
798     /// The difference is not guaranteed to be normalized.
799     #[inline]
sub(self, rhs: Self) -> Self800     fn sub(self, rhs: Self) -> Self {
801         Self::from_vec4(Vec4::from(self) - Vec4::from(rhs))
802     }
803 }
804 
805 impl Mul<f32> for Quat {
806     type Output = Self;
807     /// Multiplies a quaternion by a scalar value.
808     ///
809     /// The product is not guaranteed to be normalized.
810     #[inline]
mul(self, rhs: f32) -> Self811     fn mul(self, rhs: f32) -> Self {
812         Self::from_vec4(Vec4::from(self) * rhs)
813     }
814 }
815 
816 impl Div<f32> for Quat {
817     type Output = Self;
818     /// Divides a quaternion by a scalar value.
819     /// The quotient is not guaranteed to be normalized.
820     #[inline]
div(self, rhs: f32) -> Self821     fn div(self, rhs: f32) -> Self {
822         Self::from_vec4(Vec4::from(self) / rhs)
823     }
824 }
825 
826 impl Mul<Quat> for Quat {
827     type Output = Self;
828     /// Multiplies two quaternions. If they each represent a rotation, the result will
829     /// represent the combined rotation.
830     ///
831     /// Note that due to floating point rounding the result may not be perfectly
832     /// normalized.
833     ///
834     /// # Panics
835     ///
836     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
837     #[inline]
mul(self, rhs: Self) -> Self838     fn mul(self, rhs: Self) -> Self {
839         self.mul_quat(rhs)
840     }
841 }
842 
843 impl MulAssign<Quat> for Quat {
844     /// Multiplies two quaternions. If they each represent a rotation, the result will
845     /// represent the combined rotation.
846     ///
847     /// Note that due to floating point rounding the result may not be perfectly
848     /// normalized.
849     ///
850     /// # Panics
851     ///
852     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
853     #[inline]
mul_assign(&mut self, rhs: Self)854     fn mul_assign(&mut self, rhs: Self) {
855         *self = self.mul_quat(rhs);
856     }
857 }
858 
859 impl Mul<Vec3> for Quat {
860     type Output = Vec3;
861     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
862     ///
863     /// # Panics
864     ///
865     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
866     #[inline]
mul(self, rhs: Vec3) -> Self::Output867     fn mul(self, rhs: Vec3) -> Self::Output {
868         self.mul_vec3(rhs)
869     }
870 }
871 
872 impl Neg for Quat {
873     type Output = Self;
874     #[inline]
neg(self) -> Self875     fn neg(self) -> Self {
876         self * -1.0
877     }
878 }
879 
880 impl Default for Quat {
881     #[inline]
default() -> Self882     fn default() -> Self {
883         Self::IDENTITY
884     }
885 }
886 
887 impl PartialEq for Quat {
888     #[inline]
eq(&self, rhs: &Self) -> bool889     fn eq(&self, rhs: &Self) -> bool {
890         Vec4::from(*self).eq(&Vec4::from(*rhs))
891     }
892 }
893 
894 #[cfg(not(target_arch = "spirv"))]
895 impl AsRef<[f32; 4]> for Quat {
896     #[inline]
as_ref(&self) -> &[f32; 4]897     fn as_ref(&self) -> &[f32; 4] {
898         unsafe { &*(self as *const Self as *const [f32; 4]) }
899     }
900 }
901 
902 impl Sum<Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,903     fn sum<I>(iter: I) -> Self
904     where
905         I: Iterator<Item = Self>,
906     {
907         iter.fold(Self::ZERO, Self::add)
908     }
909 }
910 
911 impl<'a> Sum<&'a Self> for Quat {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,912     fn sum<I>(iter: I) -> Self
913     where
914         I: Iterator<Item = &'a Self>,
915     {
916         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
917     }
918 }
919 
920 impl Product for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,921     fn product<I>(iter: I) -> Self
922     where
923         I: Iterator<Item = Self>,
924     {
925         iter.fold(Self::IDENTITY, Self::mul)
926     }
927 }
928 
929 impl<'a> Product<&'a Self> for Quat {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,930     fn product<I>(iter: I) -> Self
931     where
932         I: Iterator<Item = &'a Self>,
933     {
934         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
935     }
936 }
937 
938 impl Mul<Vec3A> for Quat {
939     type Output = Vec3A;
940     #[inline]
mul(self, rhs: Vec3A) -> Self::Output941     fn mul(self, rhs: Vec3A) -> Self::Output {
942         self.mul_vec3a(rhs)
943     }
944 }
945 
946 impl From<Quat> for Vec4 {
947     #[inline]
from(q: Quat) -> Self948     fn from(q: Quat) -> Self {
949         Self(q.0)
950     }
951 }
952 
953 impl From<Quat> for (f32, f32, f32, f32) {
954     #[inline]
from(q: Quat) -> Self955     fn from(q: Quat) -> Self {
956         Vec4::from(q).into()
957     }
958 }
959 
960 impl From<Quat> for [f32; 4] {
961     #[inline]
from(q: Quat) -> Self962     fn from(q: Quat) -> Self {
963         Vec4::from(q).into()
964     }
965 }
966 
967 impl From<Quat> for __m128 {
968     #[inline]
from(q: Quat) -> Self969     fn from(q: Quat) -> Self {
970         q.0
971     }
972 }
973 
974 impl Deref for Quat {
975     type Target = crate::deref::Vec4<f32>;
976     #[inline]
deref(&self) -> &Self::Target977     fn deref(&self) -> &Self::Target {
978         unsafe { &*(self as *const Self).cast() }
979     }
980 }
981 
982 impl DerefMut for Quat {
983     #[inline]
deref_mut(&mut self) -> &mut Self::Target984     fn deref_mut(&mut self) -> &mut Self::Target {
985         unsafe { &mut *(self as *mut Self).cast() }
986     }
987 }
988