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