Source file
src/simd/simd_test.go
1
2
3
4
5
6
7 package simd_test
8
9 import (
10 "simd"
11 "slices"
12 "testing"
13 )
14
15 type signed interface {
16 ~int | ~int8 | ~int16 | ~int32 | ~int64
17 }
18
19 type unsigned interface {
20 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
21 }
22
23 type integer interface {
24 ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
25 }
26
27 type float interface {
28 ~float32 | ~float64
29 }
30
31 type number interface {
32 ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
33 }
34
35 func TestInt8s(t *testing.T) {
36
37 in1 := []int8{
38 1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16,
39 17, -18, 19, -20, 21, -22, 23, -24, 25, -26, 27, -28, 29, -30, 31, -32,
40 33, -34, 35, -36, 37, -38, 39, -40, 41, -42, 43, -44, 45, -46, 47, -48,
41 49, -50, 51, -52, 53, -54, 55, -56, 57, -58, 59, -60, 61, -62, 63, -64,
42 }
43 in2 := make([]int8, 64)
44 for i := range in2 {
45 in2[i] = 2
46 }
47
48 x := simd.LoadInt8s(in1)
49 y := simd.LoadInt8s(in2)
50
51 if x.Len() <= 0 {
52 t.Errorf("Int8s.Len() returned <= 0")
53 }
54
55 sum := x.Add(y)
56 diff := x.Sub(y)
57 neg := x.Neg()
58 abs := x.Abs()
59
60 buf := make([]int8, x.Len())
61 sum.Store(buf)
62 for i := 0; i < x.Len() && i < len(in1); i++ {
63 expected := in1[i] + in2[i]
64 if buf[i] != expected {
65 t.Errorf("Add at %d: got %d, want %d", i, buf[i], expected)
66 }
67 }
68
69 diff.Store(buf)
70 for i := 0; i < x.Len() && i < len(in1); i++ {
71 expected := in1[i] - in2[i]
72 if buf[i] != expected {
73 t.Errorf("Sub at %d: got %d, want %d", i, buf[i], expected)
74 }
75 }
76
77 neg.Store(buf)
78 for i := 0; i < x.Len() && i < len(in1); i++ {
79 expected := -in1[i]
80 if buf[i] != expected {
81 t.Errorf("Neg at %d: got %d, want %d", i, buf[i], expected)
82 }
83 }
84
85 abs.Store(buf)
86 for i := 0; i < x.Len() && i < len(in1); i++ {
87 expected := in1[i]
88 if expected < 0 {
89 expected = -expected
90 }
91 if buf[i] != expected {
92 t.Errorf("Abs at %d: got %d, want %d", i, buf[i], expected)
93 }
94 }
95 }
96
97 func TestInt16s(t *testing.T) {
98
99 in1 := make([]int16, 32)
100 in2 := make([]int16, 32)
101 for i := range in1 {
102 in1[i] = int16((i + 1) * 100)
103 if i%2 != 0 {
104 in1[i] = -in1[i]
105 }
106 in2[i] = 10
107 }
108
109 x := simd.LoadInt16s(in1)
110 y := simd.LoadInt16s(in2)
111
112 sum := x.Add(y)
113 buf := make([]int16, x.Len())
114 sum.Store(buf)
115
116 for i := 0; i < x.Len() && i < len(in1); i++ {
117 expected := in1[i] + in2[i]
118 if buf[i] != expected {
119 t.Errorf("Int16s Add at %d: got %d, want %d", i, buf[i], expected)
120 }
121 }
122
123
124 rotLeft := x.RotateAllLeft(3)
125 rotLeft.Store(buf)
126 for i := 0; i < x.Len() && i < len(in1); i++ {
127 val := uint16(in1[i])
128 expected := int16((val << 3) | (val >> 13))
129 if buf[i] != expected {
130 t.Errorf("Int16s RotateAllLeft at %d: got %d, want %d", i, buf[i], expected)
131 }
132 }
133
134
135 rotRight := x.RotateAllRight(19)
136 rotRight.Store(buf)
137 for i := 0; i < x.Len() && i < len(in1); i++ {
138 val := uint16(in1[i])
139 expected := int16((val >> 3) | (val << 13))
140 if buf[i] != expected {
141 t.Errorf("Int16s RotateAllRight(19) at %d: got %d, want %d", i, buf[i], expected)
142 }
143 }
144 }
145
146 func TestInt32s(t *testing.T) {
147
148 in1 := make([]int32, 16)
149 in2 := make([]int32, 16)
150 for i := range in1 {
151 in1[i] = int32((i + 1) * 1000)
152 if i%2 != 0 {
153 in1[i] = -in1[i]
154 }
155 in2[i] = 100
156 }
157
158 x := simd.LoadInt32s(in1)
159 y := simd.LoadInt32s(in2)
160
161 sum := x.Add(y)
162 buf := make([]int32, x.Len())
163 sum.Store(buf)
164
165 for i := 0; i < x.Len() && i < len(in1); i++ {
166 expected := in1[i] + in2[i]
167 if buf[i] != expected {
168 t.Errorf("Int32s Add at %d: got %d, want %d", i, buf[i], expected)
169 }
170 }
171
172
173 rotLeft := x.RotateAllLeft(5)
174 rotLeft.Store(buf)
175 for i := 0; i < x.Len() && i < len(in1); i++ {
176 val := uint32(in1[i])
177 expected := int32((val << 5) | (val >> 27))
178 if buf[i] != expected {
179 t.Errorf("Int32s RotateAllLeft at %d: got %d, want %d", i, buf[i], expected)
180 }
181 }
182
183
184 rotRight := x.RotateAllRight(37)
185 rotRight.Store(buf)
186 for i := 0; i < x.Len() && i < len(in1); i++ {
187 val := uint32(in1[i])
188 expected := int32((val >> 5) | (val << 27))
189 if buf[i] != expected {
190 t.Errorf("Int32s RotateAllRight(37) at %d: got %d, want %d", i, buf[i], expected)
191 }
192 }
193 }
194
195 func TestInt64s(t *testing.T) {
196
197 in1 := make([]int64, 8)
198 in2 := make([]int64, 8)
199 for i := range in1 {
200 in1[i] = int64((i + 1) * 10000)
201 if i%2 != 0 {
202 in1[i] = -in1[i]
203 }
204 in2[i] = 1000
205 }
206
207 x := simd.LoadInt64s(in1)
208 y := simd.LoadInt64s(in2)
209
210 sum := x.Add(y)
211 buf := make([]int64, x.Len())
212 sum.Store(buf)
213
214 for i := 0; i < x.Len() && i < len(in1); i++ {
215 expected := in1[i] + in2[i]
216 if buf[i] != expected {
217 t.Errorf("Int64s Add at %d: got %d, want %d", i, buf[i], expected)
218 }
219 }
220
221
222 rotLeft := x.RotateAllLeft(7)
223 rotLeft.Store(buf)
224 for i := 0; i < x.Len() && i < len(in1); i++ {
225 val := uint64(in1[i])
226 expected := int64((val << 7) | (val >> 57))
227 if buf[i] != expected {
228 t.Errorf("Int64s RotateAllLeft at %d: got %d, want %d", i, buf[i], expected)
229 }
230 }
231
232
233 rotRight := x.RotateAllRight(71)
234 rotRight.Store(buf)
235 for i := 0; i < x.Len() && i < len(in1); i++ {
236 val := uint64(in1[i])
237 expected := int64((val >> 7) | (val << 57))
238 if buf[i] != expected {
239 t.Errorf("Int64s RotateAllRight(71) at %d: got %d, want %d", i, buf[i], expected)
240 }
241 }
242 }
243
244 func TestUint8s(t *testing.T) {
245
246 in1 := make([]uint8, 64)
247 in2 := make([]uint8, 64)
248 for i := range in1 {
249 in1[i] = uint8(i + 1)
250 in2[i] = 10
251 }
252
253 x := simd.LoadUint8s(in1)
254 y := simd.LoadUint8s(in2)
255
256 avg := x.Average(y)
257 buf := make([]uint8, x.Len())
258 avg.Store(buf)
259
260 for i := 0; i < x.Len() && i < len(in1); i++ {
261 expected := uint8((int(in1[i]) + int(in2[i]) + 1) >> 1)
262 if buf[i] != expected {
263 t.Errorf("Uint8s Average at %d: got %d, want %d", i, buf[i], expected)
264 }
265 }
266 }
267
268 func TestFloat32s(t *testing.T) {
269
270 in1 := make([]float32, 16)
271 in2 := make([]float32, 16)
272 for i := range in1 {
273 val := float32(i) + 1.5
274 if i%2 != 0 {
275 val = -val
276 }
277 in1[i] = val
278 in2[i] = 0.5
279 }
280
281 x := simd.LoadFloat32s(in1)
282 y := simd.LoadFloat32s(in2)
283
284 sum := x.Add(y)
285 buf := make([]float32, x.Len())
286 sum.Store(buf)
287
288 for i := 0; i < x.Len() && i < len(in1); i++ {
289 expected := in1[i] + in2[i]
290 if buf[i] != expected {
291 t.Errorf("Float32s Add at %d: got %f, want %f", i, buf[i], expected)
292 }
293 }
294 }
295
296 func TestFloat64s(t *testing.T) {
297
298 in1 := make([]float64, 8)
299 in2 := make([]float64, 8)
300 for i := range in1 {
301 val := float64(i)*10.0 + 10.25
302 if i%2 != 0 {
303 val = -val
304 }
305 in1[i] = val
306 in2[i] = 1.0
307 }
308
309 x := simd.LoadFloat64s(in1)
310 y := simd.LoadFloat64s(in2)
311
312 mul := x.Mul(y)
313 buf := make([]float64, x.Len())
314 mul.Store(buf)
315
316 for i := 0; i < x.Len() && i < len(in1); i++ {
317 expected := in1[i] * in2[i]
318 if buf[i] != expected {
319 t.Errorf("Float64s Mul at %d: got %f, want %f", i, buf[i], expected)
320 }
321 }
322 }
323
324 func TestUint16s(t *testing.T) {
325 in1 := make([]uint16, 32)
326 for i := range in1 {
327 in1[i] = uint16((i + 1) * 100)
328 }
329
330 x := simd.LoadUint16s(in1)
331 buf := make([]uint16, x.Len())
332
333
334 rotLeft := x.RotateAllLeft(3)
335 rotLeft.Store(buf)
336 for i := 0; i < x.Len() && i < len(in1); i++ {
337 val := in1[i]
338 expected := (val << 3) | (val >> 13)
339 if buf[i] != expected {
340 t.Errorf("Uint16s RotateAllLeft at %d: got %d, want %d", i, buf[i], expected)
341 }
342 }
343
344
345 rotRight := x.RotateAllRight(19)
346 rotRight.Store(buf)
347 for i := 0; i < x.Len() && i < len(in1); i++ {
348 val := in1[i]
349 expected := (val >> 3) | (val << 13)
350 if buf[i] != expected {
351 t.Errorf("Uint16s RotateAllRight(19) at %d: got %d, want %d", i, buf[i], expected)
352 }
353 }
354 }
355
356 func TestUint32s(t *testing.T) {
357 in1 := make([]uint32, 16)
358 for i := range in1 {
359 in1[i] = uint32((i + 1) * 1000)
360 }
361
362 x := simd.LoadUint32s(in1)
363 buf := make([]uint32, x.Len())
364
365
366 rotLeft := x.RotateAllLeft(5)
367 rotLeft.Store(buf)
368 for i := 0; i < x.Len() && i < len(in1); i++ {
369 val := in1[i]
370 expected := (val << 5) | (val >> 27)
371 if buf[i] != expected {
372 t.Errorf("Uint32s RotateAllLeft at %d: got %d, want %d", i, buf[i], expected)
373 }
374 }
375
376
377 rotRight := x.RotateAllRight(37)
378 rotRight.Store(buf)
379 for i := 0; i < x.Len() && i < len(in1); i++ {
380 val := in1[i]
381 expected := (val >> 5) | (val << 27)
382 if buf[i] != expected {
383 t.Errorf("Uint32s RotateAllRight(37) at %d: got %d, want %d", i, buf[i], expected)
384 }
385 }
386 }
387
388 func TestUint64s(t *testing.T) {
389 in1 := make([]uint64, 8)
390 for i := range in1 {
391 in1[i] = uint64((i + 1) * 10000)
392 }
393
394 x := simd.LoadUint64s(in1)
395 buf := make([]uint64, x.Len())
396
397
398 rotLeft := x.RotateAllLeft(7)
399 rotLeft.Store(buf)
400 for i := 0; i < x.Len() && i < len(in1); i++ {
401 val := in1[i]
402 expected := (val << 7) | (val >> 57)
403 if buf[i] != expected {
404 t.Errorf("Uint64s RotateAllLeft at %d: got %d, want %d", i, buf[i], expected)
405 }
406 }
407
408
409 rotRight := x.RotateAllRight(71)
410 rotRight.Store(buf)
411 for i := 0; i < x.Len() && i < len(in1); i++ {
412 val := in1[i]
413 expected := (val >> 7) | (val << 57)
414 if buf[i] != expected {
415 t.Errorf("Uint64s RotateAllRight(71) at %d: got %d, want %d", i, buf[i], expected)
416 }
417 }
418 }
419
420 type HasStoreLen[E number] interface {
421 Store(s []E)
422 Len() int
423 }
424
425 func testBroadcast[E number, V HasStoreLen[E]](t *testing.T, x E, f func(e E) V) {
426 v := f(x)
427 s := make([]E, v.Len())
428 v.Store(s)
429 for _, e := range s {
430 if e != x {
431 t.Errorf("Expected %v, saw %v", x, e)
432 }
433 }
434 }
435
436 func TestBroadcast(t *testing.T) {
437 testBroadcast(t, int8(-2), simd.BroadcastInt8s)
438 testBroadcast(t, int16(-2), simd.BroadcastInt16s)
439 testBroadcast(t, int32(-2), simd.BroadcastInt32s)
440 testBroadcast(t, int64(-2), simd.BroadcastInt64s)
441
442 testBroadcast(t, uint8(99), simd.BroadcastUint8s)
443 testBroadcast(t, uint16(9999), simd.BroadcastUint16s)
444 testBroadcast(t, uint32(99991111), simd.BroadcastUint32s)
445 testBroadcast(t, uint64(112233445599887766), simd.BroadcastUint64s)
446
447 testBroadcast(t, float32(99991111), simd.BroadcastFloat32s)
448 testBroadcast(t, float64(112233445599887766), simd.BroadcastFloat64s)
449 }
450
451 func TestMaskToInt(t *testing.T) {
452 topBits := simd.BroadcastUint8s(0x80)
453 got := make([]int8, topBits.Len())
454 topBits.Equal(topBits).ToInt8s().Store(got)
455 want := slices.Repeat([]int8{-1}, topBits.Len())
456 if !slices.Equal(want, got) {
457 t.Errorf("Wanted %v, got %v", want, got)
458 }
459 }
460
461
462 func four() uint64 {
463 return 4
464 }
465
466 func TestShiftAllLeft(t *testing.T) {
467
468 in := []int16{
469 1, 2, 4, 8, 16, 32, 64, 128,
470 0, 0, 0, 0, 0, 0, 0, 0,
471 0, 0, 0, 0, 0, 0, 0, 0,
472 0, 0, 0, 0, 0, 0, 0, 0,
473 }
474
475 v := simd.LoadInt16s(in)
476 want := []int16{
477 1 << 4, 2 << 4, 4 << 4, 8 << 4, 16 << 4, 32 << 4, 64 << 4, 128 << 4,
478 0, 0, 0, 0, 0, 0, 0, 0,
479 0, 0, 0, 0, 0, 0, 0, 0,
480 0, 0, 0, 0, 0, 0, 0, 0,
481 }[:v.Len()]
482
483 {
484
485 res := v.ShiftAllLeft(4)
486 got := make([]int16, res.Len())
487 res.Store(got)
488 if !slices.Equal(want, got) {
489 t.Errorf("Wanted %v, got %v", want, got)
490 }
491 }
492 {
493
494 res := v.ShiftAllLeft(four())
495 got := make([]int16, res.Len())
496 res.Store(got)
497 if !slices.Equal(want, got) {
498 t.Errorf("Wanted %v, got %v", want, got)
499 }
500 }
501 }
502
View as plain text