Skip to content

Commit cc288b6

Browse files
authored
Merge pull request #18 from theriault/dot-product
add dot product
2 parents 78780e7 + e87464f commit cc288b6

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

statistics/dot_product.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package statistics
2+
3+
import "github.com/theriault/maths"
4+
5+
// DotProduct calculates the dot product of two slices of the same type.
6+
//
7+
// If X and Y are not the same length, it will return the dot product of the smaller sized array.
8+
//
9+
// Time complexity: O(min(|X|, |Y|)) - we iterate over X and Y up to the length of the smaller array
10+
// Space complexity: O(1)
11+
//
12+
// https://en.wikipedia.org/wiki/Dot_product
13+
func DotProduct[T maths.Integer | maths.Float](X, Y []T) T {
14+
l := len(X)
15+
if len(Y) < l {
16+
l = len(Y)
17+
}
18+
sum := T(0)
19+
for i := 0; i < l; i++ {
20+
sum += X[i] * Y[i]
21+
}
22+
return sum
23+
}

statistics/dot_product_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package statistics
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func ExampleDotProduct() {
9+
X1 := []uint8{1, 2, 3}
10+
Y1 := []uint8{3, 4, 5}
11+
product1 := DotProduct(X1, Y1)
12+
fmt.Printf("The dot product of %v and %v is %v.\n", X1, Y1, product1)
13+
14+
X2 := []float64{1.1, 2.2, 3.3}
15+
Y2 := []float64{3.3, 4.4, 5.5}
16+
product2 := DotProduct(X2, Y2)
17+
fmt.Printf("The dot product of %v and %v is %v.\n", X2, Y2, product2)
18+
19+
// Output:
20+
// The dot product of [1 2 3] and [3 4 5] is 26.
21+
// The dot product of [1.1 2.2 3.3] and [3.3 4.4 5.5] is 31.46.
22+
}
23+
24+
func TestDotProduct(t *testing.T) {
25+
cases := []struct {
26+
name string
27+
X []int
28+
Y []int
29+
expected string
30+
}{
31+
{
32+
name: "test 1 - positives",
33+
X: []int{1, 2, 3},
34+
Y: []int{3, 4, 5},
35+
expected: "int 26",
36+
},
37+
{
38+
name: "test 2 - zero",
39+
X: []int{1, 2, 3},
40+
Y: []int{0, 0, 0},
41+
expected: "int 0",
42+
},
43+
{
44+
name: "test 3 - unequal lengths",
45+
X: []int{1, 2, 3},
46+
Y: []int{4, 5},
47+
expected: "int 14",
48+
},
49+
{
50+
name: "test 4 - unequal lengths",
51+
X: []int{1, 2, 3},
52+
Y: []int{3, 4, 5, 6},
53+
expected: "int 26",
54+
},
55+
{
56+
name: "test 5 - negatives",
57+
X: []int{1, -2, 3},
58+
Y: []int{3, 4, -5},
59+
expected: "int -20",
60+
},
61+
}
62+
63+
for _, c := range cases {
64+
c := c
65+
t.Run(c.name, func(t *testing.T) {
66+
t.Parallel()
67+
actual := DotProduct(c.X, c.Y)
68+
r := fmt.Sprintf("%T %v", actual, actual)
69+
if r != c.expected {
70+
t.Logf("expected %v, got %v", c.expected, r)
71+
t.FailNow()
72+
}
73+
})
74+
}
75+
}

0 commit comments

Comments
 (0)