Repository: bitshifter/glam-rs
Pull request #461 (2024-01-11 00:34:26)

Signed and unsigned wrapping and saturating add and sub for integer v…
…ectors. (#460)


Patch:
diff --git a/codegen/templates/vec.rs.tera b/codegen/templates/vec.rs.tera
index 6a73bc8..d59c2c8 100644
--- a/codegen/templates/vec.rs.tera
+++ b/codegen/templates/vec.rs.tera
@@ -43,6 +43,7 @@
     {% set is_signed = true %}
     {% set is_float = false %}
     {% set self_t = "I16Vec" ~ dim %}
+    {% set opposite_signedness_t = "U16Vec" ~ dim %}
     {% set vec2_t = "I16Vec2" %}
     {% set vec3_t = "I16Vec3" %}
     {% set vec4_t = "I16Vec4" %}
@@ -51,6 +52,7 @@
     {% set is_signed = false %}
     {% set is_float = false %}
     {% set self_t = "U16Vec" ~ dim %}
+    {% set opposite_signedness_t = "I16Vec" ~ dim %}
     {% set vec2_t = "U16Vec2" %}
     {% set vec3_t = "U16Vec3" %}
     {% set vec4_t = "U16Vec4" %}
@@ -59,6 +61,7 @@
     {% set is_signed = true %}
     {% set is_float = false %}
     {% set self_t = "IVec" ~ dim %}
+    {% set opposite_signedness_t = "UVec" ~ dim %}
     {% set vec2_t = "IVec2" %}
     {% set vec3_t = "IVec3" %}
     {% set vec4_t = "IVec4" %}
@@ -68,6 +71,7 @@
     {% set is_signed = false %}
     {% set is_float = false %}
     {% set self_t = "UVec" ~ dim %}
+    {% set opposite_signedness_t = "IVec" ~ dim %}
     {% set vec2_t = "UVec2" %}
     {% set vec3_t = "UVec3" %}
     {% set vec4_t = "UVec4" %}
@@ -77,6 +81,7 @@
     {% set is_signed = true %}
     {% set is_float = false %}
     {% set self_t = "I64Vec" ~ dim %}
+    {% set opposite_signedness_t = "U64Vec" ~ dim %}
     {% set vec2_t = "I64Vec2" %}
     {% set vec3_t = "I64Vec3" %}
     {% set vec4_t = "I64Vec4" %}
@@ -86,6 +91,7 @@
     {% set is_signed = false %}
     {% set is_float = false %}
     {% set self_t = "U64Vec" ~ dim %}
+    {% set opposite_signedness_t = "I64Vec" ~ dim %}
     {% set vec2_t = "U64Vec2" %}
     {% set vec3_t = "U64Vec3" %}
     {% set vec4_t = "U64Vec4" %}
@@ -2019,6 +2025,85 @@ impl {{ self_t }} {
             {%- endfor %}
         }
     }
+    {% if is_signed %}
+        /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+        ///
+        /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+        #[inline]
+        #[must_use]
+        pub const fn wrapping_add_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self {
+            Self {
+                {% for c in components %}
+                    {{ c }}: self.{{ c }}.wrapping_add_unsigned(rhs.{{ c }}),
+                {%- endfor %}
+            }
+        }
+
+        /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+        ///
+        /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+        #[inline]
+        #[must_use]
+        pub const fn wrapping_sub_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self {
+            Self {
+                {% for c in components %}
+                    {{ c }}: self.{{ c }}.wrapping_sub_unsigned(rhs.{{ c }}),
+                {%- endfor %}
+            }
+        }
+
+        // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+        ///
+        /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+        #[inline]
+        #[must_use]
+        pub const fn saturating_add_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self {
+            Self {
+                {% for c in components %}
+                    {{ c }}: self.{{ c }}.saturating_add_unsigned(rhs.{{ c }}),
+                {%- endfor %}
+            }
+        }
+
+        /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+        ///
+        /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+        #[inline]
+        #[must_use]
+        pub const fn saturating_sub_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self {
+            Self {
+                {% for c in components %}
+                    {{ c }}: self.{{ c }}.saturating_sub_unsigned(rhs.{{ c }}),
+                {%- endfor %}
+            }
+        }
+    {% else %}
+        /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+        ///
+        /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+        #[inline]
+        #[must_use]
+        pub const fn wrapping_add_signed(self, rhs: {{ opposite_signedness_t }}) -> Self {
+            Self {
+                {% for c in components %}
+                    {{ c }}: self.{{ c }}.wrapping_add_signed(rhs.{{ c }}),
+                {%- endfor %}
+            }
+        }
+
+        /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+        ///
+        /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+        #[inline]
+        #[must_use]
+        pub const fn saturating_add_signed(self, rhs: {{ opposite_signedness_t }}) -> Self {
+            Self {
+                {% for c in components %}
+                    {{ c }}: self.{{ c }}.saturating_add_signed(rhs.{{ c }}),
+                {%- endfor %}
+            }
+        }
+    {% endif %}
 {% endif %}
 }
 
