Repository: bitshifter/glam-rs
Pull request #190 (2021-06-11 21:05:39)

Added matrix assign ops and col_mut methods.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36787a0..02ba092 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog], and this project adheres to
 [Semantic Versioning].
 
+## [Unreleased]
+
+### Added
+
+* Added `col_mut()` method which returns a mutable reference to a matrix column
+  to all matrix types.
+* Added `AddAssign`, `MulAssign` and `SubAssign` implementations for all matrix
+  types.
+
 ## [0.16.0] - 2021-06-06
 
 ### Breaking changes
diff --git a/src/core/traits/matrix.rs b/src/core/traits/matrix.rs
index fd28226..2b44210 100644
--- a/src/core/traits/matrix.rs
+++ b/src/core/traits/matrix.rs
@@ -625,7 +625,7 @@ pub trait Matrix4x4<T: NumEx, V4: Vector4<T>>: Matrix<T> {
     }
 
     #[inline]
-    fn mul_vector(&self, other: &V4) -> V4 {
+    fn mul_vector(&self, other: V4) -> V4 {
         let mut res = self.x_axis().mul(other.splat_x());
         res = self.y_axis().mul_add(other.splat_y(), res);
         res = self.z_axis().mul_add(other.splat_z(), res);
@@ -636,10 +636,10 @@ pub trait Matrix4x4<T: NumEx, V4: Vector4<T>>: Matrix<T> {
     #[inline]
     fn mul_matrix(&self, other: &Self) -> Self {
         Self::from_cols(
-            self.mul_vector(other.x_axis()),
-            self.mul_vector(other.y_axis()),
-            self.mul_vector(other.z_axis()),
-            self.mul_vector(other.w_axis()),
+            self.mul_vector(*other.x_axis()),
+            self.mul_vector(*other.y_axis()),
+            self.mul_vector(*other.z_axis()),
+            self.mul_vector(*other.w_axis()),
         )
     }
 
diff --git a/src/lib.rs b/src/lib.rs
index 8cc780e..c049115 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -233,6 +233,9 @@ The minimum supported Rust version is `1.45.0`.
 #[macro_use]
 mod macros;
 
+#[macro_use]
+mod mat;
+
 #[macro_use]
 mod vec;
 
diff --git a/src/mat.rs b/src/mat.rs
new file mode 100644
index 0000000..d5f0e0d
--- /dev/null
+++ b/src/mat.rs
@@ -0,0 +1,108 @@
+// Adds common vector trait implementations.
+// The traits here should be supported for all types of $t and all sizes of vector.
+macro_rules! impl_matn_common_traits {
+    ($t:ty, $matn:ident, $vecn:ident) => {
+        impl Default for $matn {
+            #[inline(always)]
+            fn default() -> Self {
+                Self::IDENTITY
+            }
+        }
+
+        impl Add<$matn> for $matn {
+            type Output = Self;
+            #[inline(always)]
+            fn add(self, other: Self) -> Self::Output {
+                Self(self.0.add_matrix(&other.0))
+            }
+        }
+
+        impl AddAssign<$matn> for $matn {
+            #[inline(always)]
+            fn add_assign(&mut self, other: Self) {
+                self.0 = self.0.add_matrix(&other.0);
+            }
+        }
+
+        impl Sub<$matn> for $matn {
+            type Output = Self;
+            #[inline(always)]
+            fn sub(self, other: Self) -> Self::Output {
+                Self(self.0.sub_matrix(&other.0))
+            }
+        }
+
+        impl SubAssign<$matn> for $matn {
+            #[inline(always)]
+            fn sub_assign(&mut self, other: Self) {
+                self.0 = self.0.sub_matrix(&other.0);
+            }
+        }
+
+        impl Mul<$matn> for $matn {
+            type Output = Self;
+            #[inline(always)]
+            fn mul(self, other: Self) -> Self::Output {
+                Self(self.0.mul_matrix(&other.0))
+            }
+        }
+
+        impl MulAssign<$matn> for $matn {
+            #[inline(always)]
+            fn mul_assign(&mut self, other: Self) {
+                self.0 = self.0.mul_matrix(&other.0);
+            }
+        }
+
+        impl Mul<$vecn> for $matn {
+            type Output = $vecn;
+            #[inline(always)]
+            fn mul(self, other: $vecn) -> Self::Output {
+                $vecn(self.0.mul_vector(other.0))
+            }
+        }
+
+        impl Mul<$matn> for $t {
+            type Output = $matn;
+            #[inline(always)]
+            fn mul(self, other: $matn) -> Self::Output {
+                $matn(other.0.mul_scalar(self))
+            }
+        }
+
+        impl Mul<$t> for $matn {
+            type Output = Self;
+            #[inline(always)]
+            fn mul(self, other: $t) -> Self::Output {
+                Self(self.0.mul_scalar(other))
+            }
+        }
+
+        impl MulAssign<$t> for $matn {
+            #[inline(always)]
+            fn mul_assign(&mut self, other: $t) {
+                self.0 = self.0.mul_scalar(other);
+            }
+        }
+
+        #[cfg(feature = "std")]
+        impl<'a> Sum<&'a Self> for $matn {
+            fn sum<I>(iter: I) -> Self
+            where
+                I: Iterator<Item = &'a Self>,
+            {
+                iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
+            }
+        }
+
+        #[cfg(feature = "std")]
+        impl<'a> Product<&'a Self> for $matn {
+            fn product<I>(iter: I) -> Self
+            where
+                I: Iterator<Item = &'a Self>,
+            {
+                iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
+            }
+        }
+    };
+}
diff --git a/src/mat2.rs b/src/mat2.rs
index 69acd74..6c10b0e 100644
--- a/src/mat2.rs
+++ b/src/mat2.rs
@@ -5,7 +5,7 @@ use crate::core::{
 use crate::{DMat3, DVec2, Mat3, Vec2};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
-use core::ops::{Add, Deref, DerefMut, Mul, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign};
 
 #[cfg(all(
     target_arch = "x86",
@@ -124,6 +124,23 @@ macro_rules! impl_mat2_methods {
             }
         }
 
+        /// Returns a mutable reference to the matrix column for the given `index`.
+        ///
+        /// # Panics
+        ///
+        /// Panics if `index` is greater than 1.
+        #[inline]
+        pub fn col_mut(&mut self, index: usize) -> &mut $vec2 {
+            match index {
+                0 => &mut self.x_axis,
+                1 => &mut self.y_axis,
+                _ => panic!(
+                    "index out of bounds: the len is 2 but the index is {}",
+                    index
+                ),
+            }
+        }
+
         /// Returns the matrix row for the given `index`.
         ///
         /// # Panics
@@ -141,18 +158,6 @@ macro_rules! impl_mat2_methods {
             }
         }
 
-        // #[inline]
-        // pub(crate) fn col_mut(&mut self, index: usize) -> &mut $vec2 {
-        //     match index {
-        //         0 => unsafe { &mut *(self.0.as_mut().as_mut_ptr() as *mut $vec2) },
-        //         1 => unsafe { &mut *(self.0.as_mut()[2..].as_mut_ptr() as *mut $vec2) },
-        //         _ => panic!(
-        //             "index out of bounds: the len is 2 but the index is {}",
-        //             index
-        //         ),
-        //     }
-        // }
-
         /// Returns `true` if, and only if, all elements are finite.
         /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
         #[inline]
@@ -243,12 +248,7 @@ macro_rules! impl_mat2_traits {
             $mat2::from_cols(x_axis, y_axis)
         }
 
-        impl Default for $mat2 {
-            #[inline(always)]
-            fn default() -> Self {
-                Self::IDENTITY
-            }
-        }
+        impl_matn_common_traits!($t, $mat2, $vec2);
 
         impl PartialEq for $mat2 {
             #[inline]
@@ -271,54 +271,6 @@ macro_rules! impl_mat2_traits {
             }
         }
 
-        impl Add<$mat2> for $mat2 {
-            type Output = Self;
-            #[inline(always)]
-            fn add(self, other: Self) -> Self {
-                Self(self.0.add_matrix(&other.0))
-            }
-        }
-
-        impl Sub<$mat2> for $mat2 {
-            type Output = Self;
-            #[inline(always)]
-            fn sub(self, other: Self) -> Self {
-                Self(self.0.sub_matrix(&other.0))
-            }
-        }
-
-        impl Mul<$mat2> for $mat2 {
-            type Output = Self;
-            #[inline(always)]
-            fn mul(self, other: Self) -> Self {
-                Self(self.0.mul_matrix(&other.0))
-            }
-        }
-
-        impl Mul<$vec2> for $mat2 {
-            type Output = $vec2;
-            #[inline(always)]
-            fn mul(self, other: $vec2) -> $vec2 {
-                $vec2(self.0.mul_vector(other.0))
-            }
-        }
-
-        impl Mul<$mat2> for $t {
-            type Output = $mat2;
-            #[inline(always)]
-            fn mul(self, other: $mat2) -> $mat2 {
-                $mat2(other.0.mul_scalar(self))
-            }
-        }
-
-        impl Mul<$t> for $mat2 {
-            type Output = Self;
-            #[inline(always)]
-            fn mul(self, other: $t) -> Self {
-                Self(self.0.mul_scalar(other))
-            }
-        }
-
         impl Deref for $mat2 {
             type Target = Columns2<$vec2>;
             #[inline(always)]
@@ -357,26 +309,6 @@ macro_rules! impl_mat2_traits {
                 write!(f, "[{}, {}]", self.x_axis, self.y_axis)
             }
         }
-
-        #[cfg(feature = "std")]
-        impl<'a> Sum<&'a Self> for $mat2 {
-            fn sum<I>(iter: I) -> Self
-            where
-                I: Iterator<Item = &'a Self>,
-            {
-                iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
-            }
-        }
-
-        #[cfg(feature = "std")]
-        impl<'a> Product<&'a Self> for $mat2 {
-            fn product<I>(iter: I) -> Self
-            where
-                I: Iterator<Item = &'a Self>,
-            {
-                iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
-            }
-        }
     };
 }
 
