Skip to main content

glam/f64/
dquat.rs

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