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 if max_angle < 0.0 {
606 let target = (self - rhs * self.dot(rhs)).normalize();
608 let angle = self.angle_between(target);
609 if angle <= 1e-4 {
610 return target;
611 }
612 return self.slerp(target, (-max_angle / angle).clamp(0.0, 1.0));
613 }
614 self.slerp(rhs, (max_angle / angle).clamp(0.0, 1.0))
615 }
616
617 #[inline]
627 #[must_use]
628 pub fn abs_diff_eq(self, rhs: Self, max_abs_diff: f64) -> bool {
629 DVec4::from(self).abs_diff_eq(DVec4::from(rhs), max_abs_diff)
630 }
631
632 #[inline(always)]
633 #[must_use]
634 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
635 fn lerp_impl(self, end: Self, s: f64) -> Self {
636 (self * (1.0 - s) + end * s).normalize()
637 }
638
639 #[doc(alias = "mix")]
652 #[inline]
653 #[must_use]
654 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
655 pub fn lerp(self, end: Self, s: f64) -> Self {
656 glam_assert!(self.is_normalized());
657 glam_assert!(end.is_normalized());
658
659 let dot = self.dot(end);
660 let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
661 self.lerp_impl(end * bias, s)
662 }
663
664 #[inline(always)]
665 #[must_use]
666 fn slerp_impl(self, end: Self, dot: f64, s: f64) -> Self {
667 let theta = math::acos_approx(dot);
668
669 let scale1 = math::sin(theta * (1.0 - s));
670 let scale2 = math::sin(theta * s);
671 let theta_sin = math::sin(theta);
672 ((self * scale1) + (end * scale2)) * (1.0 / theta_sin)
673 }
674
675 #[inline]
685 #[must_use]
686 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
687 pub fn slerp(self, mut end: Self, s: f64) -> Self {
688 glam_assert!(self.is_normalized());
690 glam_assert!(end.is_normalized());
691
692 let mut dot = self.dot(end);
699 if dot < 0.0 {
700 end = -end;
701 dot = -dot;
702 }
703
704 const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
705 if dot > DOT_THRESHOLD {
706 self.lerp_impl(end, s)
708 } else {
709 self.slerp_impl(end, dot, s)
710 }
711 }
712
713 #[inline]
727 #[must_use]
728 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
729 pub fn slerp_long(self, end: Self, s: f64) -> Self {
730 glam_assert!(self.is_normalized());
731 glam_assert!(end.is_normalized());
732
733 let dot = self.dot(end);
734
735 const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON;
736 if dot.abs() > DOT_THRESHOLD {
737 self.lerp_impl(end, s)
739 } else {
740 self.slerp_impl(end, dot, s)
741 }
742 }
743
744 #[inline]
750 #[must_use]
751 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
752 pub fn mul_vec3(self, rhs: DVec3) -> DVec3 {
753 glam_assert!(self.is_normalized());
754
755 let w = self.w;
756 let b = DVec3::new(self.x, self.y, self.z);
757 let b2 = b.dot(b);
758 rhs.mul(w * w - b2)
759 .add(b.mul(rhs.dot(b) * 2.0))
760 .add(b.cross(rhs).mul(w * 2.0))
761 }
762
763 #[inline]
768 #[must_use]
769 pub fn mul_quat(self, rhs: Self) -> Self {
770 let (x0, y0, z0, w0) = self.into();
771 let (x1, y1, z1, w1) = rhs.into();
772 Self::from_xyzw(
773 w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1,
774 w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1,
775 w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1,
776 w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1,
777 )
778 }
779
780 #[inline]
790 #[must_use]
791 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
792 pub fn from_affine3(a: &crate::DAffine3) -> Self {
793 Self::from_rotation_axes(a.matrix3.x_axis, a.matrix3.y_axis, a.matrix3.z_axis)
794 }
795
796 #[inline]
797 #[must_use]
798 pub fn as_quat(self) -> Quat {
799 Quat::from_xyzw(self.x as f32, self.y as f32, self.z as f32, self.w as f32)
800 }
801}
802
803impl fmt::Debug for DQuat {
804 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
805 fmt.debug_tuple(stringify!(DQuat))
806 .field(&self.x)
807 .field(&self.y)
808 .field(&self.z)
809 .field(&self.w)
810 .finish()
811 }
812}
813
814impl fmt::Display for DQuat {
815 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
816 if let Some(p) = f.precision() {
817 write!(
818 f,
819 "[{:.*}, {:.*}, {:.*}, {:.*}]",
820 p, self.x, p, self.y, p, self.z, p, self.w
821 )
822 } else {
823 write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w)
824 }
825 }
826}
827
828impl Add for DQuat {
829 type Output = Self;
830 #[inline]
837 fn add(self, rhs: Self) -> Self {
838 Self::from_vec4(DVec4::from(self) + DVec4::from(rhs))
839 }
840}
841
842impl Add<&Self> for DQuat {
843 type Output = Self;
844 #[inline]
845 fn add(self, rhs: &Self) -> Self {
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 Add<DQuat> for &DQuat {
859 type Output = DQuat;
860 #[inline]
861 fn add(self, rhs: DQuat) -> DQuat {
862 (*self).add(rhs)
863 }
864}
865
866impl AddAssign for DQuat {
867 #[inline]
868 fn add_assign(&mut self, rhs: Self) {
869 *self = self.add(rhs);
870 }
871}
872
873impl AddAssign<&Self> for DQuat {
874 #[inline]
875 fn add_assign(&mut self, rhs: &Self) {
876 self.add_assign(*rhs);
877 }
878}
879
880impl Sub for DQuat {
881 type Output = Self;
882 #[inline]
886 fn sub(self, rhs: Self) -> Self {
887 Self::from_vec4(DVec4::from(self) - DVec4::from(rhs))
888 }
889}
890
891impl Sub<&Self> for DQuat {
892 type Output = Self;
893 #[inline]
894 fn sub(self, rhs: &Self) -> Self {
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 Sub<DQuat> for &DQuat {
908 type Output = DQuat;
909 #[inline]
910 fn sub(self, rhs: DQuat) -> DQuat {
911 (*self).sub(rhs)
912 }
913}
914
915impl SubAssign for DQuat {
916 #[inline]
917 fn sub_assign(&mut self, rhs: Self) {
918 *self = self.sub(rhs);
919 }
920}
921
922impl SubAssign<&Self> for DQuat {
923 #[inline]
924 fn sub_assign(&mut self, rhs: &Self) {
925 self.sub_assign(*rhs);
926 }
927}
928
929impl Mul<f64> for DQuat {
930 type Output = Self;
931 #[inline]
935 fn mul(self, rhs: f64) -> Self {
936 Self::from_vec4(DVec4::from(self) * rhs)
937 }
938}
939
940impl Mul<&f64> for DQuat {
941 type Output = Self;
942 #[inline]
943 fn mul(self, rhs: &f64) -> Self {
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 Mul<f64> for &DQuat {
957 type Output = DQuat;
958 #[inline]
959 fn mul(self, rhs: f64) -> DQuat {
960 (*self).mul(rhs)
961 }
962}
963
964impl MulAssign<f64> for DQuat {
965 #[inline]
966 fn mul_assign(&mut self, rhs: f64) {
967 *self = self.mul(rhs);
968 }
969}
970
971impl MulAssign<&f64> for DQuat {
972 #[inline]
973 fn mul_assign(&mut self, rhs: &f64) {
974 self.mul_assign(*rhs);
975 }
976}
977
978impl Div<f64> for DQuat {
979 type Output = Self;
980 #[inline]
983 fn div(self, rhs: f64) -> Self {
984 Self::from_vec4(DVec4::from(self) / rhs)
985 }
986}
987
988impl Div<&f64> for DQuat {
989 type Output = Self;
990 #[inline]
991 fn div(self, rhs: &f64) -> Self {
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 Div<f64> for &DQuat {
1005 type Output = DQuat;
1006 #[inline]
1007 fn div(self, rhs: f64) -> DQuat {
1008 (*self).div(rhs)
1009 }
1010}
1011
1012impl DivAssign<f64> for DQuat {
1013 #[inline]
1014 fn div_assign(&mut self, rhs: f64) {
1015 *self = self.div(rhs);
1016 }
1017}
1018
1019impl DivAssign<&f64> for DQuat {
1020 #[inline]
1021 fn div_assign(&mut self, rhs: &f64) {
1022 self.div_assign(*rhs);
1023 }
1024}
1025
1026impl Mul for DQuat {
1027 type Output = Self;
1028 #[inline]
1034 fn mul(self, rhs: Self) -> Self {
1035 self.mul_quat(rhs)
1036 }
1037}
1038
1039impl Mul<&Self> for DQuat {
1040 type Output = Self;
1041 #[inline]
1042 fn mul(self, rhs: &Self) -> Self {
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 Mul<DQuat> for &DQuat {
1056 type Output = DQuat;
1057 #[inline]
1058 fn mul(self, rhs: DQuat) -> DQuat {
1059 (*self).mul(rhs)
1060 }
1061}
1062
1063impl MulAssign for DQuat {
1064 #[inline]
1065 fn mul_assign(&mut self, rhs: Self) {
1066 *self = self.mul(rhs);
1067 }
1068}
1069
1070impl MulAssign<&Self> for DQuat {
1071 #[inline]
1072 fn mul_assign(&mut self, rhs: &Self) {
1073 self.mul_assign(*rhs);
1074 }
1075}
1076
1077impl Mul<DVec3> for DQuat {
1078 type Output = DVec3;
1079 #[inline]
1085 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1086 fn mul(self, rhs: DVec3) -> Self::Output {
1087 self.mul_vec3(rhs)
1088 }
1089}
1090
1091impl Mul<&DVec3> for DQuat {
1092 type Output = DVec3;
1093 #[inline]
1094 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1095 fn mul(self, rhs: &DVec3) -> DVec3 {
1096 self.mul(*rhs)
1097 }
1098}
1099
1100impl Mul<&DVec3> for &DQuat {
1101 type Output = DVec3;
1102 #[inline]
1103 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1104 fn mul(self, rhs: &DVec3) -> DVec3 {
1105 (*self).mul(*rhs)
1106 }
1107}
1108
1109impl Mul<DVec3> for &DQuat {
1110 type Output = DVec3;
1111 #[inline]
1112 #[cfg_attr(any(debug_assertions, feature = "glam-assert"), track_caller)]
1113 fn mul(self, rhs: DVec3) -> DVec3 {
1114 (*self).mul(rhs)
1115 }
1116}
1117
1118impl Neg for DQuat {
1119 type Output = Self;
1120 #[inline]
1121 fn neg(self) -> Self {
1122 self * -1.0
1123 }
1124}
1125
1126impl Neg for &DQuat {
1127 type Output = DQuat;
1128 #[inline]
1129 fn neg(self) -> DQuat {
1130 (*self).neg()
1131 }
1132}
1133
1134impl Default for DQuat {
1135 #[inline]
1136 fn default() -> Self {
1137 Self::IDENTITY
1138 }
1139}
1140
1141impl PartialEq for DQuat {
1142 #[inline]
1143 fn eq(&self, rhs: &Self) -> bool {
1144 DVec4::from(*self).eq(&DVec4::from(*rhs))
1145 }
1146}
1147
1148impl AsRef<[f64; 4]> for DQuat {
1149 #[inline]
1150 fn as_ref(&self) -> &[f64; 4] {
1151 unsafe { &*(self as *const Self as *const [f64; 4]) }
1152 }
1153}
1154
1155impl Sum<Self> for DQuat {
1156 fn sum<I>(iter: I) -> Self
1157 where
1158 I: Iterator<Item = Self>,
1159 {
1160 iter.fold(Self::ZERO, Self::add)
1161 }
1162}
1163
1164impl<'a> Sum<&'a Self> for DQuat {
1165 fn sum<I>(iter: I) -> Self
1166 where
1167 I: Iterator<Item = &'a Self>,
1168 {
1169 iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
1170 }
1171}
1172
1173impl Product for DQuat {
1174 fn product<I>(iter: I) -> Self
1175 where
1176 I: Iterator<Item = Self>,
1177 {
1178 iter.fold(Self::IDENTITY, Self::mul)
1179 }
1180}
1181
1182impl<'a> Product<&'a Self> for DQuat {
1183 fn product<I>(iter: I) -> Self
1184 where
1185 I: Iterator<Item = &'a Self>,
1186 {
1187 iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
1188 }
1189}
1190
1191impl From<DQuat> for DVec4 {
1192 #[inline]
1193 fn from(q: DQuat) -> Self {
1194 Self::new(q.x, q.y, q.z, q.w)
1195 }
1196}
1197
1198impl From<DQuat> for (f64, f64, f64, f64) {
1199 #[inline]
1200 fn from(q: DQuat) -> Self {
1201 (q.x, q.y, q.z, q.w)
1202 }
1203}
1204
1205impl From<DQuat> for [f64; 4] {
1206 #[inline]
1207 fn from(q: DQuat) -> Self {
1208 [q.x, q.y, q.z, q.w]
1209 }
1210}