Repository: bitshifter/glam-rs
Pull request #341 (2022-09-29 01:12:10)

Add dot_v and tests
Addresses #338 


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 1240ad5..eaf4bc7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -50,7 +50,7 @@ bytemuck = { version = "1.5", optional = true, default-features = false }
 mint = { version = "0.5.8", optional = true, default-features = false }
 num-traits = { version = "0.2.14", optional = true, default-features = false }
 rand = { version = "0.8", optional = true, default-features = false }
-serde = { version = "1.0", optional = true, features = ["derive"] }
+serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
 rkyv = { version = "0.7", optional = true }
 bytecheck = { version = "0.6", optional = true, default-features = false}
 
diff --git a/codegen/templates/vec.rs.tera b/codegen/templates/vec.rs.tera
index a8ca85b..e8128ce 100644
--- a/codegen/templates/vec.rs.tera
+++ b/codegen/templates/vec.rs.tera
@@ -430,6 +430,20 @@ impl {{ self_t }} {
         {% endif %}
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs` 
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        {% if is_sse2 %}
+            Self(unsafe { dot{{ dim }}_into_m128(self.0, rhs.0) })
+        {% elif is_wasm32 %}
+            Self(unsafe { dot{{ dim }}_into_v128(self.0, rhs.0) })
+        {% elif is_coresimd %}
+            Self(unsafe { dot{{ dim }}_into_f32x4(self.0, rhs.0) })
+        {% else %}
+            Self::splat(self.dot(rhs))
+        {% endif %}
+    }
+
 {% if dim == 3 %}
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
diff --git a/src/f32/coresimd/vec3a.rs b/src/f32/coresimd/vec3a.rs
index 5215abb..966217e 100644
--- a/src/f32/coresimd/vec3a.rs
+++ b/src/f32/coresimd/vec3a.rs
@@ -148,6 +148,12 @@ impl Vec3A {
         dot3(self.0, rhs.0)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self(unsafe { dot3_into_f32x4(self.0, rhs.0) })
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/f32/coresimd/vec4.rs b/src/f32/coresimd/vec4.rs
index 03e5abe..38b2d4f 100644
--- a/src/f32/coresimd/vec4.rs
+++ b/src/f32/coresimd/vec4.rs
@@ -141,6 +141,12 @@ impl Vec4 {
         dot4(self.0, rhs.0)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self(unsafe { dot4_into_f32x4(self.0, rhs.0) })
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/f32/scalar/vec3a.rs b/src/f32/scalar/vec3a.rs
index 71b9ebd..00c1e8f 100644
--- a/src/f32/scalar/vec3a.rs
+++ b/src/f32/scalar/vec3a.rs
@@ -159,6 +159,12 @@ impl Vec3A {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/f32/scalar/vec4.rs b/src/f32/scalar/vec4.rs
index 7facd6c..db0a60a 100644
--- a/src/f32/scalar/vec4.rs
+++ b/src/f32/scalar/vec4.rs
@@ -162,6 +162,12 @@ impl Vec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/f32/sse2/vec3a.rs b/src/f32/sse2/vec3a.rs
index 1ead0df..734d3ea 100644
--- a/src/f32/sse2/vec3a.rs
+++ b/src/f32/sse2/vec3a.rs
@@ -160,6 +160,12 @@ impl Vec3A {
         unsafe { dot3(self.0, rhs.0) }
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self(unsafe { dot3_into_m128(self.0, rhs.0) })
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/f32/sse2/vec4.rs b/src/f32/sse2/vec4.rs
index ab645ca..e318cad 100644
--- a/src/f32/sse2/vec4.rs
+++ b/src/f32/sse2/vec4.rs
@@ -153,6 +153,12 @@ impl Vec4 {
         unsafe { dot4(self.0, rhs.0) }
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self(unsafe { dot4_into_m128(self.0, rhs.0) })
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/f32/vec2.rs b/src/f32/vec2.rs
index 7c275eb..ab9ec46 100644
--- a/src/f32/vec2.rs
+++ b/src/f32/vec2.rs
@@ -125,6 +125,12 @@ impl Vec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/f32/vec3.rs b/src/f32/vec3.rs
index df0ae09..3f745c0 100644
--- a/src/f32/vec3.rs
+++ b/src/f32/vec3.rs
@@ -153,6 +153,12 @@ impl Vec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/f32/wasm32/vec3a.rs b/src/f32/wasm32/vec3a.rs
index cec3c79..678b781 100644
--- a/src/f32/wasm32/vec3a.rs
+++ b/src/f32/wasm32/vec3a.rs
@@ -152,6 +152,12 @@ impl Vec3A {
         dot3(self.0, rhs.0)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self(unsafe { dot3_into_v128(self.0, rhs.0) })
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/f32/wasm32/vec4.rs b/src/f32/wasm32/vec4.rs
index bc79cc8..55386ad 100644
--- a/src/f32/wasm32/vec4.rs
+++ b/src/f32/wasm32/vec4.rs
@@ -145,6 +145,12 @@ impl Vec4 {
         dot4(self.0, rhs.0)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self(unsafe { dot4_into_v128(self.0, rhs.0) })
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/f64/dvec2.rs b/src/f64/dvec2.rs
index 205dca2..3fdfc44 100644
--- a/src/f64/dvec2.rs
+++ b/src/f64/dvec2.rs
@@ -125,6 +125,12 @@ impl DVec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/f64/dvec3.rs b/src/f64/dvec3.rs
index 2251a28..d7bc1a2 100644
--- a/src/f64/dvec3.rs
+++ b/src/f64/dvec3.rs
@@ -153,6 +153,12 @@ impl DVec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/f64/dvec4.rs b/src/f64/dvec4.rs
index 132b8a8..21a60ce 100644
--- a/src/f64/dvec4.rs
+++ b/src/f64/dvec4.rs
@@ -154,6 +154,12 @@ impl DVec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/i32/ivec2.rs b/src/i32/ivec2.rs
index 4ad537b..fc21896 100644
--- a/src/i32/ivec2.rs
+++ b/src/i32/ivec2.rs
@@ -119,6 +119,12 @@ impl IVec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/i32/ivec3.rs b/src/i32/ivec3.rs
index 0019b51..1d14108 100644
--- a/src/i32/ivec3.rs
+++ b/src/i32/ivec3.rs
@@ -147,6 +147,12 @@ impl IVec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/i32/ivec4.rs b/src/i32/ivec4.rs
index 53e90ac..449f1b9 100644
--- a/src/i32/ivec4.rs
+++ b/src/i32/ivec4.rs
@@ -148,6 +148,12 @@ impl IVec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/u32/uvec2.rs b/src/u32/uvec2.rs
index b422600..ac3d7df 100644
--- a/src/u32/uvec2.rs
+++ b/src/u32/uvec2.rs
@@ -110,6 +110,12 @@ impl UVec2 {
         (self.x * rhs.x) + (self.y * rhs.y)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.
diff --git a/src/u32/uvec3.rs b/src/u32/uvec3.rs
index 18a5bbd..192886e 100644
--- a/src/u32/uvec3.rs
+++ b/src/u32/uvec3.rs
@@ -135,6 +135,12 @@ impl UVec3 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Computes the cross product of `self` and `rhs`.
     #[inline]
     pub fn cross(self, rhs: Self) -> Self {
diff --git a/src/u32/uvec4.rs b/src/u32/uvec4.rs
index aa07f0c..decccf3 100644
--- a/src/u32/uvec4.rs
+++ b/src/u32/uvec4.rs
@@ -133,6 +133,12 @@ impl UVec4 {
         (self.x * rhs.x) + (self.y * rhs.y) + (self.z * rhs.z) + (self.w * rhs.w)
     }
 
+    /// Returns a vector where every component is the dot product of `self` and `rhs`
+    #[inline]
+    pub fn dot_into_vec(self, rhs: Self) -> Self {
+        Self::splat(self.dot(rhs))
+    }
+
     /// Returns a vector containing the minimum values for each element of `self` and `rhs`.
     ///
     /// In other words this computes `[self.x.min(rhs.x), self.y.min(rhs.y), ..]`.


Test patch:
diff --git a/tests/vec2.rs b/tests/vec2.rs
index f165982..2f88b77 100644
--- a/tests/vec2.rs
+++ b/tests/vec2.rs
@@ -554,6 +554,7 @@ macro_rules! impl_vec2_float_tests {
             assert_eq!(13.0, (-5.0 * x).distance(12.0 * y));
             assert_eq!(x, (2.0 * x).normalize());
             assert_eq!(1.0 * 3.0 + 2.0 * 4.0, $new(1.0, 2.0).dot($new(3.0, 4.0)));
+            assert_eq!($new(8.0, 8.0), $new(1.0, 2.0).dot_into_vec($new(4.0, 2.0)));
             assert_eq!(2.0 * 2.0 + 3.0 * 3.0, $new(2.0, 3.0).length_squared());
             assert_eq!(
                 (2.0 as $t * 2.0 + 3.0 * 3.0).sqrt(),
diff --git a/tests/vec3.rs b/tests/vec3.rs
index 80956d7..6ee71da 100644
--- a/tests/vec3.rs
+++ b/tests/vec3.rs
@@ -598,6 +598,10 @@ macro_rules! impl_vec3_float_tests {
                 1.0 * 4.0 + 2.0 * 5.0 + 3.0 * 6.0,
                 $new(1.0, 2.0, 3.0).dot($new(4.0, 5.0, 6.0))
             );
+            assert_eq!(
+                $new(14.0, 14.0, 14.0),
+                $new(0.0, 4.0, 6.0).dot_into_vec($new(3.0, 2.0, 1.0))
+            );
             assert_eq!(
                 2.0 * 2.0 + 3.0 * 3.0 + 4.0 * 4.0,
                 $new(2.0, 3.0, 4.0).length_squared()
diff --git a/tests/vec4.rs b/tests/vec4.rs
index 60b282a..0dd6264 100644
--- a/tests/vec4.rs
+++ b/tests/vec4.rs
@@ -676,6 +676,10 @@ macro_rules! impl_vec4_float_tests {
                 1.0 * 5.0 + 2.0 * 6.0 + 3.0 * 7.0 + 4.0 * 8.0,
                 $new(1.0, 2.0, 3.0, 4.0).dot($new(5.0, 6.0, 7.0, 8.0))
             );
+            assert_eq!(
+                $new(28.0, 28.0, 28.0, 28.0),
+                $new(0.0, 5.0, 3.0, 6.0).dot_into_vec($new(7.0, 2.0, 4.0, 1.0))
+            );
             assert_eq!(
                 2.0 * 2.0 + 3.0 * 3.0 + 4.0 * 4.0 + 5.0 * 5.0,
                 $new(2.0, 3.0, 4.0, 5.0).length_squared()