1
2
3
4
5
6
7 package test_helpers
8
9 import (
10 "math"
11 "math/bits"
12 "testing"
13 "unsafe"
14 )
15
16 func ReduceSum[S number](s []S) S {
17 var x S
18 for _, v := range s {
19 x += v
20 }
21 return x
22 }
23
24
25
26
27 func Round[S float](x S) S { return S(math.RoundToEven(float64(x))) }
28 func Ceil[S float](x S) S { return S(math.Ceil(float64(x))) }
29 func Floor[S float](x S) S { return S(math.Floor(float64(x))) }
30 func Trunc[S float](x S) S { return S(math.Trunc(float64(x))) }
31
32 func Neg[S number](x S) S {
33 return -x
34 }
35
36 func Abs[S, S2 number](x S) S2 {
37 if x == 0 {
38 return 0
39 }
40 if x < 0 {
41 return S2(-x)
42 }
43 return S2(x)
44 }
45
46 func Add[S number](x, y S) S {
47 return x + y
48 }
49
50 func Sub[S number](x, y S) S {
51 return x - y
52 }
53
54 func Mul[S number](x, y S) S {
55 return x * y
56 }
57
58 func Div[S float](x, y S) S {
59 return x / y
60 }
61
62 func And[S integer](x, y S) S {
63 return x & y
64 }
65
66 func Or[S integer](x, y S) S {
67 return x | y
68 }
69
70 func Xor[S integer](x, y S) S {
71 return x ^ y
72 }
73
74 func AndNot[S integer](x, y S) S {
75 return x &^ y
76 }
77
78 func Xnor[S integer](x, y S) S {
79 return ^(x ^ y)
80 }
81
82 func Not[S integer](x S) S {
83 return ^x
84 }
85
86 func Max[S number](x, y S) S {
87 return max(x, y)
88 }
89
90 func Min[S number](x, y S) S {
91 return min(x, y)
92 }
93
94 func ShiftLeft[S integer](x S, s uint64) S {
95 return x << s
96 }
97
98 func ShiftRight[S integer](x S, s uint64) S {
99 return x >> s
100 }
101
102 func Equal[S number](x, y S) bool {
103 return x == y
104 }
105
106 func NotEqual[S number](x, y S) bool {
107 return x != y
108 }
109
110 func Less[S number](x, y S) bool {
111 return x < y
112 }
113
114 func LessEqual[S number](x, y S) bool {
115 return x <= y
116 }
117
118 func Greater[S number](x, y S) bool {
119 return x > y
120 }
121
122 func GreaterEqual[S number](x, y S) bool {
123 return x >= y
124 }
125
126 func RotateLeft[S integer](x S, dist uint64) S {
127 size := uint64(unsafe.Sizeof(x)) * 8
128 mask := (uint64(1) << size) - 1
129 dist = dist & (size - 1)
130 if dist == 0 {
131 return x
132 }
133 return (x << dist) | S((mask&uint64(x))>>(size-dist))
134 }
135
136 func RotateRight[S integer](x S, dist uint64) S {
137 size := uint64(unsafe.Sizeof(x)) * 8
138 mask := (uint64(1) << size) - 1
139 dist = dist & (size - 1)
140 if dist == 0 {
141 return x
142 }
143 return S((mask&uint64(x))>>dist) | (x << (size - dist))
144 }
145
146 func OnesCount[T integer](x T) T {
147 size := uint64(unsafe.Sizeof(x)) * 8
148 return T(bits.OnesCount64(uint64(x) & ((1 << size) - 1)))
149 }
150
151 func TrailingZeros[T integer](x T) T {
152 size := int(unsafe.Sizeof(x)) * 8
153 tz := bits.TrailingZeros64(uint64(x))
154 if tz > size {
155 tz = size
156 }
157 return T(tz)
158 }
159
160
161 type Vec[E number] interface {
162 Store(s []E)
163 Len() int
164 }
165
166
167 type Mask interface {
168 String() string
169 }
170
171
172 type IVec[E signed, M Mask] interface {
173 Store(s []E)
174 Len() int
175 ToMask() M
176 }
177
178
179
180
181
182
183
184
185 func TestV2S[S number, V Vec[S]](t *testing.T, slice []S, load func([]S) V, f func(_ V) S, want func([]S) S) {
186 var v V
187 n := v.Len()
188 t.Helper()
189 forSlice(t, slice, n, func(x []S) bool {
190 t.Helper()
191 a := load(x)
192 g := f(a)
193 w := want(x)
194 return CheckScalarsLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v", x) })
195 })
196 }
197
198
199 func TestV2V[S number, V Vec[S]](t *testing.T, slice []S, load func([]S) V, f func(_ V) V, want func([]S) []S) {
200 var v V
201 n := v.Len()
202 t.Helper()
203 forSlice(t, slice, n, func(x []S) bool {
204 t.Helper()
205 a := load(x)
206 g := make([]S, n)
207 f(a).Store(g)
208 w := want(x)
209 return CheckSlicesLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v", x) })
210 })
211 }
212
213
214
215
216
217
218
219 func TestV2Ve[S, S2 number, V Vec[S], V2 Vec[S2]](t *testing.T, slice []S, load func([]S) V, f func(_ V) V2, want func(S) S2) {
220 var v V
221 var v2 V2
222 n, n2 := v.Len(), v2.Len()
223 t.Helper()
224 forSlice(t, slice, n, func(x []S) bool {
225 t.Helper()
226 a := load(x)
227 g := make([]S2, n2)
228 f(a).Store(g)
229 w := ImpliedDo(n2, func(i int) S2 {
230 if i < n {
231 return want(x[i])
232 }
233 return 0
234 })
235 return CheckSlicesLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v", x) })
236 })
237 }
238
239
240 func TestVR2Ve[S number, V Vec[S]](t *testing.T, slice []S, shifts []uint64, load func([]S) V, f func(V, uint64) V, want func(S, uint64) S) {
241 var v V
242 n := v.Len()
243 t.Helper()
244 for _, shift := range shifts {
245 forSlice(t, slice, n, func(x []S) bool {
246 t.Helper()
247 a := load(x)
248 g := make([]S, n)
249 f(a, shift).Store(g)
250 w := ImpliedDo(n, func(i int) S { return want(x[i], shift) })
251 return CheckSlicesLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v, dist=%v", x, shift) })
252 })
253 }
254 }
255
256
257 func TestVV2V[S number, V Vec[S]](t *testing.T, slice []S, load func([]S) V, f func(_, _ V) V, want func(_, _ []S) []S) {
258 var v V
259 n := v.Len()
260 t.Helper()
261 forSlicePair(t, slice, n, func(x, y []S) bool {
262 t.Helper()
263 a := load(x)
264 b := load(y)
265 g := make([]S, n)
266 f(a, b).Store(g)
267 w := want(x, y)
268 return CheckSlicesLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) })
269 })
270 }
271
272
273 func TestVV2Ve[S number, V Vec[S]](t *testing.T, slice []S, load func([]S) V, f func(_, _ V) V, want func(_, _ S) S) {
274 var v V
275 n := v.Len()
276 t.Helper()
277 forSlicePair(t, slice, n, func(x, y []S) bool {
278 t.Helper()
279 a := load(x)
280 b := load(y)
281 g := make([]S, n)
282 f(a, b).Store(g)
283 w := ImpliedDo(n, func(i int) S { return want(x[i], y[i]) })
284 return CheckSlicesLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) })
285 })
286 }
287
288
289 func TestVV2Me[S number, V Vec[S], M Mask](t *testing.T, slice []S, load func([]S) V, f func(_, _ V) M, want func(_, _ S) bool) {
290 var v V
291 n := v.Len()
292 t.Helper()
293 forSlicePair(t, slice, n, func(x, y []S) bool {
294 t.Helper()
295 a := load(x)
296 b := load(y)
297 g := f(a, b).String()
298 w := ImpliedBools(n, func(i int) bool { return want(x[i], y[i]) })
299 return CheckStringsLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) })
300 })
301 }
302
303
304 func TestM2Me[S signed, M Mask, V IVec[S, M]](t *testing.T, load func([]S) V, f func(_ M) M, want func(_ S) S) {
305 var v V
306 n := v.Len()
307 t.Helper()
308 b2s := func(b bool) S {
309 if b {
310 return -1
311 }
312 return 0
313 }
314
315 bload := func(s []bool) V {
316 sl := make([]S, n)
317 for i := range sl {
318 sl[i] = b2s(s[i])
319 }
320 return load(sl)
321 }
322 forBoolSlice(t, Bools(), n, func(x []bool) bool {
323 t.Helper()
324 a := bload(x)
325 g := f(a.ToMask()).String()
326 w := ImpliedBools(n, func(i int) bool { return 0 != want(b2s(x[i])) })
327 return CheckStringsLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v", x) })
328 })
329 }
330
331
332 func TestMM2Me[S signed, M Mask, V IVec[S, M]](t *testing.T, load func([]S) V, f func(_, _ M) M, want func(_, _ S) S) {
333 var v V
334 n := v.Len()
335 t.Helper()
336 b2s := func(b bool) S {
337 if b {
338 return -1
339 }
340 return 0
341 }
342
343 bload := func(s []bool) V {
344 sl := make([]S, n)
345 for i := range sl {
346 sl[i] = b2s(s[i])
347 }
348 return load(sl)
349 }
350 forBoolSlicePair(t, Bools(), n, func(x, y []bool) bool {
351 t.Helper()
352 a := bload(x)
353 b := bload(y)
354 g := f(a.ToMask(), b.ToMask()).String()
355 w := ImpliedBools(n, func(i int) bool { return 0 != want(b2s(x[i]), b2s(y[i])) })
356 return CheckStringsLogInput(t, g, w, 0.000001, func() { t.Helper(); t.Logf("x=%v, y=%v", x, y) })
357 })
358 }
359
View as plain text