1use 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#[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#[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 const ZERO: Self = Self::from_array([0.0; 4]);
49
50 pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0);
52
53 pub const NAN: Self = Self::from_array([f64::NAN; 4]);
55
56 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 let dif10 = m11 - m00;
220 let omm22 = 1.0 - m22;
221 if dif10 <= 0.0 {
222 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 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 let sum10 = m11 + m00;
245 let opm22 = 1.0 + m22;
246 if sum10 <= 0.0 {
247 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 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 #[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 #[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 #[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 Self::IDENTITY
329 } else if dot < -ONE_MINUS_EPS {
330 use core::f64::consts::PI; 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 #[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 #[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 Self::IDENTITY
387 } else if dot < -ONE_MINUS_EPSILON {
388 const COS_FRAC_PI_2: f64 = 0.0;
390 const SIN_FRAC_PI_2: f64 = 1.0;
391 Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2)
393 } else {
394 let z = from.x * to.y - to.x * from.y;
396 let w = 1.0 + dot;
397 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 #[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 #[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 #[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 #[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 #[inline]
448 #[must_use]
449 pub fn xyz(self) -> DVec3 {
450 DVec3::new(self.x, self.y, self.z)
451 }
452
453 #[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 #[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 #[inline]
486 #[must_use]
487 pub fn dot(self, rhs: Self) -> f64 {
488 DVec4::from(self).dot(DVec4::from(rhs))
489 }
490
491 #[doc(alias = "magnitude")]
493 #[inline]
494 #[must_use]
495 pub fn length(self) -> f64 {
496 DVec4::from(self).length()
497 }
498
499 #[doc(alias = "magnitude2")]
504 #[inline]
505 #[must_use]
506 pub fn length_squared(self) -> f64 {
507 DVec4::from(self).length_squared()
508 }
509
510 #[inline]
514 #[must_use]
515 pub fn length_recip(self) -> f64 {
516 DVec4::from(self).length_recip()
517 }
518
519 #[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 #[inline]
536 #[must_use]
537 pub fn is_finite(self) -> bool {
538 DVec4::from(self).is_finite()
539 }
540
541 #[inline]
543 #[must_use]
544 pub fn is_nan(self) -> bool {
545 DVec4::from(self).is_nan()
546 }
547
548 #[inline]
552 #[must_use]
553 pub fn is_normalized(self) -> bool {
554 DVec4::from(self).is_normalized()
555 }
556
557 #[inline]
559 #[must_use]
560 pub fn is_near_identity(self) -> bool {
561 const THRESHOLD: f64 = 1.0 - 1e-14;
566 self.w.abs() > THRESHOLD
567 }
568
569 #[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 #[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 #[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 #[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 #[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 glam_assert!(self.is_normalized());
682 glam_assert!(end.is_normalized());
683
684 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 self.lerp_impl(end, s)
700 } else {
701 self.slerp_impl(end, dot, s)
702 }
703 }
704
705 #[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 self.lerp_impl(end, s)
731 } else {
732 self.slerp_impl(end, dot, s)
733 }
734 }
735
736 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}