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
13package main
14
15import (
16	"bufio"
17	"fmt"
18	"os"
19)
20
21var 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
27type Uint64 struct {
28	hi	uint32
29	lo	uint32
30}
31
32type Int64 struct {
33	hi	int32
34	lo	uint32
35}
36
37func (a Uint64) Int64() (c Int64) {
38	c.hi = int32(a.hi)
39	c.lo = a.lo
40	return
41}
42
43func (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
57func (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
72func (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
87func (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
94func (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
101func (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
110func (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
119func (a Uint64) Neg() (c Uint64) {
120	var zero Uint64
121	return zero.Minus(a)
122}
123
124func (a Uint64) Com() (c Uint64) {
125	c.hi = ^a.hi
126	c.lo = ^a.lo
127	return
128}
129
130func (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
148func (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
158func (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
167func (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
184func (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
190func (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
196func (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
202func (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
208func (a Uint64) String() string	{ return fmt.Sprintf("%#x%08x", a.hi, a.lo) }
209
210func (a Int64) Uint64() (c Uint64) {
211	c.hi = uint32(a.hi)
212	c.lo = a.lo
213	return
214}
215
216func (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
233func (a Int64) LeftShift(b uint) (c Int64)	{ return a.Uint64().LeftShift(b).Int64() }
234
235func (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
250func (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
257func (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
264func (a Int64) Plus(b Int64) (c Int64)	{ return a.Uint64().Plus(b.Uint64()).Int64() }
265
266func (a Int64) Minus(b Int64) (c Int64)	{ return a.Uint64().Minus(b.Uint64()).Int64() }
267
268func (a Int64) Neg() (c Int64)	{ return a.Uint64().Neg().Int64() }
269
270func (a Int64) Com() (c Int64)	{ return a.Uint64().Com().Int64() }
271
272func (a Int64) Times(b Int64) (c Int64)	{ return a.Uint64().Times(b.Uint64()).Int64() }
273
274func (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
302func (a Int64) And(b Int64) (c Int64)	{ return a.Uint64().And(b.Uint64()).Int64() }
303
304func (a Int64) AndNot(b Int64) (c Int64)	{ return a.Uint64().AndNot(b.Uint64()).Int64() }
305
306func (a Int64) Or(b Int64) (c Int64)	{ return a.Uint64().Or(b.Uint64()).Int64() }
307
308func (a Int64) Xor(b Int64) (c Int64)	{ return a.Uint64().Xor(b.Uint64()).Int64() }
309
310func (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
317var 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
354var 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
379var 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
404var 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
409const 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
507func 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
563const 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
580const 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
597const 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
610const 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
622const 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
634func 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
716func 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}
729