diff --git a/src/mat3.rs b/src/mat3.rs
index f71bf3f..dcc4aa8 100644
--- a/src/mat3.rs
+++ b/src/mat3.rs
@@ -5,7 +5,7 @@ use crate::core::{
 use crate::{DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat2, Mat4, Quat, Vec2, Vec3, Vec3A};
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
-use core::ops::{Add, Deref, DerefMut, Mul, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign};
 
 #[cfg(all(
     target_arch = "x86",
@@ -237,6 +237,24 @@ macro_rules! impl_mat3_methods {
             }
         }
 
+        /// Returns a mutable reference to the matrix column for the given `index`.
+        ///
+        /// # Panics
+        ///
+        /// Panics if `index` is greater than 2.
+        #[inline]
+        pub fn col_mut(&mut self, index: usize) -> &mut $vec3a {
+            match index {
+                0 => &mut self.x_axis,
+                1 => &mut self.y_axis,
+                2 => &mut self.z_axis,
+                _ => panic!(
+                    "index out of bounds: the len is 3 but the index is {}",
+                    index
+                ),
+            }
+        }
+
         /// Returns the matrix row for the given `index`.
         ///
         /// # Panics
@@ -255,19 +273,6 @@ macro_rules! impl_mat3_methods {
             }
         }
 