diff --git a/src/i16/i16vec2.rs b/src/i16/i16vec2.rs
index 7f06c1c..612b344 100644
--- a/src/i16/i16vec2.rs
+++ b/src/i16/i16vec2.rs
@@ -511,6 +511,54 @@ impl I16Vec2 {
             y: self.y.saturating_div(rhs.y),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: U16Vec2) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: U16Vec2) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: U16Vec2) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: U16Vec2) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+        }
+    }
 }
 
 impl Default for I16Vec2 {
diff --git a/src/i16/i16vec3.rs b/src/i16/i16vec3.rs
index 5bdc6a7..4836573 100644
--- a/src/i16/i16vec3.rs
+++ b/src/i16/i16vec3.rs
@@ -548,6 +548,58 @@ impl I16Vec3 {
             z: self.z.saturating_div(rhs.z),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: U16Vec3) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+            z: self.z.wrapping_add_unsigned(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: U16Vec3) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+            z: self.z.wrapping_sub_unsigned(rhs.z),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: U16Vec3) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+            z: self.z.saturating_add_unsigned(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: U16Vec3) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+            z: self.z.saturating_sub_unsigned(rhs.z),
+        }
+    }
 }
 
 impl Default for I16Vec3 {
diff --git a/src/i16/i16vec4.rs b/src/i16/i16vec4.rs
index 9db87cc..e717747 100644
--- a/src/i16/i16vec4.rs
+++ b/src/i16/i16vec4.rs
@@ -574,6 +574,62 @@ impl I16Vec4 {
             w: self.w.saturating_div(rhs.w),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: U16Vec4) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+            z: self.z.wrapping_add_unsigned(rhs.z),
+            w: self.w.wrapping_add_unsigned(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: U16Vec4) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+            z: self.z.wrapping_sub_unsigned(rhs.z),
+            w: self.w.wrapping_sub_unsigned(rhs.w),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: U16Vec4) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+            z: self.z.saturating_add_unsigned(rhs.z),
+            w: self.w.saturating_add_unsigned(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: U16Vec4) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+            z: self.z.saturating_sub_unsigned(rhs.z),
+            w: self.w.saturating_sub_unsigned(rhs.w),
+        }
+    }
 }
 
 impl Default for I16Vec4 {
diff --git a/src/i32/ivec2.rs b/src/i32/ivec2.rs
index fdc4c81..b3a90ff 100644
--- a/src/i32/ivec2.rs
+++ b/src/i32/ivec2.rs
@@ -511,6 +511,54 @@ impl IVec2 {
             y: self.y.saturating_div(rhs.y),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: UVec2) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: UVec2) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: UVec2) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: UVec2) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+        }
+    }
 }
 
 impl Default for IVec2 {
diff --git a/src/i32/ivec3.rs b/src/i32/ivec3.rs
index 1a8425b..dc71e8f 100644
--- a/src/i32/ivec3.rs
+++ b/src/i32/ivec3.rs
@@ -548,6 +548,58 @@ impl IVec3 {
             z: self.z.saturating_div(rhs.z),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: UVec3) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+            z: self.z.wrapping_add_unsigned(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: UVec3) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+            z: self.z.wrapping_sub_unsigned(rhs.z),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: UVec3) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+            z: self.z.saturating_add_unsigned(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: UVec3) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+            z: self.z.saturating_sub_unsigned(rhs.z),
