1
2
3
4
5
6
7 package simd_test
8
9 import (
10 "math"
11 "simd/archsimd"
12 "testing"
13 )
14
15
16
17
18 func testSVEReduceSum[T float32 | float64, V any](t *testing.T, name string, n int, load func([]T) V, sum func(V) T) {
19 t.Helper()
20 xs := make([]T, n)
21 for start := -20; start <= 20; start += 7 {
22 var want T
23 for i := range xs {
24 xs[i] = T(start + 3*i)
25 want += xs[i]
26 }
27 if got := sum(load(xs)); got != want {
28 t.Errorf("%s(%v) = %v, want %v", name, xs, got, want)
29 }
30 }
31
32 inf := T(math.Inf(1))
33 for _, c := range []struct {
34 lane int
35 val T
36 isNaN bool
37 wantInf bool
38 }{
39 {0, T(math.NaN()), true, false},
40 {n - 1, T(math.NaN()), true, false},
41 {n / 2, inf, false, true},
42 } {
43 for i := range xs {
44 xs[i] = 1
45 }
46 xs[c.lane] = c.val
47 got := sum(load(xs))
48 switch {
49 case c.isNaN && got == got:
50 t.Errorf("%s with NaN in lane %d = %v, want NaN", name, c.lane, got)
51 case c.wantInf && got != inf:
52 t.Errorf("%s with +Inf in lane %d = %v, want +Inf", name, c.lane, got)
53 }
54 }
55 }
56
57 func TestReduceSumSVE(t *testing.T) {
58 if !archsimd.ARM64.SVE() {
59 t.Skip("no SVE")
60 }
61 testSVEReduceSum(t, "Float32s.ReduceSum", archsimd.Float32s{}.Len(), archsimd.LoadFloat32s, archsimd.Float32s.ReduceSum)
62 testSVEReduceSum(t, "Float64s.ReduceSum", archsimd.Float64s{}.Len(), archsimd.LoadFloat64s, archsimd.Float64s.ReduceSum)
63 }
64
65
66
67 func testSVEReduceMax[T float32 | float64, V any](t *testing.T, name string, n int, load func([]T) V, reduce func(V) T) {
68 t.Helper()
69 xs := make([]T, n)
70 for lane := range xs {
71 for i := range xs {
72 xs[i] = T(-3*i - 1)
73 }
74 xs[lane] = 5
75 if got := reduce(load(xs)); got != 5 {
76 t.Errorf("%s(%v) = %v, want 5", name, xs, got)
77 }
78 }
79
80 for i := range xs {
81 xs[i] = T(math.Inf(-1))
82 }
83 if got := reduce(load(xs)); got != T(math.Inf(-1)) {
84 t.Errorf("%s(all -Inf) = %v, want -Inf", name, got)
85 }
86
87 for _, lane := range []int{0, n / 2, n - 1} {
88 for i := range xs {
89 xs[i] = T(i)
90 }
91 xs[lane] = T(math.NaN())
92 if got := reduce(load(xs)); got == got {
93 t.Errorf("%s with NaN in lane %d = %v, want NaN", name, lane, got)
94 }
95 }
96
97 negZero := T(math.Copysign(0, -1))
98 for _, lane := range []int{0, n - 1} {
99 for i := range xs {
100 xs[i] = negZero
101 }
102 xs[lane] = 0
103 if got := reduce(load(xs)); got != 0 || math.Signbit(float64(got)) {
104 t.Errorf("%s of signed zeros with +0 in lane %d = %v, want +0", name, lane, got)
105 }
106 }
107 }
108
109 func TestReduceMaxSVE(t *testing.T) {
110 if !archsimd.ARM64.SVE() {
111 t.Skip("no SVE")
112 }
113 testSVEReduceMax(t, "Float32s.ReduceMax", archsimd.Float32s{}.Len(), archsimd.LoadFloat32s, archsimd.Float32s.ReduceMax)
114 testSVEReduceMax(t, "Float64s.ReduceMax", archsimd.Float64s{}.Len(), archsimd.LoadFloat64s, archsimd.Float64s.ReduceMax)
115 }
116
View as plain text