-        // #[inline]
-        // pub(crate) fn col_mut(&mut self, index: usize) -> &mut $vec3 {
-        //     match index {
-        //         0 => &mut self.x_axis,
-        //         1 => &mut self.y_axis,
-        //         2 => &mut self.z_axis,
-        //         _ => panic!(
-        //             "index out of bounds: the len is 3 but the index is {}",
-        //             index
-        //         ),
-        //     }
-        // }
-
         /// Returns `true` if, and only if, all elements are finite.
         /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
         #[inline]
@@ -377,12 +382,7 @@ macro_rules! impl_mat3_traits {
             $mat3::from_cols(x_axis, y_axis, z_axis)
         }
 
-        impl Default for $mat3 {
-            #[inline(always)]
-            fn default() -> Self {
-                Self::IDENTITY
-            }
-        }
+        impl_matn_common_traits!($t, $mat3, $vec3a);
 
         impl PartialEq for $mat3 {
             #[inline]
@@ -426,80 +426,12 @@ macro_rules! impl_mat3_traits {
             }
         }
 
-        impl Add<$mat3> for $mat3 {
-            type Output = Self;
-            #[inline(always)]
-            fn add(self, other: Self) -> Self {
-                self.add_mat3(&other)
-            }
-        }
-
-        impl Sub<$mat3> for $mat3 {
-            type Output = Self;
-            #[inline(always)]
-            fn sub(self, other: Self) -> Self {
-                self.sub_mat3(&other)
-            }
-        }
-
-        impl Mul<$mat3> for $mat3 {
-            type Output = Self;
-            #[inline(always)]
-            fn mul(self, other: Self) -> Self {
-                self.mul_mat3(&other)
-            }
-        }
-
-        impl Mul<$vec3> for $mat3 {
-            type Output = $vec3;
-            #[inline(always)]
-            fn mul(self, other: $vec3) -> $vec3 {
-                self.mul_vec3(other)
-            }
-        }
-
-        impl Mul<$mat3> for $t {
-            type Output = $mat3;
-            #[inline(always)]
-            fn mul(self, other: $mat3) -> $mat3 {
-                other.mul_scalar(self)
-            }
-        }
-
-        impl Mul<$t> for $mat3 {
-            type Output = Self;
-            #[inline(always)]
-            fn mul(self, other: $t) -> Self {
-                self.mul_scalar(other)
-            }
-        }
-
         impl From<$mat4> for $mat3 {
             /// Creates a 3x3 matrix from the top left submatrix of the given 4x4 matrix.
             fn from(m: $mat4) -> $mat3 {
                 $mat3::from_cols(m.x_axis.into(), m.y_axis.into(), m.z_axis.into())
             }
         }