+        }
+    }
 }
 
 impl Default for IVec3 {
diff --git a/src/i32/ivec4.rs b/src/i32/ivec4.rs
index 5ebdd69..7d5fbb8 100644
--- a/src/i32/ivec4.rs
+++ b/src/i32/ivec4.rs
@@ -574,6 +574,62 @@ impl IVec4 {
             w: self.w.saturating_div(rhs.w),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: UVec4) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+            z: self.z.wrapping_add_unsigned(rhs.z),
+            w: self.w.wrapping_add_unsigned(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: UVec4) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+            z: self.z.wrapping_sub_unsigned(rhs.z),
+            w: self.w.wrapping_sub_unsigned(rhs.w),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: UVec4) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+            z: self.z.saturating_add_unsigned(rhs.z),
+            w: self.w.saturating_add_unsigned(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: UVec4) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+            z: self.z.saturating_sub_unsigned(rhs.z),
+            w: self.w.saturating_sub_unsigned(rhs.w),
+        }
+    }
 }
 
 impl Default for IVec4 {
diff --git a/src/i64/i64vec2.rs b/src/i64/i64vec2.rs
index b1355d1..b90c08c 100644
--- a/src/i64/i64vec2.rs
+++ b/src/i64/i64vec2.rs
@@ -511,6 +511,54 @@ impl I64Vec2 {
             y: self.y.saturating_div(rhs.y),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: U64Vec2) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: U64Vec2) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: U64Vec2) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: U64Vec2) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+        }
+    }
 }
 
 impl Default for I64Vec2 {
diff --git a/src/i64/i64vec3.rs b/src/i64/i64vec3.rs
index 336e817..5261d90 100644
--- a/src/i64/i64vec3.rs
+++ b/src/i64/i64vec3.rs
@@ -548,6 +548,58 @@ impl I64Vec3 {
             z: self.z.saturating_div(rhs.z),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: U64Vec3) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+            z: self.z.wrapping_add_unsigned(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: U64Vec3) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+            z: self.z.wrapping_sub_unsigned(rhs.z),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: U64Vec3) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+            z: self.z.saturating_add_unsigned(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: U64Vec3) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+            z: self.z.saturating_sub_unsigned(rhs.z),
+        }
+    }
 }
 
 impl Default for I64Vec3 {
diff --git a/src/i64/i64vec4.rs b/src/i64/i64vec4.rs
index bd4c0c1..ddb3252 100644
--- a/src/i64/i64vec4.rs
+++ b/src/i64/i64vec4.rs
@@ -574,6 +574,62 @@ impl I64Vec4 {
             w: self.w.saturating_div(rhs.w),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_unsigned(self, rhs: U64Vec4) -> Self {
+        Self {
+            x: self.x.wrapping_add_unsigned(rhs.x),
+            y: self.y.wrapping_add_unsigned(rhs.y),
+            z: self.z.wrapping_add_unsigned(rhs.z),
+            w: self.w.wrapping_add_unsigned(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_sub_unsigned(self, rhs: U64Vec4) -> Self {
+        Self {
+            x: self.x.wrapping_sub_unsigned(rhs.x),
+            y: self.y.wrapping_sub_unsigned(rhs.y),
+            z: self.z.wrapping_sub_unsigned(rhs.z),
+            w: self.w.wrapping_sub_unsigned(rhs.w),
+        }
+    }
+
+    // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_unsigned(self, rhs: U64Vec4) -> Self {
+        Self {
+            x: self.x.saturating_add_unsigned(rhs.x),
+            y: self.y.saturating_add_unsigned(rhs.y),
+            z: self.z.saturating_add_unsigned(rhs.z),
+            w: self.w.saturating_add_unsigned(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_sub_unsigned(self, rhs: U64Vec4) -> Self {
+        Self {
+            x: self.x.saturating_sub_unsigned(rhs.x),
+            y: self.y.saturating_sub_unsigned(rhs.y),
+            z: self.z.saturating_sub_unsigned(rhs.z),
+            w: self.w.saturating_sub_unsigned(rhs.w),
+        }
+    }
 }
 
 impl Default for I64Vec4 {
diff --git a/src/u16/u16vec2.rs b/src/u16/u16vec2.rs
index 3ee390c..f00d41c 100644
--- a/src/u16/u16vec2.rs
+++ b/src/u16/u16vec2.rs
@@ -406,6 +406,30 @@ impl U16Vec2 {
             y: self.y.saturating_div(rhs.y),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: I16Vec2) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: I16Vec2) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+        }
+    }
 }
 
 impl Default for U16Vec2 {
diff --git a/src/u16/u16vec3.rs b/src/u16/u16vec3.rs
index e2859a0..334e7bb 100644
--- a/src/u16/u16vec3.rs
+++ b/src/u16/u16vec3.rs
@@ -461,6 +461,32 @@ impl U16Vec3 {
             z: self.z.saturating_div(rhs.z),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: I16Vec3) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+            z: self.z.wrapping_add_signed(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: I16Vec3) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+            z: self.z.saturating_add_signed(rhs.z),
+        }
+    }
 }
 
 impl Default for U16Vec3 {
diff --git a/src/u16/u16vec4.rs b/src/u16/u16vec4.rs
index e6b68e5..33ee151 100644
--- a/src/u16/u16vec4.rs
+++ b/src/u16/u16vec4.rs
@@ -479,6 +479,34 @@ impl U16Vec4 {
             w: self.w.saturating_div(rhs.w),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: I16Vec4) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+            z: self.z.wrapping_add_signed(rhs.z),
+            w: self.w.wrapping_add_signed(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: I16Vec4) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+            z: self.z.saturating_add_signed(rhs.z),
+            w: self.w.saturating_add_signed(rhs.w),
+        }
+    }
 }
 
 impl Default for U16Vec4 {
diff --git a/src/u32/uvec2.rs b/src/u32/uvec2.rs
index 39fbf9a..bd7ad48 100644
--- a/src/u32/uvec2.rs
+++ b/src/u32/uvec2.rs
@@ -406,6 +406,30 @@ impl UVec2 {
             y: self.y.saturating_div(rhs.y),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: IVec2) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: IVec2) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+        }
