]> Cypherpunks.ru repositories - gostls13.git/blob - test/64bit.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / 64bit.go
1 // runoutput
2
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Generate test of 64-bit arithmetic.
8 // Most synthesized routines have different cases for
9 // constants vs variables and even the generated code has
10 // different cases for large and small constants,
11 // so try a good range of inputs.
12
13 package main
14
15 import (
16         "bufio"
17         "fmt"
18         "os"
19 )
20
21 var bout *bufio.Writer
22
23 // 64-bit math without using 64-bit numbers,
24 // so that we can generate the test program even
25 // if the compiler has buggy or missing 64-bit support.
26
27 type Uint64 struct {
28         hi      uint32
29         lo      uint32
30 }
31
32 type Int64 struct {
33         hi      int32
34         lo      uint32
35 }
36
37 func (a Uint64) Int64() (c Int64) {
38         c.hi = int32(a.hi)
39         c.lo = a.lo
40         return
41 }
42
43 func (a Uint64) Cmp(b Uint64) int {
44         switch {
45         case a.hi < b.hi:
46                 return -1
47         case a.hi > b.hi:
48                 return 1
49         case a.lo < b.lo:
50                 return -1
51         case a.lo > b.lo:
52                 return 1
53         }
54         return 0
55 }
56
57 func (a Uint64) LeftShift(b uint) (c Uint64) {
58         switch {
59         case b >= 64:
60                 c.hi = 0
61                 c.lo = 0
62         case b >= 32:
63                 c.hi = a.lo << (b - 32)
64                 c.lo = 0
65         default:
66                 c.hi = a.hi<<b | a.lo>>(32-b)
67                 c.lo = a.lo << b
68         }
69         return
70 }
71
72 func (a Uint64) RightShift(b uint) (c Uint64) {
73         switch {
74         case b >= 64:
75                 c.hi = 0
76                 c.lo = a.hi
77         case b >= 32:
78                 c.hi = 0
79                 c.lo = a.hi >> (b - 32)
80         default:
81                 c.hi = a.hi >> b
82                 c.lo = a.hi<<(32-b) | a.lo>>b
83         }
84         return
85 }
86
87 func (a Uint64) LeftShift64(b Uint64) (c Uint64) {
88         if b.hi != 0 || b.lo >= 64 {
89                 return
90         }
91         return a.LeftShift(uint(b.lo))
92 }
93
94 func (a Uint64) RightShift64(b Uint64) (c Uint64) {
95         if b.hi != 0 || b.lo >= 64 {
96                 return
97         }
98         return a.RightShift(uint(b.lo))
99 }
100
101 func (a Uint64) Plus(b Uint64) (c Uint64) {
102         var carry uint32
103         if c.lo = a.lo + b.lo; c.lo < a.lo {
104                 carry = 1
105         }
106         c.hi = a.hi + b.hi + carry
107         return
108 }
109
110 func (a Uint64) Minus(b Uint64) (c Uint64) {
111         var borrow uint32
112         if c.lo = a.lo - b.lo; c.lo > a.lo {
113                 borrow = 1
114         }
115         c.hi = a.hi - b.hi - borrow
116         return
117 }
118
119 func (a Uint64) Neg() (c Uint64) {
120         var zero Uint64
121         return zero.Minus(a)
122 }
123
124 func (a Uint64) Com() (c Uint64) {
125         c.hi = ^a.hi
126         c.lo = ^a.lo
127         return
128 }
129
130 func (a Uint64) Len() int {
131         switch {
132         case a.hi != 0:
133                 for i := 31; i >= 0; i-- {
134                         if a.hi&(1<<uint(i)) != 0 {
135                                 return i + 1 + 32
136                         }
137                 }
138         case a.lo != 0:
139                 for i := 31; i >= 0; i-- {
140                         if a.lo&(1<<uint(i)) != 0 {
141                                 return i + 1
142                         }
143                 }
144         }
145         return 0
146 }
147
148 func (a Uint64) HasBit(b uint) bool {
149         switch {
150         case b >= 64:
151                 return false
152         case b >= 32:
153                 return a.hi&(1<<(b-32)) != 0
154         }
155         return a.lo&(1<<b) != 0
156 }
157
158 func (a Uint64) Times(b Uint64) (c Uint64) {
159         for i := uint(0); i < 64; i++ {
160                 if b.HasBit(i) {
161                         c = c.Plus(a.LeftShift(i))
162                 }
163         }
164         return
165 }
166
167 func (a Uint64) DivMod(b Uint64) (quo, rem Uint64) {
168         n := a.Len() - b.Len()
169         if n >= 0 {
170                 b = b.LeftShift(uint(n))
171                 for i := 0; i <= n; i++ {
172                         quo = quo.LeftShift(1)
173                         if b.Cmp(a) <= 0 {      // b <= a
174                                 quo.lo |= 1
175                                 a = a.Minus(b)
176                         }
177                         b = b.RightShift(1)
178                 }
179         }
180         rem = a
181         return
182 }
183
184 func (a Uint64) And(b Uint64) (c Uint64) {
185         c.hi = a.hi & b.hi
186         c.lo = a.lo & b.lo
187         return
188 }
189
190 func (a Uint64) AndNot(b Uint64) (c Uint64) {
191         c.hi = a.hi &^ b.hi
192         c.lo = a.lo &^ b.lo
193         return
194 }
195
196 func (a Uint64) Or(b Uint64) (c Uint64) {
197         c.hi = a.hi | b.hi
198         c.lo = a.lo | b.lo
199         return
200 }
201
202 func (a Uint64) Xor(b Uint64) (c Uint64) {
203         c.hi = a.hi ^ b.hi
204         c.lo = a.lo ^ b.lo
205         return
206 }
207
208 func (a Uint64) String() string { return fmt.Sprintf("%#x%08x", a.hi, a.lo) }
209
210 func (a Int64) Uint64() (c Uint64) {
211         c.hi = uint32(a.hi)
212         c.lo = a.lo
213         return
214 }
215
216 func (a Int64) Cmp(b Int64) int {
217         // Same body as Uint64.Cmp,
218         // but behaves differently
219         // because hi is uint32 not int32.
220         switch {
221         case a.hi < b.hi:
222                 return -1
223         case a.hi > b.hi:
224                 return 1
225         case a.lo < b.lo:
226                 return -1
227         case a.lo > b.lo:
228                 return 1
229         }
230         return 0
231 }
232
233 func (a Int64) LeftShift(b uint) (c Int64)      { return a.Uint64().LeftShift(b).Int64() }
234
235 func (a Int64) RightShift(b uint) (c Int64) {
236         switch {
237         case b >= 64:
238                 c.hi = a.hi >> 31       // sign extend
239                 c.lo = uint32(c.hi)
240         case b >= 32:
241                 c.hi = a.hi >> 31       // sign extend
242                 c.lo = uint32(a.hi >> (b - 32))
243         default:
244                 c.hi = a.hi >> b
245                 c.lo = uint32(a.hi<<(32-b)) | a.lo>>b
246         }
247         return
248 }
249
250 func (a Int64) LeftShift64(b Uint64) (c Int64) {
251         if b.hi != 0 || b.lo >= 64 {
252                 return
253         }
254         return a.LeftShift(uint(b.lo))
255 }
256
257 func (a Int64) RightShift64(b Uint64) (c Int64) {
258         if b.hi != 0 || b.lo >= 64 {
259                 return a.RightShift(64)
260         }
261         return a.RightShift(uint(b.lo))
262 }
263
264 func (a Int64) Plus(b Int64) (c Int64)  { return a.Uint64().Plus(b.Uint64()).Int64() }
265
266 func (a Int64) Minus(b Int64) (c Int64) { return a.Uint64().Minus(b.Uint64()).Int64() }
267
268 func (a Int64) Neg() (c Int64)  { return a.Uint64().Neg().Int64() }
269
270 func (a Int64) Com() (c Int64)  { return a.Uint64().Com().Int64() }
271
272 func (a Int64) Times(b Int64) (c Int64) { return a.Uint64().Times(b.Uint64()).Int64() }
273
274 func (a Int64) DivMod(b Int64) (quo Int64, rem Int64) {
275         var zero Int64
276
277         quoSign := +1
278         remSign := +1
279         if a.Cmp(zero) < 0 {
280                 quoSign = -1
281                 remSign = -1
282                 a = a.Neg()
283         }
284         if b.Cmp(zero) < 0 {
285                 quoSign = -quoSign
286                 b = b.Neg()
287         }
288
289         q, r := a.Uint64().DivMod(b.Uint64())
290         quo = q.Int64()
291         rem = r.Int64()
292
293         if quoSign < 0 {
294                 quo = quo.Neg()
295         }
296         if remSign < 0 {
297                 rem = rem.Neg()
298         }
299         return
300 }
301
302 func (a Int64) And(b Int64) (c Int64)   { return a.Uint64().And(b.Uint64()).Int64() }
303
304 func (a Int64) AndNot(b Int64) (c Int64)        { return a.Uint64().AndNot(b.Uint64()).Int64() }
305
306 func (a Int64) Or(b Int64) (c Int64)    { return a.Uint64().Or(b.Uint64()).Int64() }
307
308 func (a Int64) Xor(b Int64) (c Int64)   { return a.Uint64().Xor(b.Uint64()).Int64() }
309
310 func (a Int64) String() string {
311         if a.hi < 0 {
312                 return fmt.Sprintf("-%s", a.Neg().Uint64())
313         }
314         return a.Uint64().String()
315 }
316
317 var int64Values = []Int64{
318         Int64{0, 0},
319         Int64{0, 1},
320         Int64{0, 2},
321         Int64{0, 3},
322         Int64{0, 100},
323         Int64{0, 10001},
324         Int64{0, 1<<31 - 1},
325         Int64{0, 1 << 31},
326         Int64{0, 1<<31 + 1},
327         Int64{0, 1<<32 - 1<<30},
328         Int64{0, 1<<32 - 1},
329         Int64{1, 0},
330         Int64{1, 1},
331         Int64{2, 0},
332         Int64{1<<31 - 1, 1<<32 - 10000},
333         Int64{1<<31 - 1, 1<<32 - 1},
334         Int64{0x789abcde, 0xf0123456},
335
336         Int64{-1, 1<<32 - 1},
337         Int64{-1, 1<<32 - 2},
338         Int64{-1, 1<<32 - 3},
339         Int64{-1, 1<<32 - 100},
340         Int64{-1, 1<<32 - 10001},
341         Int64{-1, 1<<32 - (1<<31 - 1)},
342         Int64{-1, 1<<32 - 1<<31},
343         Int64{-1, 1<<32 - (1<<31 + 1)},
344         Int64{-1, 1<<32 - (1<<32 - 1<<30)},
345         Int64{-1, 0},
346         Int64{-1, 1},
347         Int64{-2, 0},
348         Int64{-(1 << 31), 10000},
349         Int64{-(1 << 31), 1},
350         Int64{-(1 << 31), 0},
351         Int64{-0x789abcde, 0xf0123456},
352 }
353
354 var uint64Values = []Uint64{
355         Uint64{0, 0},
356         Uint64{0, 1},
357         Uint64{0, 2},
358         Uint64{0, 3},
359         Uint64{0, 100},
360         Uint64{0, 10001},
361         Uint64{0, 1<<31 - 1},
362         Uint64{0, 1 << 31},
363         Uint64{0, 1<<31 + 1},
364         Uint64{0, 1<<32 - 1<<30},
365         Uint64{0, 1<<32 - 1},
366         Uint64{1, 0},
367         Uint64{1, 1},
368         Uint64{2, 0},
369         Uint64{1<<31 - 1, 1<<32 - 10000},
370         Uint64{1<<31 - 1, 1<<32 - 1},
371         Uint64{1<<32 - 1<<30, 0},
372         Uint64{1<<32 - 1, 0},
373         Uint64{1<<32 - 1, 1<<32 - 100},
374         Uint64{1<<32 - 1, 1<<32 - 1},
375         Uint64{0x789abcde, 0xf0123456},
376         Uint64{0xfedcba98, 0x76543210},
377 }
378
379 var shiftValues = []Uint64{
380         Uint64{0, 0},
381         Uint64{0, 1},
382         Uint64{0, 2},
383         Uint64{0, 3},
384         Uint64{0, 15},
385         Uint64{0, 16},
386         Uint64{0, 17},
387         Uint64{0, 31},
388         Uint64{0, 32},
389         Uint64{0, 33},
390         Uint64{0, 61},
391         Uint64{0, 62},
392         Uint64{0, 63},
393         Uint64{0, 64},
394         Uint64{0, 65},
395         Uint64{0, 1<<32 - 1},
396         Uint64{1, 0},
397         Uint64{1, 1},
398         Uint64{1 << 28, 0},
399         Uint64{1 << 31, 0},
400         Uint64{1<<32 - 1, 0},
401         Uint64{1<<32 - 1, 1<<32 - 1},
402 }
403
404 var ntest = 0
405
406 // Part 1 is tests of variable operations; generic functions
407 // called by repetitive code.  Could make a table but not worth it.
408
409 const prolog = "\n" +
410         "package main\n" +
411         "\n" +
412         "import \"os\"\n" +
413         "\n" +
414         "var ok = true\n" +
415         "\n" +
416         "func testInt64Unary(a, plus, xor, minus int64) {\n" +
417         "       if n, op, want := +a, `+`, plus; n != want { ok=false; println(`int64`, op, a, `=`, n, `should be`, want); }\n" +
418         "       if n, op, want := ^a, `^`, xor; n != want { ok=false; println(`int64`, op, a, `=`, n, `should be`, want); }\n" +
419         "       if n, op, want := -a, `-`, minus; n != want { ok=false; println(`int64`, op, a, `=`, n, `should be`, want); }\n" +
420         "}\n" +
421         "\n" +
422         "func testInt64Binary(a, b, add, sub, mul, div, mod, and, or, xor, andnot int64, dodiv bool) {\n" +
423         "       if n, op, want := a + b, `+`, add; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
424         "       if n, op, want := a - b, `-`, sub; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
425         "       if n, op, want := a * b, `*`, mul; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
426         "       if dodiv {\n" +
427         "               if n, op, want := a / b, `/`, div; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
428         "               if n, op, want := a % b, `%`, mod; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
429         "       }\n" +
430         "       if n, op, want := a & b, `&`, and; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
431         "       if n, op, want := a | b, `|`, or; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
432         "       if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
433         "       if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(`int64`, a, op, b, `=`, n, `should be`, want); }\n" +
434         "}\n" +
435         "\n" +
436         "func testInt64Shift(a int64, b uint64, left, right int64) {\n" +
437         "       if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`int64`, a, op, `uint64`, s, `=`, n, `should be`, want); }\n" +
438         "       if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`int64`, a, op, `uint64`, s, `=`, n, `should be`, want); }\n" +
439         "       if uint64(uint(b)) == b {\n" +
440         "               b := uint(b);\n" +
441         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`int64`, a, op, `uint`, s, `=`, n, `should be`, want); }\n" +
442         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`int64`, a, op, `uint`, s, `=`, n, `should be`, want); }\n" +
443         "       }\n" +
444         "       if uint64(uint32(b)) == b {\n" +
445         "               b := uint32(b);\n" +
446         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`int64`, a, op, `uint32`, s, `=`, n, `should be`, want); }\n" +
447         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`int64`, a, op, `uint32`, s, `=`, n, `should be`, want); }\n" +
448         "       }\n" +
449         "       if uint64(uint16(b)) == b {\n" +
450         "               b := uint16(b);\n" +
451         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`int64`, a, op, `uint16`, s, `=`, n, `should be`, want); }\n" +
452         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`int64`, a, op, `uint16`, s, `=`, n, `should be`, want); }\n" +
453         "       }\n" +
454         "       if uint64(uint8(b)) == b {\n" +
455         "               b := uint8(b);\n" +
456         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`int64`, a, op, `uint8`, s, `=`, n, `should be`, want); }\n" +
457         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`int64`, a, op, `uint8`, s, `=`, n, `should be`, want); }\n" +
458         "       }\n" +
459         "}\n" +
460         "\n" +
461         "func testUint64Unary(a, plus, xor, minus uint64) {\n" +
462         "       if n, op, want := +a, `+`, plus; n != want { ok=false; println(`uint64`, op, a, `=`, n, `should be`, want); }\n" +
463         "       if n, op, want := ^a, `^`, xor; n != want { ok=false; println(`uint64`, op, a, `=`, n, `should be`, want); }\n" +
464         "       if n, op, want := -a, `-`, minus; n != want { ok=false; println(`uint64`, op, a, `=`, n, `should be`, want); }\n" +
465         "}\n" +
466         "\n" +
467         "func testUint64Binary(a, b, add, sub, mul, div, mod, and, or, xor, andnot uint64, dodiv bool) {\n" +
468         "       if n, op, want := a + b, `+`, add; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
469         "       if n, op, want := a - b, `-`, sub; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
470         "       if n, op, want := a * b, `*`, mul; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
471         "       if dodiv {\n" +
472         "               if n, op, want := a / b, `/`, div; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
473         "               if n, op, want := a % b, `%`, mod; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
474         "       }\n" +
475         "       if n, op, want := a & b, `&`, and; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
476         "       if n, op, want := a | b, `|`, or; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
477         "       if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
478         "       if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(`uint64`, a, op, b, `=`, n, `should be`, want); }\n" +
479         "}\n" +
480         "\n" +
481         "func testUint64Shift(a, b, left, right uint64) {\n" +
482         "       if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`uint64`, a, op, `uint64`, s, `=`, n, `should be`, want); }\n" +
483         "       if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`uint64`, a, op, `uint64`, s, `=`, n, `should be`, want); }\n" +
484         "       if uint64(uint(b)) == b {\n" +
485         "               b := uint(b);\n" +
486         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`uint64`, a, op, `uint`, s, `=`, n, `should be`, want); }\n" +
487         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`uint64`, a, op, `uint`, s, `=`, n, `should be`, want); }\n" +
488         "       }\n" +
489         "       if uint64(uint32(b)) == b {\n" +
490         "               b := uint32(b);\n" +
491         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`uint64`, a, op, `uint32`, s, `=`, n, `should be`, want); }\n" +
492         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`uint64`, a, op, `uint32`, s, `=`, n, `should be`, want); }\n" +
493         "       }\n" +
494         "       if uint64(uint16(b)) == b {\n" +
495         "               b := uint16(b);\n" +
496         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`uint64`, a, op, `uint16`, s, `=`, n, `should be`, want); }\n" +
497         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`uint64`, a, op, `uint16`, s, `=`, n, `should be`, want); }\n" +
498         "       }\n" +
499         "       if uint64(uint8(b)) == b {\n" +
500         "               b := uint8(b);\n" +
501         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(`uint64`, a, op, `uint8`, s, `=`, n, `should be`, want); }\n" +
502         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(`uint64`, a, op, `uint8`, s, `=`, n, `should be`, want); }\n" +
503         "       }\n" +
504         "}\n" +
505         "\n"
506
507 func varTests() {
508         fmt.Fprint(bout, prolog)
509         for _, a := range int64Values {
510                 fmt.Fprintf(bout, "func test%v() {\n", ntest)
511                 ntest++
512                 fmt.Fprintf(bout, "\ttestInt64Unary(%v, %v, %v, %v);\n", a, a, a.Com(), a.Neg())
513                 for _, b := range int64Values {
514                         var div, mod Int64
515                         dodiv := false
516                         var zero Int64
517                         if b.Cmp(zero) != 0 {   // b != 0
518                                 // Can't divide by zero but also can't divide -0x8000...000 by -1.
519                                 var bigneg = Int64{-0x80000000, 0}
520                                 var minus1 = Int64{-1, ^uint32(0)}
521                                 if a.Cmp(bigneg) != 0 || b.Cmp(minus1) != 0 {   // a != -1<<63 || b != -1
522                                         div, mod = a.DivMod(b)
523                                         dodiv = true
524                                 }
525                         }
526                         fmt.Fprintf(bout, "\ttestInt64Binary(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v);\n",
527                                 a, b, a.Plus(b), a.Minus(b), a.Times(b), div, mod,
528                                 a.And(b), a.Or(b), a.Xor(b), a.AndNot(b), dodiv)
529                 }
530                 for _, b := range shiftValues {
531                         fmt.Fprintf(bout, "\ttestInt64Shift(%v, %v, %v, %v);\n",
532                                 a, b, a.LeftShift64(b), a.RightShift64(b))
533                 }
534                 fmt.Fprintf(bout, "}\n")
535         }
536
537         for _, a := range uint64Values {
538                 fmt.Fprintf(bout, "func test%v() {\n", ntest)
539                 ntest++
540                 fmt.Fprintf(bout, "\ttestUint64Unary(%v, %v, %v, %v);\n", a, a, a.Com(), a.Neg())
541                 for _, b := range uint64Values {
542                         var div, mod Uint64
543                         dodiv := false
544                         var zero Uint64
545                         if b.Cmp(zero) != 0 {   // b != 0
546                                 div, mod = a.DivMod(b)
547                                 dodiv = true
548                         }
549                         fmt.Fprintf(bout, "\ttestUint64Binary(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v);\n",
550                                 a, b, a.Plus(b), a.Minus(b), a.Times(b), div, mod,
551                                 a.And(b), a.Or(b), a.Xor(b), a.AndNot(b), dodiv)
552                 }
553                 for _, b := range shiftValues {
554                         fmt.Fprintf(bout, "\ttestUint64Shift(%v, %v, %v, %v);\n",
555                                 a, b, a.LeftShift64(b), a.RightShift64(b))
556                 }
557                 fmt.Fprintf(bout, "}\n")
558         }
559 }
560
561 // Part 2 is tests of operations involving one variable and one constant.
562
563 const binaryConstL = "func test%vBinaryL%v(b, add, sub, mul, div, mod, and, or, xor, andnot %v, dodiv bool) {\n" +
564         "       const a %v = %v;\n" +
565         "       const typ = `%s`;\n" +
566         "       if n, op, want := a + b, `+`, add; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
567         "       if n, op, want := a - b, `-`, sub; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
568         "       if n, op, want := a * b, `*`, mul; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
569         "       if dodiv {\n" +
570         "               if n, op, want := a / b, `/`, div; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
571         "               if n, op, want := a %% b, `%%`, mod; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
572         "       }\n" +
573         "       if n, op, want := a & b, `&`, and; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
574         "       if n, op, want := a | b, `|`, or; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
575         "       if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
576         "       if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(typ, `const`, a, op, `var`, b, `=`, n, `should be`, want); }\n" +
577         "}\n" +
578         "\n"
579
580 const binaryConstR = "func test%vBinaryR%v(a, add, sub, mul, div, mod, and, or, xor, andnot %v, dodiv bool) {\n" +
581         "       const b %v = %v;\n" +
582         "       const typ = `%s`;\n" +
583         "       if n, op, want := a + b, `+`, add; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
584         "       if n, op, want := a - b, `-`, sub; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
585         "       if n, op, want := a * b, `*`, mul; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
586         "       if dodiv {\n" +
587         "               if n, op, want := a / b, `/`, div; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
588         "               if n, op, want := a %% b, `%%`, mod; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
589         "       }\n" +
590         "       if n, op, want := a & b, `&`, and; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
591         "       if n, op, want := a | b, `|`, or; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
592         "       if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
593         "       if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
594         "}\n" +
595         "\n"
596
597 const binaryConstR0 = "func test%vBinaryR%v(a, add, sub, mul, div, mod, and, or, xor, andnot %v, dodiv bool) {\n" +
598         "       const b %v = %v;\n" +
599         "       const typ = `%s`;\n" +
600         "       if n, op, want := a + b, `+`, add; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
601         "       if n, op, want := a - b, `-`, sub; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
602         "       if n, op, want := a * b, `*`, mul; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
603         "       if n, op, want := a & b, `&`, and; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
604         "       if n, op, want := a | b, `|`, or; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
605         "       if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
606         "       if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
607         "}\n" +
608         "\n"
609
610 const shiftConstL = "func test%vShiftL%v(b uint64, left, right %v) {\n" +
611         "       const a %v = %v;\n" +
612         "       const typ = `%s`;\n" +
613         "       if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(typ, `const`, a, op, `var`, s, `=`, n, `should be`, want); }\n" +
614         "       if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(typ, `const`, a, op, `var`, s, `=`, n, `should be`, want); }\n" +
615         "       if uint64(uint32(b)) == b {\n" +
616         "               b := uint32(b);\n" +
617         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(typ, `const`, a, op, `var`, s, `=`, n, `should be`, want); }\n" +
618         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(typ, `const`, a, op, `var`, s, `=`, n, `should be`, want); }\n" +
619         "       }\n" +
620         "}\n"
621
622 const shiftConstR = "func test%vShiftR%v(a, left, right %v) {\n" +
623         "       const b uint64 = %v;\n" +
624         "       const typ = `%s`;\n" +
625         "       if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(typ, `var`, a, op, `const`, s, `=`, n, `should be`, want); }\n" +
626         "       if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(typ, `var`, a, op, `const`, s, `=`, n, `should be`, want); }\n" +
627         "       if b & 0xffffffff == b {\n" +
628         "               const b = uint32(b & 0xffffffff);\n" +
629         "               if n, op, s, want := a << b, `<<`, b, left; n != want { ok=false; println(typ, `var`, a, op, `const`, s, `=`, n, `should be`, want); }\n" +
630         "               if n, op, s, want := a >> b, `>>`, b, right; n != want { ok=false; println(typ, `var`, a, op, `const`, s, `=`, n, `should be`, want); }\n" +
631         "       }\n" +
632         "}\n"
633
634 func constTests() {
635         for i, a := range int64Values {
636                 fmt.Fprintf(bout, binaryConstL, "Int64", i, "int64", "int64", a, "int64")
637                 if a.hi == 0 && a.lo == 0 {
638                         fmt.Fprintf(bout, binaryConstR0, "Int64", i, "int64", "int64", a, "int64")
639                 } else {
640                         fmt.Fprintf(bout, binaryConstR, "Int64", i, "int64", "int64", a, "int64")
641                 }
642                 fmt.Fprintf(bout, shiftConstL, "Int64", i, "int64", "int64", a, "int64")
643         }
644         for i, a := range uint64Values {
645                 fmt.Fprintf(bout, binaryConstL, "Uint64", i, "uint64", "uint64", a, "uint64")
646                 if a.hi == 0 && a.lo == 0 {
647                         fmt.Fprintf(bout, binaryConstR0, "Uint64", i, "uint64", "uint64", a, "uint64")
648                 } else {
649                         fmt.Fprintf(bout, binaryConstR, "Uint64", i, "uint64", "uint64", a, "uint64")
650                 }
651                 fmt.Fprintf(bout, shiftConstL, "Uint64", i, "uint64", "uint64", a, "uint64")
652         }
653         for i, a := range shiftValues {
654                 fmt.Fprintf(bout, shiftConstR, "Int64", i, "int64", a, "int64")
655                 fmt.Fprintf(bout, shiftConstR, "Uint64", i, "uint64", a, "uint64")
656         }
657         for i, a := range int64Values {
658                 fmt.Fprintf(bout, "func test%v() {\n", ntest)
659                 ntest++
660                 for j, b := range int64Values {
661                         var div, mod Int64
662                         dodiv := false
663                         var zero Int64
664                         if b.Cmp(zero) != 0 {   // b != 0
665                                 // Can't divide by zero but also can't divide -0x8000...000 by -1.
666                                 var bigneg = Int64{-0x80000000, 0}
667                                 var minus1 = Int64{-1, ^uint32(0)}
668                                 if a.Cmp(bigneg) != 0 || b.Cmp(minus1) != 0 {   // a != -1<<63 || b != -1
669                                         div, mod = a.DivMod(b)
670                                         dodiv = true
671                                 }
672                         }
673                         fmt.Fprintf(bout, "\ttestInt64BinaryL%v(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v);\n",
674                                 i, b, a.Plus(b), a.Minus(b), a.Times(b), div, mod,
675                                 a.And(b), a.Or(b), a.Xor(b), a.AndNot(b), dodiv)
676                         fmt.Fprintf(bout, "\ttestInt64BinaryR%v(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v);\n",
677                                 j, a, a.Plus(b), a.Minus(b), a.Times(b), div, mod,
678                                 a.And(b), a.Or(b), a.Xor(b), a.AndNot(b), dodiv)
679                 }
680                 for j, b := range shiftValues {
681                         fmt.Fprintf(bout, "\ttestInt64ShiftL%v(%v, %v, %v);\n",
682                                 i, b, a.LeftShift64(b), a.RightShift64(b))
683                         fmt.Fprintf(bout, "\ttestInt64ShiftR%v(%v, %v, %v);\n",
684                                 j, a, a.LeftShift64(b), a.RightShift64(b))
685                 }
686                 fmt.Fprintf(bout, "}\n")
687         }
688         for i, a := range uint64Values {
689                 fmt.Fprintf(bout, "func test%v() {\n", ntest)
690                 ntest++
691                 for j, b := range uint64Values {
692                         var div, mod Uint64
693                         dodiv := false
694                         var zero Uint64
695                         if b.Cmp(zero) != 0 {   // b != 0
696                                 div, mod = a.DivMod(b)
697                                 dodiv = true
698                         }
699                         fmt.Fprintf(bout, "\ttestUint64BinaryL%v(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v);\n",
700                                 i, b, a.Plus(b), a.Minus(b), a.Times(b), div, mod,
701                                 a.And(b), a.Or(b), a.Xor(b), a.AndNot(b), dodiv)
702                         fmt.Fprintf(bout, "\ttestUint64BinaryR%v(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v);\n",
703                                 j, a, a.Plus(b), a.Minus(b), a.Times(b), div, mod,
704                                 a.And(b), a.Or(b), a.Xor(b), a.AndNot(b), dodiv)
705                 }
706                 for j, b := range shiftValues {
707                         fmt.Fprintf(bout, "\ttestUint64ShiftL%v(%v, %v, %v);\n",
708                                 i, b, a.LeftShift64(b), a.RightShift64(b))
709                         fmt.Fprintf(bout, "\ttestUint64ShiftR%v(%v, %v, %v);\n",
710                                 j, a, a.LeftShift64(b), a.RightShift64(b))
711                 }
712                 fmt.Fprintf(bout, "}\n")
713         }
714 }
715
716 func main() {
717         bout = bufio.NewWriter(os.Stdout)
718         varTests()
719         constTests()
720
721         fmt.Fprintf(bout, "func main() {\n")
722         for i := 0; i < ntest; i++ {
723                 fmt.Fprintf(bout, "\ttest%v();\n", i)
724         }
725         fmt.Fprintf(bout, "\tif !ok { os.Exit(1) }\n")
726         fmt.Fprintf(bout, "}\n")
727         bout.Flush()
728 }