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