-
-        #[cfg(feature = "std")]
-        impl<'a> Sum<&'a Self> for $mat3 {
-            fn sum<I>(iter: I) -> Self
-            where
-                I: Iterator<Item = &'a Self>,
-            {
-                iter.fold($mat3::ZERO, |a, &b| Self::add(a, b))
-            }
-        }
-
-        #[cfg(feature = "std")]
-        impl<'a> Product<&'a Self> for $mat3 {
-            fn product<I>(iter: I) -> Self
-            where
-                I: Iterator<Item = &'a Self>,
-            {
-                iter.fold($mat3::IDENTITY, |a, &b| Self::mul(a, b))
-            }
-        }
     };
 }
 
@@ -579,11 +511,11 @@ impl Mat3A {
 }
 impl_mat3_traits!(f32, mat3a, Mat3A, Mat4, Vec3, Vec3A);
 
-impl Mul<Vec3A> for Mat3A {
-    type Output = Vec3A;
+impl Mul<Vec3> for Mat3A {
+    type Output = Vec3;
     #[inline(always)]
-    fn mul(self, other: Vec3A) -> Vec3A {
-        self.mul_vec3a(other)
+    fn mul(self, other: Vec3) -> Vec3 {
+        self.mul_vec3(other)
     }
 }
 
diff --git a/src/mat4.rs b/src/mat4.rs
index cddded6..0a9390e 100644
--- a/src/mat4.rs
+++ b/src/mat4.rs
@@ -22,7 +22,7 @@ use core::arch::x86_64::*;
 
 #[cfg(not(target_arch = "spirv"))]
 use core::fmt;
-use core::ops::{Add, Deref, DerefMut, Mul, Sub};
+use core::ops::{Add, AddAssign, Deref, DerefMut, Mul, MulAssign, Sub, SubAssign};
 
 #[cfg(feature = "std")]
 use std::iter::{Product, Sum};
@@ -277,6 +277,25 @@ macro_rules! impl_mat4_methods {
             }
         }
 
+        /// Returns a mutable reference to the matrix column for the given `index`.
+        ///
+        /// # Panics
+        ///
+        /// Panics if `index` is greater than 3.
+        #[inline]
+        pub fn col_mut(&mut self, index: usize) -> &mut $vec4 {
+            match index {
+                0 => &mut self.x_axis,
+                1 => &mut self.y_axis,
+                2 => &mut self.z_axis,
+                3 => &mut self.w_axis,
+                _ => panic!(
+                    "index out of bounds: the len is 4 but the index is {}",
+                    index
+                ),
+            }
+        }
+
         /// Returns the matrix row for the given `index`.
         ///
         /// # Panics
@@ -296,20 +315,6 @@ macro_rules! impl_mat4_methods {
             }
         }
 
