1 // Generated from quat.rs.tera template. Edit the template, not the generated file.
2 
3 use crate::{
4     euler::{EulerFromQuaternion, EulerRot, EulerToQuaternion},
5     f64::math,
6     DMat3, DMat4, DVec2, DVec3, DVec4, Quat,
7 };
8 
9 #[cfg(not(target_arch = "spirv"))]
10 use core::fmt;
11 use core::iter::{Product, Sum};
12 use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
13 
14 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
15 ///
16 /// This should generally not be called manually unless you know what you are doing. Use
17 /// one of the other constructors instead such as `identity` or `from_axis_angle`.
18 #[inline]
19 #[must_use]
dquat(x: f64, y: f64, z: f64, w: f64) -> DQuat20 pub const fn dquat(x: f64, y: f64, z: f64, w: f64) -> DQuat {
21     DQuat::from_xyzw(x, y, z, w)
22 }
23 
24 /// A quaternion representing an orientation.
25 ///
26 /// This quaternion is intended to be of unit length but may denormalize due to
27 /// floating point "error creep" which can occur when successive quaternion
28 /// operations are applied.
29 #[derive(Clone, Copy)]
30 #[cfg_attr(not(target_arch = "spirv"), repr(C))]
31 #[cfg_attr(target_arch = "spirv", repr(simd))]
32 pub struct DQuat {
33     pub x: f64,
34     pub y: f64,
35     pub z: f64,
36     pub w: f64,
37 }
38 
39 impl DQuat {
40     /// All zeros.
41     const ZERO: Self = Self::from_array([0.0; 4]);
42 
43     /// The identity quaternion. Corresponds to no rotation.
44     pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
45 
46     /// All NANs.
47     pub const NAN: Self = Self::from_array([f64::NAN; 4]);
48 
49     /// Creates a new rotation quaternion.
50     ///
51     /// This should generally not be called manually unless you know what you are doing.
52     /// Use one of the other constructors instead such as `identity` or `from_axis_angle`.
53     ///
54     /// `from_xyzw` is mostly used by unit tests and `serde` deserialization.
55     ///
56     /// # Preconditions
57     ///
58     /// This function does not check if the input is normalized, it is up to the user to
59     /// provide normalized input or to normalized the resulting quaternion.
60     #[inline(always)]
61     #[must_use]
from_xyzw(x: f64, y: f64, z: f64, w: f64) -> Self62     pub const fn from_xyzw(x: f64, y: f64, z: f64, w: f64) -> Self {
63         Self { x, y, z, w }
64     }
65 
66     /// Creates a rotation quaternion from an array.
67     ///
68     /// # Preconditions
69     ///
70     /// This function does not check if the input is normalized, it is up to the user to
71     /// provide normalized input or to normalized the resulting quaternion.
72     #[inline]
73     #[must_use]
from_array(a: [f64; 4]) -> Self74     pub const fn from_array(a: [f64; 4]) -> Self {
75         Self::from_xyzw(a[0], a[1], a[2], a[3])
76     }
77 
78     /// Creates a new rotation quaternion from a 4D vector.
79     ///
80     /// # Preconditions
81     ///
82     /// This function does not check if the input is normalized, it is up to the user to
83     /// provide normalized input or to normalized the resulting quaternion.
84     #[inline]
85     #[must_use]
from_vec4(v: DVec4) -> Self86     pub const fn from_vec4(v: DVec4) -> Self {
87         Self {
88             x: v.x,
89             y: v.y,
90             z: v.z,
91             w: v.w,
92         }
93     }
94 
95     /// Creates a rotation quaternion from a slice.
96     ///
97     /// # Preconditions
98     ///
99     /// This function does not check if the input is normalized, it is up to the user to
100     /// provide normalized input or to normalized the resulting quaternion.
101     ///
102     /// # Panics
103     ///
104     /// Panics if `slice` length is less than 4.
105     #[inline]
106     #[must_use]
from_slice(slice: &[f64]) -> Self107     pub fn from_slice(slice: &[f64]) -> Self {
108         Self::from_xyzw(slice[0], slice[1], slice[2], slice[3])
109     }
110 
111     /// Writes the quaternion to an unaligned slice.
112     ///
113     /// # Panics
114     ///
115     /// Panics if `slice` length is less than 4.
116     #[inline]
write_to_slice(self, slice: &mut [f64])117     pub fn write_to_slice(self, slice: &mut [f64]) {
118         slice[0] = self.x;
119         slice[1] = self.y;
120         slice[2] = self.z;
121         slice[3] = self.w;
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]
from_axis_angle(axis: DVec3, angle: f64) -> Self133     pub fn from_axis_angle(axis: DVec3, angle: f64) -> 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]
from_scaled_axis(v: DVec3) -> Self145     pub fn from_scaled_axis(v: DVec3) -> 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]
from_rotation_x(angle: f64) -> Self157     pub fn from_rotation_x(angle: f64) -> 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]
from_rotation_y(angle: f64) -> Self165     pub fn from_rotation_y(angle: f64) -> 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]
from_rotation_z(angle: f64) -> Self173     pub fn from_rotation_z(angle: f64) -> 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]
from_euler(euler: EulerRot, a: f64, b: f64, c: f64) -> Self181     pub fn from_euler(euler: EulerRot, a: f64, b: f64, c: f64) -> Self {
182         euler.new_quat(a, b, c)
183     }
184 
185     /// From the columns of a 3x3 rotation matrix.
186     #[inline]
187     #[must_use]
from_rotation_axes(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self188     pub(crate) fn from_rotation_axes(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self {
189         // Based on https://github.com/microsoft/DirectXMath `XM$quaternionRotationMatrix`
190         let (m00, m01, m02) = x_axis.into();
191         let (m10, m11, m12) = y_axis.into();
192         let (m20, m21, m22) = z_axis.into();
193         if m22 <= 0.0 {
194             // x^2 + y^2 >= z^2 + w^2
195             let dif10 = m11 - m00;
196             let omm22 = 1.0 - m22;
197             if dif10 <= 0.0 {
198                 // x^2 >= y^2
199                 let four_xsq = omm22 - dif10;
200                 let inv4x = 0.5 / math::sqrt(four_xsq);
201                 Self::from_xyzw(
202                     four_xsq * inv4x,
203                     (m01 + m10) * inv4x,
204                     (m02 + m20) * inv4x,
205                     (m12 - m21) * inv4x,
206                 )
207             } else {
208                 // y^2 >= x^2
209                 let four_ysq = omm22 + dif10;
210                 let inv4y = 0.5 / math::sqrt(four_ysq);
211                 Self::from_xyzw(
212                     (m01 + m10) * inv4y,
213                     four_ysq * inv4y,
214                     (m12 + m21) * inv4y,
215                     (m20 - m02) * inv4y,
216                 )
217             }
218         } else {
219             // z^2 + w^2 >= x^2 + y^2
220             let sum10 = m11 + m00;
221             let opm22 = 1.0 + m22;
222             if sum10 <= 0.0 {
223                 // z^2 >= w^2
224                 let four_zsq = opm22 - sum10;
225                 let inv4z = 0.5 / math::sqrt(four_zsq);
226                 Self::from_xyzw(
227                     (m02 + m20) * inv4z,
228                     (m12 + m21) * inv4z,
229                     four_zsq * inv4z,
230                     (m01 - m10) * inv4z,
231                 )
232             } else {
233                 // w^2 >= z^2
234                 let four_wsq = opm22 + sum10;
235                 let inv4w = 0.5 / math::sqrt(four_wsq);
236                 Self::from_xyzw(
237                     (m12 - m21) * inv4w,
238                     (m20 - m02) * inv4w,
239                     (m01 - m10) * inv4w,
240                     four_wsq * inv4w,
241                 )
242             }
243         }
244     }
245 
246     /// Creates a quaternion from a 3x3 rotation matrix.
247     #[inline]
248     #[must_use]
from_mat3(mat: &DMat3) -> Self249     pub fn from_mat3(mat: &DMat3) -> Self {
250         Self::from_rotation_axes(mat.x_axis, mat.y_axis, mat.z_axis)
251     }
252 
253     /// Creates a quaternion from a 3x3 rotation matrix inside a homogeneous 4x4 matrix.
254     #[inline]
255     #[must_use]
from_mat4(mat: &DMat4) -> Self256     pub fn from_mat4(mat: &DMat4) -> Self {
257         Self::from_rotation_axes(
258             mat.x_axis.truncate(),
259             mat.y_axis.truncate(),
260             mat.z_axis.truncate(),
261         )
262     }
263 
264     /// Gets the minimal rotation for transforming `from` to `to`.  The rotation is in the
265     /// plane spanned by the two vectors.  Will rotate at most 180 degrees.
266     ///
267     /// The inputs must be unit vectors.
268     ///
269     /// `from_rotation_arc(from, to) * from ≈ to`.
270     ///
271     /// For near-singular cases (from≈to and from≈-to) the current implementation
272     /// is only accurate to about 0.001 (for `f32`).
273     ///
274     /// # Panics
275     ///
276     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
277     #[must_use]
from_rotation_arc(from: DVec3, to: DVec3) -> Self278     pub fn from_rotation_arc(from: DVec3, to: DVec3) -> Self {
279         glam_assert!(from.is_normalized());
280         glam_assert!(to.is_normalized());
281 
282         const ONE_MINUS_EPS: f64 = 1.0 - 2.0 * core::f64::EPSILON;
283         let dot = from.dot(to);
284         if dot > ONE_MINUS_EPS {
285             // 0° singulary: from ≈ to
286             Self::IDENTITY
287         } else if dot < -ONE_MINUS_EPS {
288             // 180° singulary: from ≈ -to
289             use core::f64::consts::PI; // half a turn = ��/2 = 180°
290             Self::from_axis_angle(from.any_orthonormal_vector(), PI)
291         } else {
292             let c = from.cross(to);
293             Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize()
294         }
295     }
296 
297     /// Gets the minimal rotation for transforming `from` to either `to` or `-to`.  This means
298     /// that the resulting quaternion will rotate `from` so that it is colinear with `to`.
299     ///
300     /// The rotation is in the plane spanned by the two vectors.  Will rotate at most 90
301     /// degrees.
302     ///
303     /// The inputs must be unit vectors.
304     ///
305     /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`.
306     ///
307     /// # Panics
308     ///
309     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
310     #[inline]
311     #[must_use]
from_rotation_arc_colinear(from: DVec3, to: DVec3) -> Self312     pub fn from_rotation_arc_colinear(from: DVec3, to: DVec3) -> Self {
313         if from.dot(to) < 0.0 {
314             Self::from_rotation_arc(from, -to)
315         } else {
316             Self::from_rotation_arc(from, to)
317         }
318     }
319 
320     /// Gets the minimal rotation for transforming `from` to `to`.  The resulting rotation is
321     /// around the z axis. Will rotate at most 180 degrees.
322     ///
323     /// The inputs must be unit vectors.
324     ///
325     /// `from_rotation_arc_2d(from, to) * from ≈ to`.
326     ///
327     /// For near-singular cases (from≈to and from≈-to) the current implementation
328     /// is only accurate to about 0.001 (for `f32`).
329     ///
330     /// # Panics
331     ///
332     /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled.
333     #[must_use]
from_rotation_arc_2d(from: DVec2, to: DVec2) -> Self334     pub fn from_rotation_arc_2d(from: DVec2, to: DVec2) -> Self {
335         glam_assert!(from.is_normalized());
336         glam_assert!(to.is_normalized());
337 
338         const ONE_MINUS_EPSILON: f64 = 1.0 - 2.0 * core::f64::EPSILON;
339         let dot = from.dot(to);
340         if dot > ONE_MINUS_EPSILON {
341             // 0° singulary: from ≈ to
342             Self::IDENTITY
343         } else if dot < -ONE_MINUS_EPSILON {
344             // 180° singulary: from ≈ -to
345             const COS_FRAC_PI_2: f64 = 0.0;
346             const SIN_FRAC_PI_2: f64 = 1.0;
347             // rotation around z by PI radians
348             Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
349         } else {
350             // vector3 cross where z=0
351             let z = from.x * to.y - to.x * from.y;
352             let w = 1.0 + dot;
353             // calculate length with x=0 and y=0 to normalize
354             let len_rcp = 1.0 / math::sqrt(z * z + w * w);
355             Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp)
356         }
357     }
358 
359     /// Returns the rotation axis (normalized) and angle (in radians) of `self`.
360     #[inline]
361     #[must_use]
to_axis_angle(self) -> (DVec3, f64)362     pub fn to_axis_angle(self) -> (DVec3, f64) {
363         const EPSILON: f64 = 1.0e-8;
364         let v = DVec3::new(self.x, self.y, self.z);
365         let length = v.length();
366         if length >= EPSILON {
367             let angle = 2.0 * math::atan2(length, self.w);
368             let axis = v / length;
369             (axis, angle)
370         } else {
371             (DVec3::X, 0.0)
372         }
373     }
374 
375     /// Returns the rotation axis scaled by the rotation in radians.
376     #[inline]
377     #[must_use]
to_scaled_axis(self) -> DVec3378     pub fn to_scaled_axis(self) -> DVec3 {
379         let (axis, angle) = self.to_axis_angle();
380         axis * angle
381     }
382 
383     /// Returns the rotation angles for the given euler rotation sequence.
384     #[inline]
385     #[must_use]
to_euler(self, euler: EulerRot) -> (f64, f64, f64)386     pub fn to_euler(self, euler: EulerRot) -> (f64, f64, f64) {
387         euler.convert_quat(self)
388     }
389 
390     /// `[x, y, z, w]`
391     #[inline]
392     #[must_use]
to_array(&self) -> [f64; 4]393     pub fn to_array(&self) -> [f64; 4] {
394         [self.x, self.y, self.z, self.w]
395     }
396 
397     /// Returns the vector part of the quaternion.
398     #[inline]
399     #[must_use]
xyz(self) -> DVec3400     pub fn xyz(self) -> DVec3 {
401         DVec3::new(self.x, self.y, self.z)
402     }
403 
404     /// Returns the quaternion conjugate of `self`. For a unit quaternion the
405     /// conjugate is also the inverse.
406     #[inline]
407     #[must_use]
conjugate(self) -> Self408     pub fn conjugate(self) -> Self {
409         Self {
410             x: -self.x,
411             y: -self.y,
412             z: -self.z,
413             w: self.w,
414         }
415     }
416 
417     /// Returns the inverse of a normalized quaternion.
418     ///
419     /// Typically quaternion inverse returns the conjugate of a normalized quaternion.
420     /// Because `self` is assumed to already be unit length this method *does not* normalize
421     /// before returning the conjugate.
422     ///
423     /// # Panics
424     ///
425     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
426     #[inline]
427     #[must_use]
inverse(self) -> Self428     pub fn inverse(self) -> Self {
429         glam_assert!(self.is_normalized());
430         self.conjugate()
431     }
432 
433     /// Computes the dot product of `self` and `rhs`. The dot product is
434     /// equal to the cosine of the angle between two quaternion rotations.
435     #[inline]
436     #[must_use]
dot(self, rhs: Self) -> f64437     pub fn dot(self, rhs: Self) -> f64 {
438         DVec4::from(self).dot(DVec4::from(rhs))
439     }
440 
441     /// Computes the length of `self`.
442     #[doc(alias = "magnitude")]
443     #[inline]
444     #[must_use]
length(self) -> f64445     pub fn length(self) -> f64 {
446         DVec4::from(self).length()
447     }
448 
449     /// Computes the squared length of `self`.
450     ///
451     /// This is generally faster than `length()` as it avoids a square
452     /// root operation.
453     #[doc(alias = "magnitude2")]
454     #[inline]
455     #[must_use]
length_squared(self) -> f64456     pub fn length_squared(self) -> f64 {
457         DVec4::from(self).length_squared()
458     }
459 
460     /// Computes `1.0 / length()`.
461     ///
462     /// For valid results, `self` must _not_ be of length zero.
463     #[inline]
464     #[must_use]
length_recip(self) -> f64465     pub fn length_recip(self) -> f64 {
466         DVec4::from(self).length_recip()
467     }
468 
469     /// Returns `self` normalized to length 1.0.
470     ///
471     /// For valid results, `self` must _not_ be of length zero.
472     ///
473     /// Panics
474     ///
475     /// Will panic if `self` is zero length when `glam_assert` is enabled.
476     #[inline]
477     #[must_use]
normalize(self) -> Self478     pub fn normalize(self) -> Self {
479         Self::from_vec4(DVec4::from(self).normalize())
480     }
481 
482     /// Returns `true` if, and only if, all elements are finite.
483     /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
484     #[inline]
485     #[must_use]
is_finite(self) -> bool486     pub fn is_finite(self) -> bool {
487         DVec4::from(self).is_finite()
488     }
489 
490     #[inline]
491     #[must_use]
is_nan(self) -> bool492     pub fn is_nan(self) -> bool {
493         DVec4::from(self).is_nan()
494     }
495 
496     /// Returns whether `self` of length `1.0` or not.
497     ///
498     /// Uses a precision threshold of `1e-6`.
499     #[inline]
500     #[must_use]
is_normalized(self) -> bool501     pub fn is_normalized(self) -> bool {
502         DVec4::from(self).is_normalized()
503     }
504 
505     #[inline]
506     #[must_use]
is_near_identity(self) -> bool507     pub fn is_near_identity(self) -> bool {
508         // Based on https://github.com/nfrechette/rtm `rtm::quat_near_identity`
509         let threshold_angle = 0.002_847_144_6;
510         // Because of floating point precision, we cannot represent very small rotations.
511         // The closest f32 to 1.0 that is not 1.0 itself yields:
512         // 0.99999994.acos() * 2.0  = 0.000690533954 rad
513         //
514         // An error threshold of 1.e-6 is used by default.
515         // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad
516         // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad
517         //
518         // We don't really care about the angle value itself, only if it's close to 0.
519         // This will happen whenever quat.w is close to 1.0.
520         // If the quat.w is close to -1.0, the angle will be near 2*PI which is close to
521         // a negative 0 rotation. By forcing quat.w to be positive, we'll end up with
522         // the shortest path.
523         let positive_w_angle = math::acos_approx(math::abs(self.w)) * 2.0;
524         positive_w_angle < threshold_angle
525     }
526 
527     /// Returns the angle (in radians) for the minimal rotation
528     /// for transforming this quaternion into another.
529     ///
530     /// Both quaternions must be normalized.
531     ///
532     /// # Panics
533     ///
534     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
535     #[inline]
536     #[must_use]
angle_between(self, rhs: Self) -> f64537     pub fn angle_between(self, rhs: Self) -> f64 {
538         glam_assert!(self.is_normalized() && rhs.is_normalized());
539         math::acos_approx(math::abs(self.dot(rhs))) * 2.0
540     }
541 
542     /// Returns true if the absolute difference of all elements between `self` and `rhs`
543     /// is less than or equal to `max_abs_diff`.
544     ///
545     /// This can be used to compare if two quaternions contain similar elements. It works
546     /// best when comparing with a known value. The `max_abs_diff` that should be used used
547     /// depends on the values being compared against.
548     ///
549     /// For more see
550     /// [comparing floating point numbers](https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/).
551     #[inline]
552     #[must_use]
abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool553     pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
554         DVec4::from(self).abs_diff_eq(DVec4::from(rhs), max_abs_diff)
555     }
556 
557     /// Performs a linear interpolation between `self` and `rhs` based on
558     /// the value `s`.
559     ///
560     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
561     /// is `1.0`, the result will be equal to `rhs`.
562     ///
563     /// # Panics
564     ///
565     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
566     #[doc(alias = "mix")]
567     #[inline]
568     #[must_use]
lerp(self, end: Self, s: f64) -> Self569     pub fn lerp(self, end: Self, s: f64) -> Self {
570         glam_assert!(self.is_normalized());
571         glam_assert!(end.is_normalized());
572 
573         let start = self;
574         let dot = start.dot(end);
575         let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
576         let interpolated = start.add(end.mul(bias).sub(start).mul(s));
577         interpolated.normalize()
578     }
579 
580     /// Performs a spherical linear interpolation between `self` and `end`
581     /// based on the value `s`.
582     ///
583     /// When `s` is `0.0`, the result will be equal to `self`.  When `s`
584     /// is `1.0`, the result will be equal to `end`.
585     ///
586     /// # Panics
587     ///
588     /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled.
589     #[inline]
590     #[must_use]
slerp(self, mut end: Self, s: f64) -> Self591     pub fn slerp(self, mut end: Self, s: f64) -> Self {
592         // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
593         glam_assert!(self.is_normalized());
594         glam_assert!(end.is_normalized());
595 
596         const DOT_THRESHOLD: f64 = 0.9995;
597 
598         // Note that a rotation can be represented by two quaternions: `q` and
599         // `-q`. The slerp path between `q` and `end` will be different from the
600         // path between `-q` and `end`. One path will take the long way around and
601         // one will take the short way. In order to correct for this, the `dot`
602         // product between `self` and `end` should be positive. If the `dot`
603         // product is negative, slerp between `self` and `-end`.
604         let mut dot = self.dot(end);
605         if dot < 0.0 {
606             end = -end;
607             dot = -dot;
608         }
609 
610         if dot > DOT_THRESHOLD {
611             // assumes lerp returns a normalized quaternion
612             self.lerp(end, s)
613         } else {
614             let theta = math::acos_approx(dot);
615 
616             let scale1 = math::sin(theta * (1.0 - s));
617             let scale2 = math::sin(theta * s);
618             let theta_sin = math::sin(theta);
619 
620             self.mul(scale1).add(end.mul(scale2)).mul(1.0 / theta_sin)
621         }
622     }
623 
624     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
625     ///
626     /// # Panics
627     ///
628     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
629     #[inline]
630     #[must_use]
mul_vec3(self, rhs: DVec3) -> DVec3631     pub fn mul_vec3(self, rhs: DVec3) -> DVec3 {
632         glam_assert!(self.is_normalized());
633 
634         let w = self.w;
635         let b = DVec3::new(self.x, self.y, self.z);
636         let b2 = b.dot(b);
637         rhs.mul(w * w - b2)
638             .add(b.mul(rhs.dot(b) * 2.0))
639             .add(b.cross(rhs).mul(w * 2.0))
640     }
641 
642     /// Multiplies two quaternions. If they each represent a rotation, the result will
643     /// represent the combined rotation.
644     ///
645     /// Note that due to floating point rounding the result may not be perfectly 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]
mul_quat(self, rhs: Self) -> Self652     pub fn mul_quat(self, rhs: Self) -> Self {
653         glam_assert!(self.is_normalized());
654         glam_assert!(rhs.is_normalized());
655 
656         let (x0, y0, z0, w0) = self.into();
657         let (x1, y1, z1, w1) = rhs.into();
658         Self::from_xyzw(
659             w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
660             w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
661             w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
662             w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
663         )
664     }
665 
666     /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform.
667     #[inline]
668     #[must_use]
from_affine3(a: &crate::DAffine3) -> Self669     pub fn from_affine3(a: &crate::DAffine3) -> Self {
670         #[allow(clippy::useless_conversion)]
671         Self::from_rotation_axes(
672             a.matrix3.x_axis.into(),
673             a.matrix3.y_axis.into(),
674             a.matrix3.z_axis.into(),
675         )
676     }
677 
678     #[inline]
679     #[must_use]
as_quat(self) -> Quat680     pub fn as_quat(self) -> Quat {
681         Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
682     }
683 
684     #[inline]
685     #[must_use]
686     #[deprecated(since = "0.24.2", note = "Use as_quat() instead")]
as_f32(self) -> Quat687     pub fn as_f32(self) -> Quat {
688         self.as_quat()
689     }
690 }
691 
692 #[cfg(not(target_arch = "spirv"))]
693 impl fmt::Debug for DQuat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result694     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
695         fmt.debug_tuple(stringify!(DQuat))
696             .field(&self.x)
697             .field(&self.y)
698             .field(&self.z)
699             .field(&self.w)
700             .finish()
701     }
702 }
703 
704 #[cfg(not(target_arch = "spirv"))]
705 impl fmt::Display for DQuat {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result706     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
707         write!(fmt, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
708     }
709 }
710 
711 impl Add<DQuat> for DQuat {
712     type Output = Self;
713     /// Adds two quaternions.
714     ///
715     /// The sum is not guaranteed to be normalized.
716     ///
717     /// Note that addition is not the same as combining the rotations represented by the
718     /// two quaternions! That corresponds to multiplication.
719     #[inline]
add(self, rhs: Self) -> Self720     fn add(self, rhs: Self) -> Self {
721         Self::from_vec4(DVec4::from(self) + DVec4::from(rhs))
722     }
723 }
724 
725 impl Sub<DQuat> for DQuat {
726     type Output = Self;
727     /// Subtracts the `rhs` quaternion from `self`.
728     ///
729     /// The difference is not guaranteed to be normalized.
730     #[inline]
sub(self, rhs: Self) -> Self731     fn sub(self, rhs: Self) -> Self {
732         Self::from_vec4(DVec4::from(self) - DVec4::from(rhs))
733     }
734 }
735 
736 impl Mul<f64> for DQuat {
737     type Output = Self;
738     /// Multiplies a quaternion by a scalar value.
739     ///
740     /// The product is not guaranteed to be normalized.
741     #[inline]
mul(self, rhs: f64) -> Self742     fn mul(self, rhs: f64) -> Self {
743         Self::from_vec4(DVec4::from(self) * rhs)
744     }
745 }
746 
747 impl Div<f64> for DQuat {
748     type Output = Self;
749     /// Divides a quaternion by a scalar value.
750     /// The quotient is not guaranteed to be normalized.
751     #[inline]
div(self, rhs: f64) -> Self752     fn div(self, rhs: f64) -> Self {
753         Self::from_vec4(DVec4::from(self) / rhs)
754     }
755 }
756 
757 impl Mul<DQuat> for DQuat {
758     type Output = Self;
759     /// Multiplies two quaternions. If they each represent a rotation, the result will
760     /// represent the combined rotation.
761     ///
762     /// Note that due to floating point rounding the result may not be perfectly
763     /// normalized.
764     ///
765     /// # Panics
766     ///
767     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
768     #[inline]
mul(self, rhs: Self) -> Self769     fn mul(self, rhs: Self) -> Self {
770         self.mul_quat(rhs)
771     }
772 }
773 
774 impl MulAssign<DQuat> for DQuat {
775     /// Multiplies two quaternions. If they each represent a rotation, the result will
776     /// represent the combined rotation.
777     ///
778     /// Note that due to floating point rounding the result may not be perfectly
779     /// normalized.
780     ///
781     /// # Panics
782     ///
783     /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled.
784     #[inline]
mul_assign(&mut self, rhs: Self)785     fn mul_assign(&mut self, rhs: Self) {
786         *self = self.mul_quat(rhs);
787     }
788 }
789 
790 impl Mul<DVec3> for DQuat {
791     type Output = DVec3;
792     /// Multiplies a quaternion and a 3D vector, returning the rotated vector.
793     ///
794     /// # Panics
795     ///
796     /// Will panic if `self` is not normalized when `glam_assert` is enabled.
797     #[inline]
mul(self, rhs: DVec3) -> Self::Output798     fn mul(self, rhs: DVec3) -> Self::Output {
799         self.mul_vec3(rhs)
800     }
801 }
802 
803 impl Neg for DQuat {
804     type Output = Self;
805     #[inline]
neg(self) -> Self806     fn neg(self) -> Self {
807         self * -1.0
808     }
809 }
810 
811 impl Default for DQuat {
812     #[inline]
default() -> Self813     fn default() -> Self {
814         Self::IDENTITY
815     }
816 }
817 
818 impl PartialEq for DQuat {
819     #[inline]
eq(&self, rhs: &Self) -> bool820     fn eq(&self, rhs: &Self) -> bool {
821         DVec4::from(*self).eq(&DVec4::from(*rhs))
822     }
823 }
824 
825 #[cfg(not(target_arch = "spirv"))]
826 impl AsRef<[f64; 4]> for DQuat {
827     #[inline]
as_ref(&self) -> &[f64; 4]828     fn as_ref(&self) -> &[f64; 4] {
829         unsafe { &*(self as *const Self as *const [f64; 4]) }
830     }
831 }
832 
833 impl Sum<Self> for DQuat {
sum<I>(iter: I) -> Self where I: Iterator<Item = Self>,834     fn sum<I>(iter: I) -> Self
835     where
836         I: Iterator<Item = Self>,
837     {
838         iter.fold(Self::ZERO, Self::add)
839     }
840 }
841 
842 impl<'a> Sum<&'a Self> for DQuat {
sum<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,843     fn sum<I>(iter: I) -> Self
844     where
845         I: Iterator<Item = &'a Self>,
846     {
847         iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
848     }
849 }
850 
851 impl Product for DQuat {
product<I>(iter: I) -> Self where I: Iterator<Item = Self>,852     fn product<I>(iter: I) -> Self
853     where
854         I: Iterator<Item = Self>,
855     {
856         iter.fold(Self::IDENTITY, Self::mul)
857     }
858 }
859 
860 impl<'a> Product<&'a Self> for DQuat {
product<I>(iter: I) -> Self where I: Iterator<Item = &'a Self>,861     fn product<I>(iter: I) -> Self
862     where
863         I: Iterator<Item = &'a Self>,
864     {
865         iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
866     }
867 }
868 
869 impl From<DQuat> for DVec4 {
870     #[inline]
from(q: DQuat) -> Self871     fn from(q: DQuat) -> Self {
872         Self::new(q.x, q.y, q.z, q.w)
873     }
874 }
875 
876 impl From<DQuat> for (f64, f64, f64, f64) {
877     #[inline]
from(q: DQuat) -> Self878     fn from(q: DQuat) -> Self {
879         (q.x, q.y, q.z, q.w)
880     }
881 }
882 
883 impl From<DQuat> for [f64; 4] {
884     #[inline]
from(q: DQuat) -> Self885     fn from(q: DQuat) -> Self {
886         [q.x, q.y, q.z, q.w]
887     }
888 }
889