Repository: bitshifter/glam-rs
Pull request #643 (2025-06-05 14:45:49)

Implement `AddAssign` for `Quat`/`DQuat`
# Objective

`Quat` already implements `Add`, so having `AddAssign` is useful sometimes.

## Solution

Implement `AddAssign` for `Quat` by forwarding to the `Add` implementation.


Patch:
diff --git a/src/f32/coresimd/quat.rs b/src/f32/coresimd/quat.rs
index 0159f79..e64eb38 100644
--- a/src/f32/coresimd/quat.rs
+++ b/src/f32/coresimd/quat.rs
@@ -11,7 +11,7 @@ use core::simd::*;
 
 use core::fmt;
 use core::iter::{Product, Sum};
-use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
 
 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
 ///
@@ -882,6 +882,19 @@ impl Add<Quat> for Quat {
     }
 }
 
+impl AddAssign<Quat> for Quat {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<Quat> for Quat {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.
diff --git a/src/f32/neon/quat.rs b/src/f32/neon/quat.rs
index 298655d..c8470d7 100644
--- a/src/f32/neon/quat.rs
+++ b/src/f32/neon/quat.rs
@@ -11,7 +11,7 @@ use core::arch::aarch64::*;
 
 use core::fmt;
 use core::iter::{Product, Sum};
-use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
 
 #[repr(C)]
 union UnionCast {
@@ -904,6 +904,19 @@ impl Add<Quat> for Quat {
     }
 }
 
+impl AddAssign<Quat> for Quat {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<Quat> for Quat {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.
diff --git a/src/f32/scalar/quat.rs b/src/f32/scalar/quat.rs
index d58450a..a0de8b3 100644
--- a/src/f32/scalar/quat.rs
+++ b/src/f32/scalar/quat.rs
@@ -8,7 +8,7 @@ use crate::{
 
 use core::fmt;
 use core::iter::{Product, Sum};
-use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
+use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub};
 
 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
 ///
@@ -864,6 +864,19 @@ impl Add<Quat> for Quat {
     }
 }
 
+impl AddAssign<Quat> for Quat {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<Quat> for Quat {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.
diff --git a/src/f32/sse2/quat.rs b/src/f32/sse2/quat.rs
index ee80d10..37f2598 100644
--- a/src/f32/sse2/quat.rs
+++ b/src/f32/sse2/quat.rs
@@ -14,7 +14,7 @@ use core::arch::x86_64::*;
 
 use core::fmt;
 use core::iter::{Product, Sum};
-use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
 
 #[repr(C)]
 union UnionCast {
@@ -912,6 +912,19 @@ impl Add<Quat> for Quat {
     }
 }
 
+impl AddAssign<Quat> for Quat {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<Quat> for Quat {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.
diff --git a/src/f32/wasm32/quat.rs b/src/f32/wasm32/quat.rs
index d729069..131fe56 100644
--- a/src/f32/wasm32/quat.rs
+++ b/src/f32/wasm32/quat.rs
@@ -11,7 +11,7 @@ use core::arch::wasm32::*;
 
 use core::fmt;
 use core::iter::{Product, Sum};
-use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub};
 
 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
 ///
@@ -884,6 +884,19 @@ impl Add<Quat> for Quat {
     }
 }
 
+impl AddAssign<Quat> for Quat {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<Quat> for Quat {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.
diff --git a/src/f64/dquat.rs b/src/f64/dquat.rs
index 1909753..06a1180 100644
--- a/src/f64/dquat.rs
+++ b/src/f64/dquat.rs
@@ -8,7 +8,7 @@ use crate::{
 
 use core::fmt;
 use core::iter::{Product, Sum};
-use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub};
+use core::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub};
 
 /// Creates a quaternion from `x`, `y`, `z` and `w` values.
 ///
@@ -839,6 +839,19 @@ impl Add<DQuat> for DQuat {
     }
 }
 
+impl AddAssign<DQuat> for DQuat {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<DQuat> for DQuat {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.
diff --git a/templates/quat.rs.tera b/templates/quat.rs.tera
index ea8d54d..6fe55e7 100644
--- a/templates/quat.rs.tera
+++ b/templates/quat.rs.tera
@@ -69,7 +69,7 @@ use core::ops::{
     {% if not is_scalar %}
         Deref, DerefMut,
     {% endif %}
-    Add, Div, Mul, MulAssign, Neg, Sub
+    Add, AddAssign, Div, Mul, MulAssign, Neg, Sub
 };
 
 {% if is_sse2 or is_neon %}
@@ -1258,6 +1258,19 @@ impl Add<{{ self_t }}> for {{ self_t }} {
     }
 }
 
+impl AddAssign<{{ self_t }}> for {{ self_t }} {
+    /// Adds two quaternions.
+    ///
+    /// The sum is not guaranteed to be normalized.
+    ///
+    /// Note that addition is not the same as combining the rotations represented by the
+    /// two quaternions! That corresponds to multiplication.
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        *self = *self + rhs;
+    }
+}
+
 impl Sub<{{ self_t }}> for {{ self_t }} {
     type Output = Self;
     /// Subtracts the `rhs` quaternion from `self`.


Test patch:
diff --git a/tests/quat.rs b/tests/quat.rs
index e807984..41c61d8 100644
--- a/tests/quat.rs
+++ b/tests/quat.rs
@@ -607,6 +607,19 @@ macro_rules! impl_quat_tests {
                 assert_approx_eq!(angle, angle2);
             }
         });
+
+        glam_test!(test_add_assign, {
+            {
+                // Normalization not needed for this test.
+                let q = $quat::from_xyzw(1.0, 2.0, 3.0, 4.0);
+                let p = $quat::from_xyzw(5.0, 6.0, 7.0, 8.0);
+
+                let mut pq = p;
+                pq += q;
+
+                assert_eq!(p + q, pq);
+            }
+        });
     };
 }