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