+    }
 }
 
 impl Default for UVec2 {
diff --git a/src/u32/uvec3.rs b/src/u32/uvec3.rs
index ca06d46..b9945c5 100644
--- a/src/u32/uvec3.rs
+++ b/src/u32/uvec3.rs
@@ -461,6 +461,32 @@ impl UVec3 {
             z: self.z.saturating_div(rhs.z),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: IVec3) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+            z: self.z.wrapping_add_signed(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: IVec3) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+            z: self.z.saturating_add_signed(rhs.z),
+        }
+    }
 }
 
 impl Default for UVec3 {
diff --git a/src/u32/uvec4.rs b/src/u32/uvec4.rs
index 1e64072..60bd896 100644
--- a/src/u32/uvec4.rs
+++ b/src/u32/uvec4.rs
@@ -479,6 +479,34 @@ impl UVec4 {
             w: self.w.saturating_div(rhs.w),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: IVec4) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+            z: self.z.wrapping_add_signed(rhs.z),
+            w: self.w.wrapping_add_signed(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: IVec4) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+            z: self.z.saturating_add_signed(rhs.z),
+            w: self.w.saturating_add_signed(rhs.w),
+        }
+    }
 }
 
 impl Default for UVec4 {
diff --git a/src/u64/u64vec2.rs b/src/u64/u64vec2.rs
index 4f74652..0548370 100644
--- a/src/u64/u64vec2.rs
+++ b/src/u64/u64vec2.rs
@@ -406,6 +406,30 @@ impl U64Vec2 {
             y: self.y.saturating_div(rhs.y),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: I64Vec2) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: I64Vec2) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+        }
+    }
 }
 
 impl Default for U64Vec2 {
diff --git a/src/u64/u64vec3.rs b/src/u64/u64vec3.rs
index 7411bff..57baf75 100644
--- a/src/u64/u64vec3.rs
+++ b/src/u64/u64vec3.rs
@@ -461,6 +461,32 @@ impl U64Vec3 {
             z: self.z.saturating_div(rhs.z),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: I64Vec3) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+            z: self.z.wrapping_add_signed(rhs.z),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: I64Vec3) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+            z: self.z.saturating_add_signed(rhs.z),
+        }
+    }
 }
 
 impl Default for U64Vec3 {
diff --git a/src/u64/u64vec4.rs b/src/u64/u64vec4.rs
index 91df699..b1b6de4 100644
--- a/src/u64/u64vec4.rs
+++ b/src/u64/u64vec4.rs
@@ -479,6 +479,34 @@ impl U64Vec4 {
             w: self.w.saturating_div(rhs.w),
         }
     }
