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
View as plain text