Repository: bitshifter/glam-rs
Pull request #560 (2024-09-09 16:34:20)

Remove normalized assertions from `mul_quat`
It makes sense to ensure that quaternions are normalized before using them to do things that require them to be normalized to make sense (like transforming a vector), but it is entirely valid to multiply non-normalized quaternions. Such a use case is in implementing dual quaternions, in which case we routinely multiply the (normalized) real-part quat with the (non-normalized in and of itself) dual-part quat.


Patch:
diff --git a/codegen/templates/quat.rs.tera b/codegen/templates/quat.rs.tera
index 47221e6..2caeaa7 100644
--- a/codegen/templates/quat.rs.tera
+++ b/codegen/templates/quat.rs.tera
@@ -711,7 +711,7 @@ impl {{ self_t }} {
         glam_assert!(self.is_normalized() && rhs.is_normalized());
         math::acos_approx(math::abs(self.dot(rhs))) * 2.0
     }
-    
+
     /// Rotates towards `rhs` up to `max_angle` (in radians).
     ///
     /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to
@@ -775,7 +775,7 @@ impl {{ self_t }} {
         {% if is_scalar %}
             let dot = self.dot(end);
             let bias = if dot >= 0.0 { 1.0 } else { -1.0 };
-            self.lerp_impl(end * bias, s) 
+            self.lerp_impl(end * bias, s)
         {% elif is_sse2 %}
             const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]);
             unsafe {
@@ -908,9 +908,6 @@ impl {{ self_t }} {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         {% if is_scalar %}
             let (x0, y0, z0, w0) = self.into();
             let (x1, y1, z1, w1) = rhs.into();
diff --git a/src/f32/coresimd/quat.rs b/src/f32/coresimd/quat.rs
index ffcafe7..eca7a0e 100644
--- a/src/f32/coresimd/quat.rs
+++ b/src/f32/coresimd/quat.rs
@@ -702,9 +702,6 @@ impl Quat {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         let lhs = self.0;
         let rhs = rhs.0;
 
diff --git a/src/f32/neon/quat.rs b/src/f32/neon/quat.rs
index 414aa7a..7dca3a4 100644
--- a/src/f32/neon/quat.rs
+++ b/src/f32/neon/quat.rs
@@ -715,9 +715,6 @@ impl Quat {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         unsafe {
             let lhs = self.0;
             let rhs = rhs.0;
diff --git a/src/f32/scalar/quat.rs b/src/f32/scalar/quat.rs
index cadeca7..cf5d648 100644
--- a/src/f32/scalar/quat.rs
+++ b/src/f32/scalar/quat.rs
@@ -716,9 +716,6 @@ impl Quat {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         let (x0, y0, z0, w0) = self.into();
         let (x1, y1, z1, w1) = rhs.into();
         Self::from_xyzw(
diff --git a/src/f32/sse2/quat.rs b/src/f32/sse2/quat.rs
index 181e3f4..a430a4f 100644
--- a/src/f32/sse2/quat.rs
+++ b/src/f32/sse2/quat.rs
@@ -725,9 +725,6 @@ impl Quat {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         // Based on https://github.com/nfrechette/rtm `rtm::quat_mul`
         const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]);
         const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]);
diff --git a/src/f32/wasm32/quat.rs b/src/f32/wasm32/quat.rs
index 0055c01..6632a88 100644
--- a/src/f32/wasm32/quat.rs
+++ b/src/f32/wasm32/quat.rs
@@ -702,9 +702,6 @@ impl Quat {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         let lhs = self.0;
         let rhs = rhs.0;
 
diff --git a/src/f64/dquat.rs b/src/f64/dquat.rs
index a5f4819..9eac363 100644
--- a/src/f64/dquat.rs
+++ b/src/f64/dquat.rs
@@ -698,9 +698,6 @@ impl DQuat {
     #[inline]
     #[must_use]
     pub fn mul_quat(self, rhs: Self) -> Self {
-        glam_assert!(self.is_normalized());
-        glam_assert!(rhs.is_normalized());
-
         let (x0, y0, z0, w0) = self.into();
         let (x1, y1, z1, w1) = rhs.into();
         Self::from_xyzw(


Test patch:
diff --git a/tests/quat.rs b/tests/quat.rs
index 7813b72..3c8a090 100644
--- a/tests/quat.rs
+++ b/tests/quat.rs
@@ -226,8 +226,6 @@ macro_rules! impl_quat_tests {
 
             should_glam_assert!({ ($quat::IDENTITY * 0.5).mul_vec3($vec3::X) });
             should_glam_assert!({ ($quat::IDENTITY * 0.5) * $vec3::X });
-            should_glam_assert!({ ($quat::IDENTITY * 0.5).mul_quat($quat::IDENTITY) });
-            should_glam_assert!({ ($quat::IDENTITY * 0.5) * $quat::IDENTITY });
         });
 
         glam_test!(test_angle_between, {