+
+    /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn wrapping_add_signed(self, rhs: I64Vec4) -> Self {
+        Self {
+            x: self.x.wrapping_add_signed(rhs.x),
+            y: self.y.wrapping_add_signed(rhs.y),
+            z: self.z.wrapping_add_signed(rhs.z),
+            w: self.w.wrapping_add_signed(rhs.w),
+        }
+    }
+
+    /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`.
+    ///
+    /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`.
+    #[inline]
+    #[must_use]
+    pub const fn saturating_add_signed(self, rhs: I64Vec4) -> Self {
+        Self {
+            x: self.x.saturating_add_signed(rhs.x),
+            y: self.y.saturating_add_signed(rhs.y),
+            z: self.z.saturating_add_signed(rhs.z),
+            w: self.w.saturating_add_signed(rhs.w),
+        }
+    }
 }
 
 impl Default for U64Vec4 {


Test patch:
diff --git a/tests/vec2.rs b/tests/vec2.rs
index 6f57be3..c71ed29 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -1274,6 +1274,34 @@ mod i16vec2 {
         );
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, i16::MAX).wrapping_add_unsigned(U16Vec2::new(1, 1)),
+            I16Vec2::new(i16::MIN, i16::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            I16Vec2::new(i16::MIN, i16::MIN).wrapping_sub_unsigned(U16Vec2::new(1, 1)),
+            I16Vec2::new(i16::MAX, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            I16Vec2::new(i16::MAX, i16::MAX).saturating_add_unsigned(U16Vec2::new(1, 1)),
+            I16Vec2::new(i16::MAX, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            I16Vec2::new(i16::MIN, i16::MIN).saturating_sub_unsigned(U16Vec2::new(1, 1)),
+            I16Vec2::new(i16::MIN, i16::MIN)
+        );
+    });
+
     impl_vec2_signed_integer_tests!(i16, i16vec2, I16Vec2, I16Vec3, BVec2);
     impl_vec2_eq_hash_tests!(i16, i16vec2);
 
@@ -1395,6 +1423,20 @@ mod u16vec2 {
         );
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, u16::MAX).wrapping_add_signed(I16Vec2::new(1, 1)),
+            U16Vec2::new(u16::MIN, u16::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            U16Vec2::new(u16::MAX, u16::MAX).saturating_add_signed(I16Vec2::new(1, 1)),
+            U16Vec2::new(u16::MAX, u16::MAX)
+        );
+    });
+
     impl_vec2_tests!(u16, u16vec2, U16Vec2, U16Vec3, BVec2);
     impl_vec2_eq_hash_tests!(u16, u16vec2);
 
@@ -1498,6 +1540,34 @@ mod ivec2 {
         );
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            IVec2::new(i32::MAX, i32::MAX).wrapping_add_unsigned(UVec2::new(1, 1)),
+            IVec2::new(i32::MIN, i32::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            IVec2::new(i32::MIN, i32::MIN).wrapping_sub_unsigned(UVec2::new(1, 1)),
+            IVec2::new(i32::MAX, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            IVec2::new(i32::MAX, i32::MAX).saturating_add_unsigned(UVec2::new(1, 1)),
+            IVec2::new(i32::MAX, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            IVec2::new(i32::MIN, i32::MIN).saturating_sub_unsigned(UVec2::new(1, 1)),
+            IVec2::new(i32::MIN, i32::MIN)
+        );
+    });
+
     impl_vec2_signed_integer_tests!(i32, ivec2, IVec2, IVec3, BVec2);
     impl_vec2_eq_hash_tests!(i32, ivec2);
 
@@ -1610,6 +1680,20 @@ mod uvec2 {
         );
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            UVec2::new(u32::MAX, u32::MAX).wrapping_add_signed(IVec2::new(1, 1)),
+            UVec2::new(u32::MIN, u32::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            UVec2::new(u32::MAX, u32::MAX).saturating_add_signed(IVec2::new(1, 1)),
+            UVec2::new(u32::MAX, u32::MAX)
+        );
+    });
+
     impl_vec2_tests!(u32, uvec2, UVec2, UVec3, BVec2);
     impl_vec2_eq_hash_tests!(u32, uvec2);
 
