1
2
3
4
5
6
7 package simd_test
8
9 import (
10 "fmt"
11 "simd/archsimd"
12 "strings"
13 "testing"
14 )
15
16 func TestLookupOrZero(t *testing.T) {
17
18 x := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
19 indices := []uint8{7, 6, 5, 4, 3, 2, 1, 0, 0xff, 8, 16, 9, 128, 10, 20, 11}
20 want := []uint8{8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 0, 10, 0, 11, 0, 12}
21 got := make([]uint8, len(x))
22 archsimd.LoadUint8x16(x).LookupOrZero(archsimd.LoadUint8x16(indices)).StorePart(got)
23 checkSlices(t, got, want)
24 }
25
26 func TestClMul(t *testing.T) {
27 if !archsimd.ARM64.PMULL() {
28 t.Skip("no carryless multiply")
29 }
30 var x = archsimd.LoadUint64x2([]uint64{1, 5})
31 var y = archsimd.LoadUint64x2([]uint64{3, 9})
32
33 foo := func(v archsimd.Uint64x2, s []uint64) {
34 r := make([]uint64, 2, 2)
35 v.StorePart(r)
36 checkSlices[uint64](t, r, s)
37 }
38
39 foo(x.CarrylessMultiplyEven(y), []uint64{3, 0})
40 foo(x.CarrylessMultiplyEvenOdd(y), []uint64{9, 0})
41 foo(x.CarrylessMultiplyOddEven(y), []uint64{15, 0})
42 foo(x.CarrylessMultiplyOdd(y), []uint64{45, 0})
43 foo(y.CarrylessMultiplyEven(y), []uint64{5, 0})
44 }
45
46
47 func addInt8sNoinline(a, b archsimd.Int8s) archsimd.Int8s { return a.Add(b) }
48
49
50 func blackholeSVE() {}
51
52
53
54
55 func TestAddSVEAcrossCall(t *testing.T) {
56 if !archsimd.ARM64.SVE() {
57 t.Skip("no sve")
58 }
59 var a, b, got [32]int8
60 for i := range a {
61 a[i] = int8(i)
62 b[i] = int8(2*i + 1)
63 }
64 x := archsimd.LoadInt8s(a[:])
65 addInt8sNoinline(x, archsimd.LoadInt8s(b[:])).Store(got[:])
66 for i := 0; i < x.Len(); i++ {
67 if want := a[i] + b[i]; got[i] != want {
68 t.Errorf("lane %d: got %d, want %d", i, got[i], want)
69 }
70 }
71 }
72
73
74 func greaterInt8sNoinline(a, b archsimd.Int8s) archsimd.Mask8s { return a.Greater(b) }
75
76
77
78
79
80 func TestGreaterSVEMaskRoundTrip(t *testing.T) {
81 if !archsimd.ARM64.SVE() {
82 t.Skip("no sve")
83 }
84 var a, b [32]int8
85 for i := range a {
86 a[i] = int8(i - 8)
87 b[i] = int8(2*i - 20)
88 }
89 var z archsimd.Int8s
90 m := greaterInt8sNoinline(archsimd.LoadInt8s(a[:]), archsimd.LoadInt8s(b[:]))
91 bits := make([]uint16, sveMaskUint16s)
92 m.Store(bits)
93
94 reloaded := make([]uint16, sveMaskUint16s)
95 archsimd.LoadMask8s(bits).Store(reloaded)
96
97 for i := 0; i < z.Len(); i++ {
98 want := a[i] > b[i]
99 got := bits[i/16]>>uint(i%16)&1 == 1
100 if got != want {
101 t.Errorf("lane %d: got %v, want %v (a=%d b=%d)", i, got, want, a[i], b[i])
102 }
103 if reloaded[i/16] != bits[i/16] {
104 t.Errorf("LoadMask8s round-trip mismatch at uint16 %d: %#x vs %#x", i/16, reloaded[i/16], bits[i/16])
105 }
106 }
107 }
108
109
110
111 func TestAddSVESpill(t *testing.T) {
112 if !archsimd.ARM64.SVE() {
113 t.Skip("no sve")
114 }
115 var a, b, got [32]int8
116 for i := range a {
117 a[i] = int8(i)
118 b[i] = int8(100 - i)
119 }
120 sum := archsimd.LoadInt8s(a[:]).Add(archsimd.LoadInt8s(b[:]))
121 blackholeSVE()
122 sum.Store(got[:])
123 for i := 0; i < sum.Len(); i++ {
124 if want := a[i] + b[i]; got[i] != want {
125 t.Errorf("lane %d: got %d, want %d", i, got[i], want)
126 }
127 }
128 }
129
130
131 func TestAddSaturatedSVE(t *testing.T) {
132 if !archsimd.ARM64.SVE() {
133 t.Skip("no sve")
134 }
135 var si, gi [32]int8
136 for i := range si {
137 si[i] = 100
138 }
139 vi := archsimd.LoadInt8s(si[:])
140 vi.AddSaturated(vi).Store(gi[:])
141 for i := 0; i < vi.Len(); i++ {
142 if gi[i] != 127 {
143 t.Errorf("int8 lane %d: got %d, want 127", i, gi[i])
144 }
145 }
146 var su, gu [32]uint8
147 for i := range su {
148 su[i] = 200
149 }
150 vu := archsimd.LoadUint8s(su[:])
151 vu.AddSaturated(vu).Store(gu[:])
152 for i := 0; i < vu.Len(); i++ {
153 if gu[i] != 255 {
154 t.Errorf("uint8 lane %d: got %d, want 255", i, gu[i])
155 }
156 }
157 }
158
159 func TestStringSVE(t *testing.T) {
160 if !archsimd.ARM64.SVE() {
161 t.Skip("no sve")
162 }
163 want := func(v any) string {
164 return "{" + strings.ReplaceAll(strings.Trim(fmt.Sprint(v), "[]"), " ", ",") + "}"
165 }
166
167 xs := make([]int8, archsimd.Int8s{}.Len())
168 ys := make([]int64, archsimd.Int64s{}.Len())
169 for i := range xs {
170 xs[i] = int8(i % 2)
171 }
172 for i := range ys {
173 ys[i] = int64(i % 2)
174 }
175 x := archsimd.LoadInt8s(xs)
176 y := archsimd.LoadInt64s(ys)
177 mx := x.Greater(archsimd.LoadInt8s(make([]int8, len(xs))))
178 my := y.Greater(archsimd.LoadInt64s(make([]int64, len(ys))))
179
180 if x.String() != want(xs) {
181 t.Errorf("x=%s wanted %s", x, want(xs))
182 }
183 if y.String() != want(ys) {
184 t.Errorf("y=%s wanted %s", y, want(ys))
185 }
186 if mx.String() != want(xs) {
187 t.Errorf("mx=%s wanted %s", mx, want(xs))
188 }
189 if my.String() != want(ys) {
190 t.Errorf("my=%s wanted %s", my, want(ys))
191 }
192 t.Logf("x=%s", x)
193 t.Logf("y=%s", y)
194 t.Logf("mx=%s", mx)
195 t.Logf("my=%s", my)
196 }
197
View as plain text