| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- package matmul
- import (
- "math"
- "math/rand"
- "testing"
- "makarna/pkg/backend/cpu"
- )
- func TestGemvFloat32RangeMatchesScalar(t *testing.T) {
- rng := rand.New(rand.NewSource(1))
- cases := []struct {
- K int
- N int
- startN int
- endN int
- }{
- {K: 3, N: 13, startN: 0, endN: 13},
- {K: 33, N: 17, startN: 0, endN: 17},
- {K: 33, N: 17, startN: 5, endN: 13},
- {K: 32, N: 16, startN: 0, endN: 16},
- }
- for _, tc := range cases {
- a := make([]float32, tc.K)
- for i := range a {
- a[i] = rng.Float32()*2 - 1
- }
- b := make([]float32, tc.N*tc.K)
- for i := range b {
- b[i] = rng.Float32()*2 - 1
- }
- want := make([]float32, tc.N)
- for n := tc.startN; n < tc.endN; n++ {
- var sum float32
- rowOff := n * tc.K
- for k := 0; k < tc.K; k++ {
- sum += a[k] * b[rowOff+k]
- }
- want[n] = sum
- }
- // Sanity: cpu.DotFloat32 should broadly match the scalar sum.
- for n := tc.startN; n < tc.endN; n++ {
- rowOff := n * tc.K
- gotCPU := cpu.DotFloat32(a, b[rowOff:rowOff+tc.K])
- diff := math.Abs(float64(gotCPU - want[n]))
- if diff > 1e-4 {
- t.Fatalf("DotFloat32 mismatch K=%d n=%d: got=%v want=%v", tc.K, n, gotCPU, want[n])
- }
- }
- got := make([]float32, tc.N)
- gemvFloat32Range(got, a, b, tc.K, tc.startN, tc.endN)
- const tol = 1e-4
- for n := tc.startN; n < tc.endN; n++ {
- diff := math.Abs(float64(got[n] - want[n]))
- if diff > tol {
- t.Fatalf("K=%d N=%d range=[%d,%d) n=%d: got=%v want=%v diff=%g",
- tc.K, tc.N, tc.startN, tc.endN, n, got[n], want[n], diff)
- }
- }
- }
- }
|