Repository: bitshifter/glam-rs
Pull request #467 (2024-01-27 05:09:03)

Element-wise sum and product for vectors. (#462)
Continuation of  #465


Patch:
diff --git a/codegen/templates/vec.rs.tera b/codegen/templates/vec.rs.tera
index d59c2c8..a1e67e6 100644
--- a/codegen/templates/vec.rs.tera
+++ b/codegen/templates/vec.rs.tera
@@ -754,6 +754,100 @@ impl {{ self_t }} {
         {% endif %}
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> {{ scalar_t }} {
+        {% if is_scalar %}
+            {% for c in components %}
+                self.{{ c }} {% if not loop.last %} + {% endif %}
+            {%- endfor %}
+        {% elif is_sse2 %}
+            {% if dim == 3 %}
+                unsafe {
+                    let v = self.0;
+                    let v = _mm_add_ps(v, _mm_shuffle_ps(v, Self::ZERO.0, 0b00_11_00_01));
+                    let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+                    _mm_cvtss_f32(v)
+                }
+            {% elif dim == 4 %}
+                unsafe {
+                    let v = self.0;
+                    let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01));
+                    let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+                    _mm_cvtss_f32(v)
+                }
+            {% endif %}
+        {% elif is_wasm32 %}
+            {% if dim == 3 %}
+                let v = self.0;
+                let v = f32x4_add(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ZERO.0));
+                let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+                f32x4_extract_lane::<0>(v)
+            {% elif dim == 4 %}
+                let v = self.0;
+                let v = f32x4_add(v, i32x4_shuffle::<1, 0, 3, 0>(v, v));
+                let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+                f32x4_extract_lane::<0>(v)
+            {% endif %}
+        {% elif is_coresimd %}
+            {% if dim == 3 %}
+                simd_swizzle!(self.0, Self::ZERO.0, [0, 1, 2, 4]).reduce_sum()
+            {% elif dim == 4 %}
+                self.0.reduce_sum()
+            {% endif %}
+        {% endif %}
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> {{ scalar_t }} {
+        {% if is_scalar %}
+            {% for c in components %}
+                self.{{ c }} {% if not loop.last %} * {% endif %}
+            {%- endfor %}
+        {% elif is_sse2 %}
+            {% if dim == 3 %}
+                unsafe {
+                    let v = self.0;
+                    let v = _mm_mul_ps(v, _mm_shuffle_ps(v, Self::ONE.0, 0b00_11_00_01));
+                    let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+                    _mm_cvtss_f32(v)
+                }
+            {% elif dim == 4 %}
+                unsafe {
+                    let v = self.0;
+                    let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01));
+                    let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+                    _mm_cvtss_f32(v)
+                }
+            {% endif %}
+        {% elif is_wasm32 %}
+            {% if dim == 3 %}
+                let v = self.0;
+                let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ONE.0));
+                let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+                f32x4_extract_lane::<0>(v)
+            {% elif dim == 4 %}
+                let v = self.0;
+                let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 3, 0>(v, v));
+                let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+                f32x4_extract_lane::<0>(v)
+            {% endif %}
+        {% elif is_coresimd %}
+            {% if dim == 3 %}
+                simd_swizzle!(self.0, Self::ONE.0, [0, 1, 2, 4]).reduce_product()
+            {% elif dim == 4 %}
+                self.0.reduce_product()
+            {% endif %}
+        {% endif %}
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/coresimd/vec3a.rs b/src/f32/coresimd/vec3a.rs
index be280be..45d5675 100644
--- a/src/f32/coresimd/vec3a.rs
+++ b/src/f32/coresimd/vec3a.rs
@@ -245,6 +245,24 @@ impl Vec3A {
         v[0]
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        simd_swizzle!(self.0, Self::ZERO.0, [0, 1, 2, 4]).reduce_sum()
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        simd_swizzle!(self.0, Self::ONE.0, [0, 1, 2, 4]).reduce_product()
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/coresimd/vec4.rs b/src/f32/coresimd/vec4.rs
index a600162..1c22963 100644
--- a/src/f32/coresimd/vec4.rs
+++ b/src/f32/coresimd/vec4.rs
@@ -217,6 +217,24 @@ impl Vec4 {
         self.0.reduce_max()
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        self.0.reduce_sum()
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        self.0.reduce_product()
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/scalar/vec3a.rs b/src/f32/scalar/vec3a.rs
index d92f443..b123a1e 100644
--- a/src/f32/scalar/vec3a.rs
+++ b/src/f32/scalar/vec3a.rs
@@ -257,6 +257,24 @@ impl Vec3A {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/scalar/vec4.rs b/src/f32/scalar/vec4.rs
index 4dc5640..0823987 100644
--- a/src/f32/scalar/vec4.rs
+++ b/src/f32/scalar/vec4.rs
@@ -250,6 +250,24 @@ impl Vec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/sse2/vec3a.rs b/src/f32/sse2/vec3a.rs
index afa2fa2..d442702 100644
--- a/src/f32/sse2/vec3a.rs
+++ b/src/f32/sse2/vec3a.rs
@@ -269,6 +269,34 @@ impl Vec3A {
         }
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        unsafe {
+            let v = self.0;
+            let v = _mm_add_ps(v, _mm_shuffle_ps(v, Self::ZERO.0, 0b00_11_00_01));
+            let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+            _mm_cvtss_f32(v)
+        }
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        unsafe {
+            let v = self.0;
+            let v = _mm_mul_ps(v, _mm_shuffle_ps(v, Self::ONE.0, 0b00_11_00_01));
+            let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+            _mm_cvtss_f32(v)
+        }
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/sse2/vec4.rs b/src/f32/sse2/vec4.rs
index 9adc948..cc4e050 100644
--- a/src/f32/sse2/vec4.rs
+++ b/src/f32/sse2/vec4.rs
@@ -240,6 +240,34 @@ impl Vec4 {
         }
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        unsafe {
+            let v = self.0;
+            let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01));
+            let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+            _mm_cvtss_f32(v)
+        }
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        unsafe {
+            let v = self.0;
+            let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01));
+            let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10));
+            _mm_cvtss_f32(v)
+        }
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index b94dd96..e85dc79 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -205,6 +205,24 @@ impl Vec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/vec3.rs b/src/f32/vec3.rs
index 20a0490..447d571 100644
--- a/src/f32/vec3.rs
+++ b/src/f32/vec3.rs
@@ -248,6 +248,24 @@ impl Vec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/wasm32/vec3a.rs b/src/f32/wasm32/vec3a.rs
index 754823f..c89fb1a 100644
--- a/src/f32/wasm32/vec3a.rs
+++ b/src/f32/wasm32/vec3a.rs
@@ -250,6 +250,30 @@ impl Vec3A {
         f32x4_extract_lane::<0>(v)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        let v = self.0;
+        let v = f32x4_add(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ZERO.0));
+        let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+        f32x4_extract_lane::<0>(v)
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        let v = self.0;
+        let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ONE.0));
+        let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+        f32x4_extract_lane::<0>(v)
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f32/wasm32/vec4.rs b/src/f32/wasm32/vec4.rs
index 10aabd8..992dc64 100644
--- a/src/f32/wasm32/vec4.rs
+++ b/src/f32/wasm32/vec4.rs
@@ -228,6 +228,30 @@ impl Vec4 {
         f32x4_extract_lane::<0>(v)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f32 {
+        let v = self.0;
+        let v = f32x4_add(v, i32x4_shuffle::<1, 0, 3, 0>(v, v));
+        let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+        f32x4_extract_lane::<0>(v)
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f32 {
+        let v = self.0;
+        let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 3, 0>(v, v));
+        let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v));
+        f32x4_extract_lane::<0>(v)
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f64/dvec2.rs b/src/f64/dvec2.rs
index 153ad61..4c8cb86 100644
--- a/src/f64/dvec2.rs
+++ b/src/f64/dvec2.rs
@@ -205,6 +205,24 @@ impl DVec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f64 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f64 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f64/dvec3.rs b/src/f64/dvec3.rs
index 3a0e34f..ba7f93d 100644
--- a/src/f64/dvec3.rs
+++ b/src/f64/dvec3.rs
@@ -248,6 +248,24 @@ impl DVec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f64 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f64 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/f64/dvec4.rs b/src/f64/dvec4.rs
index 02f26c1..29175c8 100644
--- a/src/f64/dvec4.rs
+++ b/src/f64/dvec4.rs
@@ -238,6 +238,24 @@ impl DVec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> f64 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> f64 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i16/i16vec2.rs b/src/i16/i16vec2.rs
index 612b344..58f2442 100644
--- a/src/i16/i16vec2.rs
+++ b/src/i16/i16vec2.rs
@@ -197,6 +197,24 @@ impl I16Vec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i16 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i16 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i16/i16vec3.rs b/src/i16/i16vec3.rs
index 4836573..2717065 100644
--- a/src/i16/i16vec3.rs
+++ b/src/i16/i16vec3.rs
@@ -240,6 +240,24 @@ impl I16Vec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i16 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i16 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i16/i16vec4.rs b/src/i16/i16vec4.rs
index e717747..9b23b91 100644
--- a/src/i16/i16vec4.rs
+++ b/src/i16/i16vec4.rs
@@ -230,6 +230,24 @@ impl I16Vec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i16 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i16 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i32/ivec2.rs b/src/i32/ivec2.rs
index b3a90ff..49d81d3 100644
--- a/src/i32/ivec2.rs
+++ b/src/i32/ivec2.rs
@@ -197,6 +197,24 @@ impl IVec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i32 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i32 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i32/ivec3.rs b/src/i32/ivec3.rs
index dc71e8f..dde78ca 100644
--- a/src/i32/ivec3.rs
+++ b/src/i32/ivec3.rs
@@ -240,6 +240,24 @@ impl IVec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i32 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i32 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i32/ivec4.rs b/src/i32/ivec4.rs
index 7d5fbb8..48bff1e 100644
--- a/src/i32/ivec4.rs
+++ b/src/i32/ivec4.rs
@@ -230,6 +230,24 @@ impl IVec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i32 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i32 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i64/i64vec2.rs b/src/i64/i64vec2.rs
index b90c08c..335d452 100644
--- a/src/i64/i64vec2.rs
+++ b/src/i64/i64vec2.rs
@@ -197,6 +197,24 @@ impl I64Vec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i64 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i64 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i64/i64vec3.rs b/src/i64/i64vec3.rs
index 5261d90..8ac88c3 100644
--- a/src/i64/i64vec3.rs
+++ b/src/i64/i64vec3.rs
@@ -240,6 +240,24 @@ impl I64Vec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i64 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i64 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/i64/i64vec4.rs b/src/i64/i64vec4.rs
index ddb3252..4456cc0 100644
--- a/src/i64/i64vec4.rs
+++ b/src/i64/i64vec4.rs
@@ -230,6 +230,24 @@ impl I64Vec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> i64 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> i64 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u16/u16vec2.rs b/src/u16/u16vec2.rs
index f00d41c..46fe28b 100644
--- a/src/u16/u16vec2.rs
+++ b/src/u16/u16vec2.rs
@@ -188,6 +188,24 @@ impl U16Vec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u16 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u16 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u16/u16vec3.rs b/src/u16/u16vec3.rs
index 334e7bb..7e5db69 100644
--- a/src/u16/u16vec3.rs
+++ b/src/u16/u16vec3.rs
@@ -228,6 +228,24 @@ impl U16Vec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u16 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u16 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u16/u16vec4.rs b/src/u16/u16vec4.rs
index 33ee151..a6390ac 100644
--- a/src/u16/u16vec4.rs
+++ b/src/u16/u16vec4.rs
@@ -215,6 +215,24 @@ impl U16Vec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u16 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u16 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u32/uvec2.rs b/src/u32/uvec2.rs
index bd7ad48..70510de 100644
--- a/src/u32/uvec2.rs
+++ b/src/u32/uvec2.rs
@@ -188,6 +188,24 @@ impl UVec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u32 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u32 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u32/uvec3.rs b/src/u32/uvec3.rs
index b9945c5..3dadd7c 100644
--- a/src/u32/uvec3.rs
+++ b/src/u32/uvec3.rs
@@ -228,6 +228,24 @@ impl UVec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u32 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u32 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u32/uvec4.rs b/src/u32/uvec4.rs
index 60bd896..5158c93 100644
--- a/src/u32/uvec4.rs
+++ b/src/u32/uvec4.rs
@@ -215,6 +215,24 @@ impl UVec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u32 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u32 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u64/u64vec2.rs b/src/u64/u64vec2.rs
index 0548370..56bb4d4 100644
--- a/src/u64/u64vec2.rs
+++ b/src/u64/u64vec2.rs
@@ -188,6 +188,24 @@ impl U64Vec2 {
         self.x.max(self.y)
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u64 {
+        self.x + self.y
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u64 {
+        self.x * self.y
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u64/u64vec3.rs b/src/u64/u64vec3.rs
index 57baf75..72ba129 100644
--- a/src/u64/u64vec3.rs
+++ b/src/u64/u64vec3.rs
@@ -228,6 +228,24 @@ impl U64Vec3 {
         self.x.max(self.y.max(self.z))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u64 {
+        self.x + self.y + self.z
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u64 {
+        self.x * self.y * self.z
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///
diff --git a/src/u64/u64vec4.rs b/src/u64/u64vec4.rs
index b1b6de4..5674314 100644
--- a/src/u64/u64vec4.rs
+++ b/src/u64/u64vec4.rs
@@ -215,6 +215,24 @@ impl U64Vec4 {
         self.x.max(self.y.max(self.z.max(self.w)))
     }
 
+    /// Returns the sum of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x + self.y + ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_sum(self) -> u64 {
+        self.x + self.y + self.z + self.w
+    }
+
+    /// Returns the product of all elements of `self`.
+    ///
+    /// In other words, this computes `self.x * self.y * ..`.
+    #[inline]
+    #[must_use]
+    pub fn element_product(self) -> u64 {
+        self.x * self.y * self.z * self.w
+    }
+
     /// Returns a vector mask containing the result of a `==` comparison for each element of
     /// `self` and `rhs`.
     ///


Test patch:
diff --git a/tests/vec2.rs b/tests/vec2.rs
index c71ed29..2ad1cd4 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -181,6 +181,12 @@ macro_rules! impl_vec2_tests {
             assert_eq!($new(1 as $t, 2 as $t), b.max(a));
         });
 
+        glam_test!(test_sum_product, {
+            let a = $new(2 as $t, 3 as $t);
+            assert_eq!(a.element_sum(), 5 as $t);
+            assert_eq!(a.element_product(), 6 as $t);
+        });
+
         glam_test!(test_clamp, {
             fn vec(x: i32, y: i32) -> $vec2 {
                 $vec2::new(x as $t, y as $t)
diff --git a/tests/vec3.rs b/tests/vec3.rs
index af1a479..3b4c2a4 100644
--- a/tests/vec3.rs
+++ b/tests/vec3.rs
@@ -220,6 +220,12 @@ macro_rules! impl_vec3_tests {
             assert_eq!(3 as $t, $new(2 as $t, 3 as $t, 1 as $t).max_element());
         });
 
+        glam_test!(test_sum_product, {
+            let a = $new(2 as $t, 3 as $t, 5 as $t);
+            assert_eq!(a.element_sum(), 10 as $t);
+            assert_eq!(a.element_product(), 30 as $t);
+        });
+
         glam_test!(test_eq, {
             let a = $new(1 as $t, 1 as $t, 1 as $t);
             let b = $new(1 as $t, 2 as $t, 3 as $t);
diff --git a/tests/vec4.rs b/tests/vec4.rs
index e0dcd9e..05fd72f 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -295,6 +295,12 @@ macro_rules! impl_vec4_tests {
             );
         });
 
+        glam_test!(test_sum_product, {
+            let a = $new(2 as $t, 3 as $t, 5 as $t, 7 as $t);
+            assert_eq!(a.element_sum(), 17 as $t);
+            assert_eq!(a.element_product(), 210 as $t);
+        });
+
         glam_test!(test_eq, {
             let a = $new(1 as $t, 1 as $t, 1 as $t, 1 as $t);
             let b = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t);