@@ -1648,6 +1732,34 @@ mod i64vec2 {
         assert!(I64Vec2::try_from(U64Vec2::new(1, u64::MAX)).is_err());
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            I64Vec2::new(i64::MAX, i64::MAX).wrapping_add_unsigned(U64Vec2::new(1, 1)),
+            I64Vec2::new(i64::MIN, i64::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            I64Vec2::new(i64::MIN, i64::MIN).wrapping_sub_unsigned(U64Vec2::new(1, 1)),
+            I64Vec2::new(i64::MAX, i64::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            I64Vec2::new(i64::MAX, i64::MAX).saturating_add_unsigned(U64Vec2::new(1, 1)),
+            I64Vec2::new(i64::MAX, i64::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            I64Vec2::new(i64::MIN, i64::MIN).saturating_sub_unsigned(U64Vec2::new(1, 1)),
+            I64Vec2::new(i64::MIN, i64::MIN)
+        );
+    });
+
     impl_vec2_signed_integer_tests!(i64, i64vec2, I64Vec2, I64Vec3, BVec2);
     impl_vec2_eq_hash_tests!(i64, i64vec2);
 
@@ -1699,6 +1811,20 @@ mod u64vec2 {
         assert!(U64Vec2::try_from(I64Vec2::new(1, -2)).is_err());
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            U64Vec2::new(u64::MAX, u64::MAX).wrapping_add_signed(I64Vec2::new(1, 1)),
+            U64Vec2::new(u64::MIN, u64::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            U64Vec2::new(u64::MAX, u64::MAX).saturating_add_signed(I64Vec2::new(1, 1)),
+            U64Vec2::new(u64::MAX, u64::MAX)
+        );
+    });
+
     impl_vec2_tests!(u64, u64vec2, U64Vec2, U64Vec3, BVec2);
     impl_vec2_eq_hash_tests!(u64, u64vec2);
 
diff --git a/tests/vec3.rs b/tests/vec3.rs
index 5c8ed97..af1a479 100644
--- a/tests/vec3.rs
+++ b/tests/vec3.rs
@@ -1562,6 +1562,36 @@ mod i16vec3 {
         );
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, i16::MAX, i16::MAX).wrapping_add_unsigned(U16Vec3::new(1, 1, 1)),
+            I16Vec3::new(i16::MIN, i16::MIN, i16::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            I16Vec3::new(i16::MIN, i16::MIN, i16::MIN).wrapping_sub_unsigned(U16Vec3::new(1, 1, 1)),
+            I16Vec3::new(i16::MAX, i16::MAX, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            I16Vec3::new(i16::MAX, i16::MAX, i16::MAX)
+                .saturating_add_unsigned(U16Vec3::new(1, 1, 1)),
+            I16Vec3::new(i16::MAX, i16::MAX, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            I16Vec3::new(i16::MIN, i16::MIN, i16::MIN)
+                .saturating_sub_unsigned(U16Vec3::new(1, 1, 1)),
+            I16Vec3::new(i16::MIN, i16::MIN, i16::MIN)
+        );
+    });
+
     impl_vec3_signed_integer_tests!(i16, i16vec3, I16Vec3, BVec3);
     impl_vec3_eq_hash_tests!(i16, i16vec3);
 
@@ -1687,6 +1717,20 @@ mod u16vec3 {
         );
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, u16::MAX, u16::MAX).wrapping_add_signed(I16Vec3::new(1, 1, 1)),
+            U16Vec3::new(u16::MIN, u16::MIN, u16::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            U16Vec3::new(u16::MAX, u16::MAX, u16::MAX).saturating_add_signed(I16Vec3::new(1, 1, 1)),
+            U16Vec3::new(u16::MAX, u16::MAX, u16::MAX)
+        );
+    });
+
     impl_vec3_tests!(u16, u16vec3, U16Vec3, BVec3);
     impl_vec3_eq_hash_tests!(u16, u16vec3);
 
@@ -1793,6 +1837,34 @@ mod ivec3 {
         );
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            IVec3::new(i32::MAX, i32::MAX, i32::MAX).wrapping_add_unsigned(UVec3::new(1, 1, 1)),
+            IVec3::new(i32::MIN, i32::MIN, i32::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            IVec3::new(i32::MIN, i32::MIN, i32::MIN).wrapping_sub_unsigned(UVec3::new(1, 1, 1)),
+            IVec3::new(i32::MAX, i32::MAX, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            IVec3::new(i32::MAX, i32::MAX, i32::MAX).saturating_add_unsigned(UVec3::new(1, 1, 1)),
+            IVec3::new(i32::MAX, i32::MAX, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            IVec3::new(i32::MIN, i32::MIN, i32::MIN).saturating_sub_unsigned(UVec3::new(1, 1, 1)),
+            IVec3::new(i32::MIN, i32::MIN, i32::MIN)
+        );
+    });
+
     impl_vec3_signed_integer_tests!(i32, ivec3, IVec3, BVec3);
     impl_vec3_eq_hash_tests!(i32, ivec3);
 