-        // #[inline]
-        // pub(crate) fn col_mut(&mut self, index: usize) -> &mut $vec4 {
-        //     match index {
-        //         0 => &mut self.x_axis,
-        //         1 => &mut self.y_axis,
-        //         2 => &mut self.z_axis,
-        //         3 => &mut self.w_axis,
-        //         _ => panic!(
-        //             "index out of bounds: the len is 4 but the index is {}",
-        //             index
-        //         ),
-        //     }
-        // }
-
         /// Returns `true` if, and only if, all elements are finite.
         /// If any element is either `NaN`, positive or negative infinity, this will return `false`.
         #[inline]
@@ -504,7 +509,7 @@ macro_rules! impl_mat4_methods {
         /// Transforms a 4D vector.
         #[inline(always)]
         pub fn mul_vec4(&self, other: $vec4) -> $vec4 {
-            $vec4(self.0.mul_vector(&other.0))
+            $vec4(self.0.mul_vector(other.0))
         }
 
         /// Multiplies two 4x4 matrices.
@@ -592,10 +597,20 @@ macro_rules! impl_mat4_traits {
             $mat4::from_cols(x_axis, y_axis, z_axis, w_axis)
         }
 
-        impl Default for $mat4 {
+        impl_matn_common_traits!($t, $mat4, $vec4);
+
+        impl Deref for $mat4 {
+            type Target = Columns4<$vec4>;
+            #[inline(always)]
+            fn deref(&self) -> &Self::Target {
+                unsafe { &*(self as *const Self as *const Self::Target) }
+            }
+        }
+
+        impl DerefMut for $mat4 {
             #[inline(always)]
-            fn default() -> Self {
-                Self::IDENTITY
+            fn deref_mut(&mut self) -> &mut Self::Target {
+                unsafe { &mut *(self as *mut Self as *mut Self::Target) }
             }
         }
 
@@ -623,69 +638,6 @@ macro_rules! impl_mat4_traits {
             }
         }
 
-        impl Add<$mat4> for $mat4 {
-            type Output = Self;
-            #[inline(always)]
-            fn add(self, other: Self) -> Self::Output {
-                self.add_mat4(&other)
-            }
-        }
-
-        impl Sub<$mat4> for $mat4 {
-            type Output = Self;
-            #[inline(always)]
-            fn sub(self, other: Self) -> Self::Output {
-                self.sub_mat4(&other)
-            }
-        }
-
-        impl Mul<$mat4> for $mat4 {
-            type Output = Self;
-            #[inline(always)]
-            fn mul(self, other: Self) -> Self::Output {
-                self.mul_mat4(&other)
-            }
-        }
-
-        impl Mul<$vec4> for $mat4 {
-            type Output = $vec4;
-            #[inline(always)]
-            fn mul(self, other: $vec4) -> Self::Output {
-                self.mul_vec4(other)
-            }
-        }
-
-        impl Mul<$mat4> for $t {
-            type Output = $mat4;
-            #[inline(always)]
-            fn mul(self, other: $mat4) -> Self::Output {
-                other.mul_scalar(self)
-            }
-        }
-
-        impl Mul<$t> for $mat4 {
-            type Output = Self;
-            #[inline(always)]
-            fn mul(self, other: $t) -> Self::Output {
-                self.mul_scalar(other)
-            }
-        }
-
-        impl Deref for $mat4 {
-            type Target = Columns4<$vec4>;
-            #[inline(always)]
-            fn deref(&self) -> &Self::Target {
-                unsafe { &*(self as *const Self as *const Self::Target) }
-            }
-        }
-
-        impl DerefMut for $mat4 {
-            #[inline(always)]
-            fn deref_mut(&mut self) -> &mut Self::Target {
-                unsafe { &mut *(self as *mut Self as *mut Self::Target) }
-            }
-        }
-
         #[cfg(not(target_arch = "spirv"))]
         impl fmt::Debug for $mat4 {
             fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
@@ -708,26 +660,6 @@ macro_rules! impl_mat4_traits {
                 )
             }
         }
-
-        #[cfg(feature = "std")]
-        impl<'a> Sum<&'a Self> for $mat4 {
-            fn sum<I>(iter: I) -> Self
-            where
-                I: Iterator<Item = &'a Self>,
-            {
-                iter.fold(Self::ZERO, |a, &b| Self::add(a, b))
-            }
-        }
-
-        #[cfg(feature = "std")]
-        impl<'a> Product<&'a Self> for $mat4 {
-            fn product<I>(iter: I) -> Self
-            where
-                I: Iterator<Item = &'a Self>,
-            {
-                iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b))
-            }
-        }
     };
 }
 


