1
2
3
4
5
6
7 package simd_test
8
9 import (
10 "fmt"
11 "math"
12 "reflect"
13 "simd/archsimd/internal/test_helpers"
14 "testing"
15 "unsafe"
16 )
17
18 type signed interface {
19 ~int | ~int8 | ~int16 | ~int32 | ~int64
20 }
21
22 type unsigned interface {
23 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
24 }
25
26 type integer interface {
27 ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
28 }
29
30 type float interface {
31 ~float32 | ~float64
32 }
33
34 type number interface {
35 ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
36 }
37
38 func checkSlices[T number](t *testing.T, got, want []T) bool {
39 t.Helper()
40 return test_helpers.CheckSlicesLogInput[T](t, got, want, 0.0, nil)
41 }
42
43 func checkSlicesLogInput[T number](t *testing.T, got, want []T, flakiness float64, logInput func()) bool {
44 t.Helper()
45 return test_helpers.CheckSlicesLogInput[T](t, got, want, flakiness, logInput)
46 }
47
48
49
50
51 func sliceOf[T number](n int) []T {
52 s := make([]T, n)
53 for i := 0; i < n; i++ {
54 s[i] = T(i + 1)
55 }
56 return s
57 }
58
59 func toVect[T signed](b []bool) []T {
60 s := make([]T, len(b))
61 for i := range b {
62 if b[i] {
63 s[i] = -1
64 }
65 }
66 return s
67 }
68
69
70 func s64[T number](s []T) []int64 {
71 var is any = s
72 if r, ok := is.([]int64); ok {
73 return r
74 }
75 r := make([]int64, len(s))
76 for i := range s {
77 r[i] = int64(s[i])
78 }
79 return r
80 }
81
82
83
84
85
86 func Do[T number](t *testing.T, n int, body func(a, c []T)) {
87 a := sliceOf[T](n)
88 b := sliceOf[T](n)
89
90 for i := n; i >= 0; i-- {
91 c := make([]T, n, n)
92 body(a[:i], c)
93 checkSlices(t, c, b)
94 if i > 0 {
95 b[i-1] = T(0)
96 }
97 }
98 }
99
100
101
102 func map3[T, U any](elem func(x, y, z T) U) func(x, y, z []T) []U {
103 return func(x, y, z []T) []U {
104 s := make([]U, len(x))
105 for i := range s {
106 s[i] = elem(x[i], y[i], z[i])
107 }
108 return s
109 }
110 }
111
112
113
114 func map2[T, U any](elem func(x, y T) U) func(x, y []T) []U {
115 return func(x, y []T) []U {
116 s := make([]U, len(x))
117 for i := range s {
118 s[i] = elem(x[i], y[i])
119 }
120 return s
121 }
122 }
123
124
125
126 func map1[T, U any](elem func(x T) U) func(x []T) []U {
127 return func(x []T) []U {
128 s := make([]U, len(x))
129 for i := range s {
130 s[i] = elem(x[i])
131 }
132 return s
133 }
134 }
135
136
137
138
139 func map1n[T, U any](elem func(x T) U, n int) func(x []T) []U {
140 return func(x []T) []U {
141 s := make([]U, n)
142 for i := range min(len(x), n) {
143 s[i] = elem(x[i])
144 }
145 return s
146 }
147 }
148
149
150
151
152 func mapCompare[T number](elem func(x, y T) bool) func(x, y []T) []int64 {
153 return func(x, y []T) []int64 {
154 s := make([]int64, len(x))
155 for i := range s {
156 if elem(x[i], y[i]) {
157 s[i] = -1
158 }
159 }
160 return s
161 }
162 }
163
164
165
166 func nOf[T any](n int, s []T) []T {
167 if len(s) >= n {
168 return s
169 }
170 r := make([]T, n)
171 for i := range r {
172 r[i] = s[i%len(s)]
173 }
174 return r
175 }
176
177
178
179 func grouped2[T any](fg func(xg, yg []T) (zg []T)) func(x, y []T) []T {
180 return func(x, y []T) []T {
181 z := make([]T, len(x))
182 groupElems := 128 / int(8*unsafe.Sizeof(*new(T)))
183 for i := 0; i < len(z); i += groupElems {
184 zg := fg(x[i:][:groupElems], y[i:][:groupElems])
185 if len(zg) != groupElems {
186 panic(fmt.Sprintf("got %d elements, want %d", len(zg), groupElems))
187 }
188 copy(z[i:], zg)
189 }
190 return z
191 }
192 }
193
194 const (
195 PN22 = 1.0 / 1024 / 1024 / 4
196 PN24 = 1.0 / 1024 / 1024 / 16
197 PN53 = PN24 * PN24 / 32
198 F0 = float32(1.0 + 513*PN22/2)
199 F1 = float32(1.0 + 511*PN22*8)
200 Aeasy = float32(2046 * PN53)
201 Ahard = float32(2047 * PN53)
202 )
203
204 var zero = 0.0
205 var nzero = -zero
206 var inf = 1 / zero
207 var ninf = -1 / zero
208 var nan = math.NaN()
209 var snan32 = math.Float32frombits(0x7f800001)
210 var snan64 = math.Float64frombits(0x7ff0000000000001)
211
212
213 const N = 144
214
215 var float32s = nOf(N, []float32{float32(inf), float32(ninf), 1, float32(nan), snan32, -float32(nan), -snan32, float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1.0 / zero), float32(-1.0 / zero), 1.0 / 2, 1.0 / 4, 1.0 / 8, 1.0 / 1000, 1.0 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
216 var float64s = nOf(N, []float64{inf, ninf, nan, snan64, -nan, -snan64, zero, -zero, 1 / zero, -1 / zero, 0.0001, 0.0000001, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1.0 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
217
218 var int32s = nOf(N, []int32{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
219 var uint32s = nOf(N, []uint32{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint32(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint32(0x55555), ^uint32(0x77777), ^uint32(0xccccc)})
220
221 var int64s = nOf(N, []int64{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
222 var uint64s = nOf(N, []uint64{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint64(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint64(0x55555), ^uint64(0x77777), ^uint64(0xccccc)})
223
224 var int16s = nOf(N, []int16{1, -1, 0, 2, 4, 8, 1024, 3, 5, 7, 11, 13, 3000, 5555, 7777, 11111, 32767, 32766, -32767, -32768, -11111, -4, -8, -16, -32, -64})
225 var uint16s = nOf(N, []uint16{1, 0, 2, 4, 8, 1024, 3, 5, 7, 11, 13, 3000, 5555, 7777, 11111, 32767, 32766, 32768, 65535, 45678, 56789})
226
227 var int8s = nOf(N, []int8{0, 1, 2, 3, 5, 7, 11, 22, 33, 55, 77, 121, 127, -1, -2, -3, -5, -7, -11, -77, -121, -127, -128, 4, 8, 16, 32, 64, -4, -8, -16, -32, -64})
228 var uint8s = nOf(N, []uint8{0, 1, 2, 3, 5, 7, 11, 22, 33, 55, 77, 121, 127, 128, 255, 233, 211, 177, 144, 4, 8, 16, 32, 64})
229
230 var bools = nOf(N, []bool{
231 true, false, true, true, false, false, true, true, true, false, false, false, true, true, true, true, false, false, false, false})
232
233 func forSlice[T number](t *testing.T, s []T, n int, f func(a []T) bool) {
234 t.Helper()
235 for i := 0; i < len(s)-n; i++ {
236 if !f(s[i : i+n]) {
237 return
238 }
239 }
240 }
241
242 func forSlicePair[T number](t *testing.T, s []T, n int, f func(a, b []T) bool) {
243 t.Helper()
244 for i := 0; i < len(s)-n; i++ {
245 for j := 0; j < len(s)-n; j++ {
246 if !f(s[i:i+n], s[j:j+n]) {
247 return
248 }
249 }
250 }
251 }
252
253 func forSliceTriple[T number](t *testing.T, s []T, n int, f func(a, b, c []T) bool) {
254 t.Helper()
255 for i := 0; i < len(s)-n; i += 3 {
256 for j := 0; j < len(s)-n; j += 3 {
257 for k := 0; k < len(s)-n; k += 3 {
258 if !f(s[i:i+n], s[j:j+n], s[k:k+n]) {
259 return
260 }
261 }
262 }
263 }
264 }
265
266 func forSliceMixed[D, S number](t *testing.T, d []D, s []S, n int, f func(a []D, b []S) bool) {
267 t.Helper()
268 for i := 0; i < len(d)-n; i++ {
269 for j := 0; j < len(s)-n; j++ {
270 if !f(d[i:i+n], s[j:j+n]) {
271 return
272 }
273 }
274 }
275 }
276
277 func forSlicePairMasked[T number](t *testing.T, s []T, n int, f func(a, b []T, m []bool) bool) {
278 t.Helper()
279 m := bools
280
281 for i := 0; i < len(s)-n; i += 3 {
282 for j := 0; j < len(s)-n; j += 3 {
283 for k := 0; k < len(m)-n; k += 3 {
284 if !f(s[i:i+n], s[j:j+n], m[k:k+n]) {
285 return
286 }
287 }
288 }
289 }
290 }
291
292
293 func hideConst[T number](x T) T {
294 return x
295 }
296
297 func testStorePartRV[T number, V any](t *testing.T, name string, n int, val V, storePart func(v V, s []T) int) {
298 t.Helper()
299
300 {
301 s := make([]T, 0)
302 rv := storePart(val, s)
303 if rv != 0 {
304 t.Errorf("%s: StorePart on empty slice returned %d, expected 0", name, rv)
305 }
306 }
307
308
309 {
310 s := make([]T, 1)
311 rv := storePart(val, s)
312 if rv != 1 {
313 t.Errorf("%s: StorePart on 1-element slice returned %d, expected 1", name, rv)
314 }
315 }
316
317
318 {
319 s := make([]T, n+5)
320 rv := storePart(val, s)
321 if rv != n {
322 t.Errorf("%s: StorePart on %d-element slice (longer than %d) returned %d, expected %d", name, n+5, n, rv, n)
323 }
324 }
325 }
326
327 type HasLenAndStorePart[T number] interface {
328 StorePart(s []T) int
329 Len() int
330 }
331
332 func testStorePartReturnValue[T number, V HasLenAndStorePart[T]](t *testing.T) {
333 t.Helper()
334 var v V
335 n := v.Len()
336 name := reflect.TypeOf(v).Name()
337
338 {
339 s := make([]T, 0)
340 rv := v.StorePart(s)
341 if rv != 0 {
342 t.Errorf("%s: StorePart on empty slice returned %d, expected 0", name, rv)
343 }
344 }
345
346
347 {
348 s := make([]T, 1)
349 rv := v.StorePart(s)
350 if rv != 1 {
351 t.Errorf("%s: StorePart on 1-element slice returned %d, expected 1", name, rv)
352 }
353 }
354
355
356 {
357 s := make([]T, n+5)
358 rv := v.StorePart(s)
359 if rv != n {
360 t.Errorf("%s: StorePart on %d-element slice (longer than %d) returned %d, expected %d", name, n+5, n, rv, n)
361 }
362 }
363 t.Logf("tested %s", name)
364 }
365
View as plain text