@@ -1910,6 +1982,20 @@ mod uvec3 {
         );
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            UVec3::new(u32::MAX, u32::MAX, u32::MAX).wrapping_add_signed(IVec3::new(1, 1, 1)),
+            UVec3::new(u32::MIN, u32::MIN, u32::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            UVec3::new(u32::MAX, u32::MAX, u32::MAX).saturating_add_signed(IVec3::new(1, 1, 1)),
+            UVec3::new(u32::MAX, u32::MAX, u32::MAX)
+        );
+    });
+
     impl_vec3_tests!(u32, uvec3, UVec3, BVec3);
     impl_vec3_eq_hash_tests!(u32, uvec3);
 
@@ -1946,6 +2032,36 @@ mod i64vec3 {
         assert!(I64Vec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err());
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            I64Vec3::new(i64::MAX, i64::MAX, i64::MAX).wrapping_add_unsigned(U64Vec3::new(1, 1, 1)),
+            I64Vec3::new(i64::MIN, i64::MIN, i64::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            I64Vec3::new(i64::MIN, i64::MIN, i64::MIN).wrapping_sub_unsigned(U64Vec3::new(1, 1, 1)),
+            I64Vec3::new(i64::MAX, i64::MAX, i64::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            I64Vec3::new(i64::MAX, i64::MAX, i64::MAX)
+                .saturating_add_unsigned(U64Vec3::new(1, 1, 1)),
+            I64Vec3::new(i64::MAX, i64::MAX, i64::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            I64Vec3::new(i64::MIN, i64::MIN, i64::MIN)
+                .saturating_sub_unsigned(U64Vec3::new(1, 1, 1)),
+            I64Vec3::new(i64::MIN, i64::MIN, i64::MIN)
+        );
+    });
+
     impl_vec3_signed_integer_tests!(i64, i64vec3, I64Vec3, BVec3);
     impl_vec3_eq_hash_tests!(i64, i64vec3);
 
@@ -1997,6 +2113,20 @@ mod u64vec3 {
         assert!(U64Vec3::try_from(I64Vec3::new(1, 2, -3)).is_err());
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            U64Vec3::new(u64::MAX, u64::MAX, u64::MAX).wrapping_add_signed(I64Vec3::new(1, 1, 1)),
+            U64Vec3::new(u64::MIN, u64::MIN, u64::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            U64Vec3::new(u64::MAX, u64::MAX, u64::MAX).saturating_add_signed(I64Vec3::new(1, 1, 1)),
+            U64Vec3::new(u64::MAX, u64::MAX, u64::MAX)
+        );
+    });
+
     impl_vec3_tests!(u64, u64vec3, U64Vec3, BVec3);
     impl_vec3_eq_hash_tests!(u64, u64vec3);
 
diff --git a/tests/vec4.rs b/tests/vec4.rs
index 22ce97f..e0dcd9e 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -1721,6 +1721,38 @@ mod i16vec4 {
         );
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX)
+                .wrapping_add_unsigned(U16Vec4::new(1, 1, 1, 1)),
+            I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN)
+                .wrapping_sub_unsigned(U16Vec4::new(1, 1, 1, 1)),
+            I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX)
+                .saturating_add_unsigned(U16Vec4::new(1, 1, 1, 1)),
+            I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN)
+                .saturating_sub_unsigned(U16Vec4::new(1, 1, 1, 1)),
+            I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN)
+        );
+    });
+
     impl_vec4_signed_integer_tests!(i16, i16vec4, I16Vec4, I16Vec3, I16Vec2, BVec4);
     impl_vec4_eq_hash_tests!(i16, i16vec4);
 