Test patch:
diff --git a/tests/mat2.rs b/tests/mat2.rs
index 01a0501..93bdd7f 100644
--- a/tests/mat2.rs
+++ b/tests/mat2.rs
@@ -46,6 +46,11 @@ macro_rules! impl_mat2_tests {
 
             assert_eq!($newvec2(1.0, 3.0), m.row(0));
             assert_eq!($newvec2(2.0, 4.0), m.row(1));
+
+            *m.col_mut(0) = m.col(0).yx();
+            *m.col_mut(1) = m.col(1).yx();
+            assert_eq!($vec2::new(2.0, 1.0), m.col(0));
+            assert_eq!($vec2::new(4.0, 3.0), m.col(1));
         }
 
         #[test]
@@ -147,27 +152,29 @@ macro_rules! impl_mat2_tests {
         #[test]
         fn test_mat2_ops() {
             let m0 = $mat2::from_cols_array_2d(&MATRIX);
-            assert_eq!(
-                $mat2::from_cols_array_2d(&[[2.0, 4.0], [6.0, 8.0]]),
-                m0 * 2.0
-            );
-            assert_eq!(
-                $mat2::from_cols_array_2d(&[[2.0, 4.0], [6.0, 8.0]]),
-                2.0 * m0
-            );
-            assert_eq!(
-                $mat2::from_cols_array_2d(&[[2.0, 4.0], [6.0, 8.0]]),
-                m0 + m0
-            );
+            let m0x2 = $mat2::from_cols_array_2d(&[[2.0, 4.0], [6.0, 8.0]]);
+            assert_eq!(m0x2, m0 * 2.0);
+            assert_eq!(m0x2, 2.0 * m0);
+            assert_eq!(m0x2, m0 + m0);
             assert_eq!($mat2::ZERO, m0 - m0);
-            assert_approx_eq!(
-                $mat2::from_cols_array_2d(&[[1.0, 2.0], [3.0, 4.0]]),
-                m0 * $mat2::IDENTITY
-            );
-            assert_approx_eq!(
-                $mat2::from_cols_array_2d(&[[1.0, 2.0], [3.0, 4.0]]),
-                $mat2::IDENTITY * m0
-            );
+            assert_approx_eq!(m0, m0 * $mat2::IDENTITY);
+            assert_approx_eq!(m0, $mat2::IDENTITY * m0);
+
+            let mut m1 = m0;
+            m1 *= 2.0;
+            assert_eq!(m0x2, m1);
+
+            let mut m1 = m0;
+            m1 += m0;
+            assert_eq!(m0x2, m1);
+
+            let mut m1 = m0;
+            m1 -= m0;
+            assert_eq!($mat2::ZERO, m1);
+
+            let mut m1 = $mat2::IDENTITY;
+            m1 *= m0;
+            assert_approx_eq!(m0, m1);
         }
 
         #[test]
@@ -215,7 +222,7 @@ macro_rules! impl_mat2_tests {
 
 mod mat2 {
     use super::support::deg;
-    use glam::{const_mat2, mat2, vec2, Mat2, Mat3, Vec2};
+    use glam::{const_mat2, mat2, swizzles::*, vec2, Mat2, Mat3, Vec2};
 
     #[test]
     fn test_align() {
@@ -246,7 +253,7 @@ mod mat2 {
 
 mod dmat2 {
     use super::support::deg;
-    use glam::{const_dmat2, dmat2, dvec2, DMat2, DMat3, DVec2};
+    use glam::{const_dmat2, dmat2, dvec2, swizzles::*, DMat2, DMat3, DVec2};
 
     #[test]
     fn test_align() {
diff --git a/tests/mat3.rs b/tests/mat3.rs
index 4ec3c33..c435d90 100644
--- a/tests/mat3.rs
+++ b/tests/mat3.rs
@@ -70,6 +70,13 @@ macro_rules! impl_mat3_tests {
             assert_eq!($newvec3(1.0, 4.0, 7.0), m.row(0));
             assert_eq!($newvec3(2.0, 5.0, 8.0), m.row(1));
             assert_eq!($newvec3(3.0, 6.0, 9.0), m.row(2));
+
+            *m.col_mut(0) = m.col(0).zyx();
+            *m.col_mut(1) = m.col(1).zyx();
+            *m.col_mut(2) = m.col(2).zyx();
+            assert_eq!($newvec3(3.0, 2.0, 1.0), m.col(0));
+            assert_eq!($newvec3(6.0, 5.0, 4.0), m.col(1));
+            assert_eq!($newvec3(9.0, 8.0, 7.0), m.col(2));
         }
 
         #[test]
@@ -269,6 +276,22 @@ macro_rules! impl_mat3_tests {
             assert_eq!($mat3::ZERO, m0 - m0);
             assert_approx_eq!(m0, m0 * $mat3::IDENTITY);
             assert_approx_eq!(m0, $mat3::IDENTITY * m0);
+
+            let mut m1 = m0;
+            m1 *= 2.0;
+            assert_eq!(m0x2, m1);
+
+            let mut m1 = m0;
+            m1 += m0;
+            assert_eq!(m0x2, m1);
+
+            let mut m1 = m0;
+            m1 -= m0;
+            assert_eq!($mat3::ZERO, m1);
+
+            let mut m1 = $mat3::IDENTITY;
+            m1 *= m0;
+            assert_approx_eq!(m0, m1);
         }
 
         #[test]
@@ -313,7 +336,7 @@ macro_rules! impl_mat3_tests {
 
 mod mat3 {
     use super::support::deg;
-    use glam::{const_mat3, mat3, vec3, vec3a, Mat3, Mat4, Vec2, Vec3, Vec3A};
+    use glam::{const_mat3, mat3, swizzles::*, vec3, vec3a, Mat3, Mat4, Vec2, Vec3, Vec3A};
 
     #[test]
     fn test_align() {
@@ -347,7 +370,7 @@ mod mat3 {
 
 mod mat3a {
     use super::support::deg;
-    use glam::{const_mat3a, mat3a, vec3a, Mat3A, Mat4, Vec2, Vec3, Vec3A};
+    use glam::{const_mat3a, mat3a, swizzles::*, vec3a, Mat3A, Mat4, Vec2, Vec3, Vec3A};
 
     #[test]
     fn test_align() {
@@ -377,7 +400,7 @@ mod mat3a {
 
 mod dmat3 {
     use super::support::deg;
-    use glam::{const_dmat3, dmat3, dvec3, DMat3, DMat4, DVec2, DVec3};
+    use glam::{const_dmat3, dmat3, dvec3, swizzles::*, DMat3, DMat4, DVec2, DVec3};
 
     #[test]
     fn test_align() {
diff --git a/tests/mat4.rs b/tests/mat4.rs
index b1057e1..2f4d4cd 100644
--- a/tests/mat4.rs
+++ b/tests/mat4.rs
@@ -107,6 +107,15 @@ macro_rules! impl_mat4_tests {
             assert_eq!($newvec4(2.0, 6.0, 10.0, 14.0), m.row(1));
             assert_eq!($newvec4(3.0, 7.0, 11.0, 15.0), m.row(2));
             assert_eq!($newvec4(4.0, 8.0, 12.0, 16.0), m.row(3));
+
+            *m.col_mut(0) = m.col(0).wzyx();
+            *m.col_mut(1) = m.col(1).wzyx();
+            *m.col_mut(2) = m.col(2).wzyx();
+            *m.col_mut(3) = m.col(3).wzyx();
+            assert_eq!($newvec4(4.0, 3.0, 2.0, 1.0), m.col(0));
+            assert_eq!($newvec4(8.0, 7.0, 6.0, 5.0), m.col(1));
+            assert_eq!($newvec4(12.0, 11.0, 10.0, 9.0), m.col(2));
+            assert_eq!($newvec4(16.0, 15.0, 14.0, 13.0), m.col(3));
         }
 
         #[test]
@@ -543,6 +552,22 @@ macro_rules! impl_mat4_tests {
             assert_eq!($mat4::ZERO, m0 - m0);
             assert_approx_eq!(m0, m0 * $mat4::IDENTITY);
             assert_approx_eq!(m0, $mat4::IDENTITY * m0);
+
+            let mut m1 = m0;
+            m1 *= 2.0;
+            assert_eq!(m0x2, m1);
+
+            let mut m1 = m0;
+            m1 += m0;
+            assert_eq!(m0x2, m1);
+
+            let mut m1 = m0;
+            m1 -= m0;
+            assert_eq!($mat4::ZERO, m1);
+
+            let mut m1 = $mat4::IDENTITY;
+            m1 *= m0;
+            assert_approx_eq!(m0, m1);
         }
 
         #[test]
@@ -593,7 +618,7 @@ macro_rules! impl_mat4_tests {
 
 mod mat4 {
     use super::support::deg;
-    use glam::{const_mat4, mat4, vec3, vec4, Mat4, Quat, Vec3, Vec4};
+    use glam::{const_mat4, mat4, swizzles::*, vec3, vec4, Mat4, Quat, Vec3, Vec4};
 
     #[test]
     fn test_align() {
@@ -646,7 +671,7 @@ mod mat4 {
 
 mod dmat4 {
     use super::support::deg;
-    use glam::{const_dmat4, dmat4, dvec3, dvec4, DMat4, DQuat, DVec3, DVec4};
+    use glam::{const_dmat4, dmat4, dvec3, dvec4, swizzles::*, DMat4, DQuat, DVec3, DVec4};
 
     #[test]
     fn test_align() {