1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
12 type funWW
func(x
, y
, c Word
) (z1
, z0 Word
)
22 {12345, 67890, 0, 0, 80235},
23 {12345, 67890, 1, 0, 80236},
27 {_M
, _M
, 0, 1, _M
- 1},
31 func testFunWW(t
*testing
.T
, msg
string, f funWW
, a argWW
) {
32 z1
, z0
:= f(a
.x
, a
.y
, a
.c
)
33 if z1
!= a
.z1 || z0
!= a
.z0
{
34 t
.Errorf("%s%+v\n\tgot z1:z0 = %#x:%#x; want %#x:%#x", msg
, a
, z1
, z0
, a
.z1
, a
.z0
)
38 func TestFunWW(t
*testing
.T
) {
39 for _
, a
:= range sumWW
{
41 testFunWW(t
, "addWW_g", addWW_g
, arg
)
43 arg
= argWW
{a
.y
, a
.x
, a
.c
, a
.z1
, a
.z0
}
44 testFunWW(t
, "addWW_g symmetric", addWW_g
, arg
)
46 arg
= argWW
{a
.z0
, a
.x
, a
.c
, a
.z1
, a
.y
}
47 testFunWW(t
, "subWW_g", subWW_g
, arg
)
49 arg
= argWW
{a
.z0
, a
.y
, a
.c
, a
.z1
, a
.x
}
50 testFunWW(t
, "subWW_g symmetric", subWW_g
, arg
)
54 type funVV
func(z
, x
, y
[]Word
) (c Word
)
62 {nat
{0}, nat
{0}, nat
{0}, 0},
63 {nat
{1}, nat
{1}, nat
{0}, 0},
64 {nat
{0}, nat
{_M
}, nat
{1}, 1},
65 {nat
{80235}, nat
{12345}, nat
{67890}, 0},
66 {nat
{_M
- 1}, nat
{_M
}, nat
{_M
}, 1},
67 {nat
{0, 0, 0, 0}, nat
{_M
, _M
, _M
, _M
}, nat
{1, 0, 0, 0}, 1},
68 {nat
{0, 0, 0, _M
}, nat
{_M
, _M
, _M
, _M
- 1}, nat
{1, 0, 0, 0}, 0},
69 {nat
{0, 0, 0, 0}, nat
{_M
, 0, _M
, 0}, nat
{1, _M
, 0, _M
}, 1},
72 func testFunVV(t
*testing
.T
, msg
string, f funVV
, a argVV
) {
73 z
:= make(nat
, len(a
.z
))
75 for i
, zi
:= range z
{
77 t
.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg
, a
, i
, zi
, a
.z
[i
])
82 t
.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg
, a
, c
, a
.c
)
86 func TestFunVV(t
*testing
.T
) {
87 for _
, a
:= range sumVV
{
89 testFunVV(t
, "addVV_g", addVV_g
, arg
)
90 testFunVV(t
, "addVV", addVV
, arg
)
92 arg
= argVV
{a
.z
, a
.y
, a
.x
, a
.c
}
93 testFunVV(t
, "addVV_g symmetric", addVV_g
, arg
)
94 testFunVV(t
, "addVV symmetric", addVV
, arg
)
96 arg
= argVV
{a
.x
, a
.z
, a
.y
, a
.c
}
97 testFunVV(t
, "subVV_g", subVV_g
, arg
)
98 testFunVV(t
, "subVV", subVV
, arg
)
100 arg
= argVV
{a
.y
, a
.z
, a
.x
, a
.c
}
101 testFunVV(t
, "subVV_g symmetric", subVV_g
, arg
)
102 testFunVV(t
, "subVV symmetric", subVV
, arg
)
106 // Always the same seed for reproducible results.
107 var rnd
= rand
.New(rand
.NewSource(0))
110 return Word(rnd
.Int63()<<1 | rnd
.Int63n(2))
113 func rndV(n
int) []Word
{
121 func benchmarkFunVV(b
*testing
.B
, f funVV
, n
int) {
125 b
.SetBytes(int64(n
* _W
))
127 for i
:= 0; i
< b
.N
; i
++ {
132 func BenchmarkAddVV_1(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 1) }
133 func BenchmarkAddVV_2(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 2) }
134 func BenchmarkAddVV_3(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 3) }
135 func BenchmarkAddVV_4(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 4) }
136 func BenchmarkAddVV_5(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 5) }
137 func BenchmarkAddVV_1e1(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 1e1
) }
138 func BenchmarkAddVV_1e2(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 1e2
) }
139 func BenchmarkAddVV_1e3(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 1e3
) }
140 func BenchmarkAddVV_1e4(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 1e4
) }
141 func BenchmarkAddVV_1e5(b
*testing
.B
) { benchmarkFunVV(b
, addVV
, 1e5
) }
143 type funVW
func(z
, x
[]Word
, y Word
) (c Word
)
153 {nat
{0}, nat
{0}, 0, 0},
154 {nat
{1}, nat
{0}, 1, 0},
155 {nat
{1}, nat
{1}, 0, 0},
156 {nat
{0}, nat
{_M
}, 1, 1},
157 {nat
{0, 0, 0, 0}, nat
{_M
, _M
, _M
, _M
}, 1, 1},
160 var prodVW
= []argVW
{
162 {nat
{0}, nat
{0}, 0, 0},
163 {nat
{0}, nat
{_M
}, 0, 0},
164 {nat
{0}, nat
{0}, _M
, 0},
165 {nat
{1}, nat
{1}, 1, 0},
166 {nat
{22793}, nat
{991}, 23, 0},
167 {nat
{0, 0, 0, 22793}, nat
{0, 0, 0, 991}, 23, 0},
168 {nat
{0, 0, 0, 0}, nat
{7893475, 7395495, 798547395, 68943}, 0, 0},
169 {nat
{0, 0, 0, 0}, nat
{0, 0, 0, 0}, 894375984, 0},
170 {nat
{_M
<< 1 & _M
}, nat
{_M
}, 1 << 1, _M
>> (_W
- 1)},
171 {nat
{_M
<< 7 & _M
}, nat
{_M
}, 1 << 7, _M
>> (_W
- 7)},
172 {nat
{_M
<< 7 & _M
, _M
, _M
, _M
}, nat
{_M
, _M
, _M
, _M
}, 1 << 7, _M
>> (_W
- 7)},
177 {nat
{0}, nat
{0}, 0, 0},
178 {nat
{0}, nat
{0}, 1, 0},
179 {nat
{0}, nat
{0}, 20, 0},
181 {nat
{_M
}, nat
{_M
}, 0, 0},
182 {nat
{_M
<< 1 & _M
}, nat
{_M
}, 1, 1},
183 {nat
{_M
<< 20 & _M
}, nat
{_M
}, 20, _M
>> (_W
- 20)},
185 {nat
{_M
, _M
, _M
}, nat
{_M
, _M
, _M
}, 0, 0},
186 {nat
{_M
<< 1 & _M
, _M
, _M
}, nat
{_M
, _M
, _M
}, 1, 1},
187 {nat
{_M
<< 20 & _M
, _M
, _M
}, nat
{_M
, _M
, _M
}, 20, _M
>> (_W
- 20)},
192 {nat
{0}, nat
{0}, 0, 0},
193 {nat
{0}, nat
{0}, 1, 0},
194 {nat
{0}, nat
{0}, 20, 0},
196 {nat
{_M
}, nat
{_M
}, 0, 0},
197 {nat
{_M
>> 1}, nat
{_M
}, 1, _M
<< (_W
- 1) & _M
},
198 {nat
{_M
>> 20}, nat
{_M
}, 20, _M
<< (_W
- 20) & _M
},
200 {nat
{_M
, _M
, _M
}, nat
{_M
, _M
, _M
}, 0, 0},
201 {nat
{_M
, _M
, _M
>> 1}, nat
{_M
, _M
, _M
}, 1, _M
<< (_W
- 1) & _M
},
202 {nat
{_M
, _M
, _M
>> 20}, nat
{_M
, _M
, _M
}, 20, _M
<< (_W
- 20) & _M
},
205 func testFunVW(t
*testing
.T
, msg
string, f funVW
, a argVW
) {
206 z
:= make(nat
, len(a
.z
))
208 for i
, zi
:= range z
{
210 t
.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg
, a
, i
, zi
, a
.z
[i
])
215 t
.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg
, a
, c
, a
.c
)
219 func makeFunVW(f
func(z
, x
[]Word
, s
uint) (c Word
)) funVW
{
220 return func(z
, x
[]Word
, s Word
) (c Word
) {
221 return f(z
, x
, uint(s
))
225 func TestFunVW(t
*testing
.T
) {
226 for _
, a
:= range sumVW
{
228 testFunVW(t
, "addVW_g", addVW_g
, arg
)
229 testFunVW(t
, "addVW", addVW
, arg
)
231 arg
= argVW
{a
.x
, a
.z
, a
.y
, a
.c
}
232 testFunVW(t
, "subVW_g", subVW_g
, arg
)
233 testFunVW(t
, "subVW", subVW
, arg
)
236 shlVW_g
:= makeFunVW(shlVU_g
)
237 shlVW
:= makeFunVW(shlVU
)
238 for _
, a
:= range lshVW
{
240 testFunVW(t
, "shlVU_g", shlVW_g
, arg
)
241 testFunVW(t
, "shlVU", shlVW
, arg
)
244 shrVW_g
:= makeFunVW(shrVU_g
)
245 shrVW
:= makeFunVW(shrVU
)
246 for _
, a
:= range rshVW
{
248 testFunVW(t
, "shrVU_g", shrVW_g
, arg
)
249 testFunVW(t
, "shrVU", shrVW
, arg
)
253 func benchmarkFunVW(b
*testing
.B
, f funVW
, n
int) {
257 b
.SetBytes(int64(n
* _W
))
259 for i
:= 0; i
< b
.N
; i
++ {
264 func BenchmarkAddVW_1(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 1) }
265 func BenchmarkAddVW_2(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 2) }
266 func BenchmarkAddVW_3(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 3) }
267 func BenchmarkAddVW_4(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 4) }
268 func BenchmarkAddVW_5(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 5) }
269 func BenchmarkAddVW_1e1(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 1e1
) }
270 func BenchmarkAddVW_1e2(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 1e2
) }
271 func BenchmarkAddVW_1e3(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 1e3
) }
272 func BenchmarkAddVW_1e4(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 1e4
) }
273 func BenchmarkAddVW_1e5(b
*testing
.B
) { benchmarkFunVW(b
, addVW
, 1e5
) }
275 type funVWW
func(z
, x
[]Word
, y
, r Word
) (c Word
)
282 var prodVWW
= []argVWW
{
284 {nat
{0}, nat
{0}, 0, 0, 0},
285 {nat
{991}, nat
{0}, 0, 991, 0},
286 {nat
{0}, nat
{_M
}, 0, 0, 0},
287 {nat
{991}, nat
{_M
}, 0, 991, 0},
288 {nat
{0}, nat
{0}, _M
, 0, 0},
289 {nat
{991}, nat
{0}, _M
, 991, 0},
290 {nat
{1}, nat
{1}, 1, 0, 0},
291 {nat
{992}, nat
{1}, 1, 991, 0},
292 {nat
{22793}, nat
{991}, 23, 0, 0},
293 {nat
{22800}, nat
{991}, 23, 7, 0},
294 {nat
{0, 0, 0, 22793}, nat
{0, 0, 0, 991}, 23, 0, 0},
295 {nat
{7, 0, 0, 22793}, nat
{0, 0, 0, 991}, 23, 7, 0},
296 {nat
{0, 0, 0, 0}, nat
{7893475, 7395495, 798547395, 68943}, 0, 0, 0},
297 {nat
{991, 0, 0, 0}, nat
{7893475, 7395495, 798547395, 68943}, 0, 991, 0},
298 {nat
{0, 0, 0, 0}, nat
{0, 0, 0, 0}, 894375984, 0, 0},
299 {nat
{991, 0, 0, 0}, nat
{0, 0, 0, 0}, 894375984, 991, 0},
300 {nat
{_M
<< 1 & _M
}, nat
{_M
}, 1 << 1, 0, _M
>> (_W
- 1)},
301 {nat
{_M
<<1&_M
+ 1}, nat
{_M
}, 1 << 1, 1, _M
>> (_W
- 1)},
302 {nat
{_M
<< 7 & _M
}, nat
{_M
}, 1 << 7, 0, _M
>> (_W
- 7)},
303 {nat
{_M
<<7&_M
+ 1<<6}, nat
{_M
}, 1 << 7, 1 << 6, _M
>> (_W
- 7)},
304 {nat
{_M
<< 7 & _M
, _M
, _M
, _M
}, nat
{_M
, _M
, _M
, _M
}, 1 << 7, 0, _M
>> (_W
- 7)},
305 {nat
{_M
<<7&_M
+ 1<<6, _M
, _M
, _M
}, nat
{_M
, _M
, _M
, _M
}, 1 << 7, 1 << 6, _M
>> (_W
- 7)},
308 func testFunVWW(t
*testing
.T
, msg
string, f funVWW
, a argVWW
) {
309 z
:= make(nat
, len(a
.z
))
310 c
:= f(z
, a
.x
, a
.y
, a
.r
)
311 for i
, zi
:= range z
{
313 t
.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg
, a
, i
, zi
, a
.z
[i
])
318 t
.Errorf("%s%+v\n\tgot c = %#x; want %#x", msg
, a
, c
, a
.c
)
322 // TODO(gri) mulAddVWW and divWVW are symmetric operations but
323 // their signature is not symmetric. Try to unify.
325 type funWVW
func(z
[]Word
, xn Word
, x
[]Word
, y Word
) (r Word
)
334 func testFunWVW(t
*testing
.T
, msg
string, f funWVW
, a argWVW
) {
335 z
:= make(nat
, len(a
.z
))
336 r
:= f(z
, a
.xn
, a
.x
, a
.y
)
337 for i
, zi
:= range z
{
339 t
.Errorf("%s%+v\n\tgot z[%d] = %#x; want %#x", msg
, a
, i
, zi
, a
.z
[i
])
344 t
.Errorf("%s%+v\n\tgot r = %#x; want %#x", msg
, a
, r
, a
.r
)
348 func TestFunVWW(t
*testing
.T
) {
349 for _
, a
:= range prodVWW
{
351 testFunVWW(t
, "mulAddVWW_g", mulAddVWW_g
, arg
)
352 testFunVWW(t
, "mulAddVWW", mulAddVWW
, arg
)
354 if a
.y
!= 0 && a
.r
< a
.y
{
355 arg
:= argWVW
{a
.x
, a
.c
, a
.z
, a
.y
, a
.r
}
356 testFunWVW(t
, "divWVW_g", divWVW_g
, arg
)
357 testFunWVW(t
, "divWVW", divWVW
, arg
)
362 var mulWWTests
= []struct {
367 // 32 bit only: {0xc47dfa8c, 50911, 0x98a4, 0x998587f4},
370 func TestMulWW(t
*testing
.T
) {
371 for i
, test
:= range mulWWTests
{
372 q
, r
:= mulWW_g(test
.x
, test
.y
)
373 if q
!= test
.q || r
!= test
.r
{
374 t
.Errorf("#%d got (%x, %x) want (%x, %x)", i
, q
, r
, test
.q
, test
.r
)
379 var mulAddWWWTests
= []struct {
383 // TODO(agl): These will only work on 64-bit platforms.
384 // {15064310297182388543, 0xe7df04d2d35d5d80, 13537600649892366549, 13644450054494335067, 10832252001440893781},
385 // {15064310297182388543, 0xdab2f18048baa68d, 13644450054494335067, 12869334219691522700, 14233854684711418382},
386 {_M
, _M
, 0, _M
- 1, 1},
390 func TestMulAddWWW(t
*testing
.T
) {
391 for i
, test
:= range mulAddWWWTests
{
392 q
, r
:= mulAddWWW_g(test
.x
, test
.y
, test
.c
)
393 if q
!= test
.q || r
!= test
.r
{
394 t
.Errorf("#%d got (%x, %x) want (%x, %x)", i
, q
, r
, test
.q
, test
.r
)
399 func benchmarkAddMulVVW(b
*testing
.B
, n
int) {
403 b
.SetBytes(int64(n
* _W
))
405 for i
:= 0; i
< b
.N
; i
++ {
410 func BenchmarkAddMulVVW_1(b
*testing
.B
) { benchmarkAddMulVVW(b
, 1) }
411 func BenchmarkAddMulVVW_2(b
*testing
.B
) { benchmarkAddMulVVW(b
, 2) }
412 func BenchmarkAddMulVVW_3(b
*testing
.B
) { benchmarkAddMulVVW(b
, 3) }
413 func BenchmarkAddMulVVW_4(b
*testing
.B
) { benchmarkAddMulVVW(b
, 4) }
414 func BenchmarkAddMulVVW_5(b
*testing
.B
) { benchmarkAddMulVVW(b
, 5) }
415 func BenchmarkAddMulVVW_1e1(b
*testing
.B
) { benchmarkAddMulVVW(b
, 1e1
) }
416 func BenchmarkAddMulVVW_1e2(b
*testing
.B
) { benchmarkAddMulVVW(b
, 1e2
) }
417 func BenchmarkAddMulVVW_1e3(b
*testing
.B
) { benchmarkAddMulVVW(b
, 1e3
) }
418 func BenchmarkAddMulVVW_1e4(b
*testing
.B
) { benchmarkAddMulVVW(b
, 1e4
) }
419 func BenchmarkAddMulVVW_1e5(b
*testing
.B
) { benchmarkAddMulVVW(b
, 1e5
) }
421 func testWordBitLen(t
*testing
.T
, fname
string, f
func(Word
) int) {
422 for i
:= 0; i
<= _W
; i
++ {
423 x
:= Word(1) << uint(i
-1) // i == 0 => x == 0
426 t
.Errorf("got %d; want %d for %s(%#x)", n
, i
, fname
, x
)
431 func TestWordBitLen(t
*testing
.T
) {
432 testWordBitLen(t
, "bitLen", bitLen
)
433 testWordBitLen(t
, "bitLen_g", bitLen_g
)
436 // runs b.N iterations of bitLen called on a Word containing (1 << nbits)-1.
437 func benchmarkBitLenN(b
*testing
.B
, nbits
uint) {
438 testword
:= Word((uint64(1) << nbits
) - 1)
439 for i
:= 0; i
< b
.N
; i
++ {
444 // Individual bitLen tests. Numbers chosen to examine both sides
445 // of powers-of-two boundaries.
446 func BenchmarkBitLen0(b
*testing
.B
) { benchmarkBitLenN(b
, 0) }
447 func BenchmarkBitLen1(b
*testing
.B
) { benchmarkBitLenN(b
, 1) }
448 func BenchmarkBitLen2(b
*testing
.B
) { benchmarkBitLenN(b
, 2) }
449 func BenchmarkBitLen3(b
*testing
.B
) { benchmarkBitLenN(b
, 3) }
450 func BenchmarkBitLen4(b
*testing
.B
) { benchmarkBitLenN(b
, 4) }
451 func BenchmarkBitLen5(b
*testing
.B
) { benchmarkBitLenN(b
, 5) }
452 func BenchmarkBitLen8(b
*testing
.B
) { benchmarkBitLenN(b
, 8) }
453 func BenchmarkBitLen9(b
*testing
.B
) { benchmarkBitLenN(b
, 9) }
454 func BenchmarkBitLen16(b
*testing
.B
) { benchmarkBitLenN(b
, 16) }
455 func BenchmarkBitLen17(b
*testing
.B
) { benchmarkBitLenN(b
, 17) }
456 func BenchmarkBitLen31(b
*testing
.B
) { benchmarkBitLenN(b
, 31) }