@@ -1863,6 +1895,22 @@ mod u16vec4 {
         );
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, u16::MAX, u16::MAX, u16::MAX)
+                .wrapping_add_signed(I16Vec4::new(1, 1, 1, 1)),
+            U16Vec4::new(u16::MIN, u16::MIN, u16::MIN, u16::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            U16Vec4::new(u16::MAX, u16::MAX, u16::MAX, u16::MAX)
+                .saturating_add_signed(I16Vec4::new(1, 1, 1, 1)),
+            U16Vec4::new(u16::MAX, u16::MAX, u16::MAX, u16::MAX)
+        );
+    });
+
     impl_vec4_tests!(u16, u16vec4, U16Vec4, U16Vec3, U16Vec2, BVec4);
     impl_vec4_eq_hash_tests!(u16, u16vec4);
 
@@ -1981,6 +2029,38 @@ mod ivec4 {
         );
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX)
+                .wrapping_add_unsigned(UVec4::new(1, 1, 1, 1)),
+            IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN)
+                .wrapping_sub_unsigned(UVec4::new(1, 1, 1, 1)),
+            IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX)
+                .saturating_add_unsigned(UVec4::new(1, 1, 1, 1)),
+            IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN)
+                .saturating_sub_unsigned(UVec4::new(1, 1, 1, 1)),
+            IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN)
+        );
+    });
+
     impl_vec4_signed_integer_tests!(i32, ivec4, IVec4, IVec3, IVec2, BVec4);
     impl_vec4_eq_hash_tests!(i32, ivec4);
 
@@ -2109,6 +2189,22 @@ mod uvec4 {
         );
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            UVec4::new(u32::MAX, u32::MAX, u32::MAX, u32::MAX)
+                .wrapping_add_signed(IVec4::new(1, 1, 1, 1)),
+            UVec4::new(u32::MIN, u32::MIN, u32::MIN, u32::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            UVec4::new(u32::MAX, u32::MAX, u32::MAX, u32::MAX)
+                .saturating_add_signed(IVec4::new(1, 1, 1, 1)),
+            UVec4::new(u32::MAX, u32::MAX, u32::MAX, u32::MAX)
+        );
+    });
+
     impl_vec4_tests!(u32, uvec4, UVec4, UVec3, UVec2, BVec4);
     impl_vec4_eq_hash_tests!(u32, uvec4);
 
@@ -2163,6 +2259,38 @@ mod i64vec4 {
         assert!(I64Vec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err());
     });
 
+    glam_test!(test_wrapping_add_unsigned, {
+        assert_eq!(
+            I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX)
+                .wrapping_add_unsigned(U64Vec4::new(1, 1, 1, 1)),
+            I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN)
+        );
+    });
+
+    glam_test!(test_wrapping_sub_unsigned, {
+        assert_eq!(
+            I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN)
+                .wrapping_sub_unsigned(U64Vec4::new(1, 1, 1, 1)),
+            I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_add_unsigned, {
+        assert_eq!(
+            I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX)
+                .saturating_add_unsigned(U64Vec4::new(1, 1, 1, 1)),
+            I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX)
+        );
+    });
+
+    glam_test!(test_saturating_sub_unsigned, {
+        assert_eq!(
+            I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN)
+                .saturating_sub_unsigned(U64Vec4::new(1, 1, 1, 1)),
+            I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN)
+        );
+    });
+
     impl_vec4_signed_integer_tests!(i64, i64vec4, I64Vec4, I64Vec3, I64Vec2, BVec4);
     impl_vec4_eq_hash_tests!(i64, i64vec4);
 
@@ -2228,6 +2356,22 @@ mod u64vec4 {
         assert!(U64Vec4::try_from(I64Vec4::new(1, 2, 3, -4)).is_err());
     });
 
+    glam_test!(test_wrapping_add_signed, {
+        assert_eq!(
+            U64Vec4::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX)
+                .wrapping_add_signed(I64Vec4::new(1, 1, 1, 1)),
+            U64Vec4::new(u64::MIN, u64::MIN, u64::MIN, u64::MIN)
+        );
+    });
+
+    glam_test!(test_saturating_add_signed, {
+        assert_eq!(
+            U64Vec4::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX)
+                .saturating_add_signed(I64Vec4::new(1, 1, 1, 1)),
+            U64Vec4::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX)
+        );
+    });
+
     impl_vec4_tests!(u64, u64vec4, U64Vec4, U64Vec3, U64Vec2, BVec4);
     impl_vec4_eq_hash_tests!(u64, u64vec4);