| // runoutput | 
 |  | 
 | // Copyright 2015 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | // terribly slow on wasm | 
 | //go:build !wasm | 
 |  | 
 | package main | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 | 	"math/big" | 
 | 	"unsafe" | 
 | ) | 
 |  | 
 | var one = big.NewInt(1) | 
 |  | 
 | type _type struct { | 
 | 	name   string | 
 | 	bits   uint | 
 | 	signed bool | 
 | } | 
 |  | 
 | // testvalues returns a list of all test values for this type. | 
 | func (t *_type) testvalues() []*big.Int { | 
 | 	var a []*big.Int | 
 |  | 
 | 	a = append(a, big.NewInt(0)) | 
 | 	a = append(a, big.NewInt(1)) | 
 | 	a = append(a, big.NewInt(2)) | 
 | 	if t.signed { | 
 | 		a = append(a, big.NewInt(-1)) | 
 | 		a = append(a, big.NewInt(-2)) | 
 | 		r := big.NewInt(1) | 
 | 		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(1))) | 
 | 		r = big.NewInt(1) | 
 | 		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(2))) | 
 | 		r = big.NewInt(1) | 
 | 		a = append(a, r.Lsh(r, t.bits-1).Neg(r)) | 
 | 		r = big.NewInt(1) | 
 | 		a = append(a, r.Lsh(r, t.bits-1).Neg(r).Add(r, big.NewInt(1))) | 
 | 	} else { | 
 | 		r := big.NewInt(1) | 
 | 		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(1))) | 
 | 		r = big.NewInt(1) | 
 | 		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(2))) | 
 | 	} | 
 | 	return a | 
 | } | 
 |  | 
 | // trunc truncates a value to the range of the given type. | 
 | func (t *_type) trunc(x *big.Int) *big.Int { | 
 | 	r := new(big.Int) | 
 | 	m := new(big.Int) | 
 | 	m.Lsh(one, t.bits) | 
 | 	m.Sub(m, one) | 
 | 	r.And(x, m) | 
 | 	if t.signed && r.Bit(int(t.bits)-1) == 1 { | 
 | 		m.Neg(one) | 
 | 		m.Lsh(m, t.bits) | 
 | 		r.Or(r, m) | 
 | 	} | 
 | 	return r | 
 | } | 
 |  | 
 | var types = []_type{ | 
 | 	_type{"byte", 8, false}, | 
 | 	_type{"int8", 8, true}, | 
 | 	_type{"uint8", 8, false}, | 
 | 	_type{"rune", 32, true}, | 
 | 	_type{"int16", 16, true}, | 
 | 	_type{"uint16", 16, false}, | 
 | 	_type{"int32", 32, true}, | 
 | 	_type{"uint32", 32, false}, | 
 | 	_type{"int64", 64, true}, | 
 | 	_type{"uint64", 64, false}, | 
 | 	_type{"int", 8 * uint(unsafe.Sizeof(int(0))), true}, | 
 | 	_type{"uint", 8 * uint(unsafe.Sizeof(uint(0))), false}, | 
 | 	_type{"uintptr", 8 * uint(unsafe.Sizeof((*byte)(nil))), false}, | 
 | } | 
 |  | 
 | type binop struct { | 
 | 	name string | 
 | 	eval func(x, y *big.Int) *big.Int | 
 | } | 
 |  | 
 | var binops = []binop{ | 
 | 	binop{"+", func(x, y *big.Int) *big.Int { return new(big.Int).Add(x, y) }}, | 
 | 	binop{"-", func(x, y *big.Int) *big.Int { return new(big.Int).Sub(x, y) }}, | 
 | 	binop{"*", func(x, y *big.Int) *big.Int { return new(big.Int).Mul(x, y) }}, | 
 | 	binop{"/", func(x, y *big.Int) *big.Int { return new(big.Int).Quo(x, y) }}, | 
 | 	binop{"%", func(x, y *big.Int) *big.Int { return new(big.Int).Rem(x, y) }}, | 
 | 	binop{"&", func(x, y *big.Int) *big.Int { return new(big.Int).And(x, y) }}, | 
 | 	binop{"|", func(x, y *big.Int) *big.Int { return new(big.Int).Or(x, y) }}, | 
 | 	binop{"^", func(x, y *big.Int) *big.Int { return new(big.Int).Xor(x, y) }}, | 
 | 	binop{"&^", func(x, y *big.Int) *big.Int { return new(big.Int).AndNot(x, y) }}, | 
 | } | 
 |  | 
 | type unop struct { | 
 | 	name string | 
 | 	eval func(x *big.Int) *big.Int | 
 | } | 
 |  | 
 | var unops = []unop{ | 
 | 	unop{"+", func(x *big.Int) *big.Int { return new(big.Int).Set(x) }}, | 
 | 	unop{"-", func(x *big.Int) *big.Int { return new(big.Int).Neg(x) }}, | 
 | 	unop{"^", func(x *big.Int) *big.Int { return new(big.Int).Not(x) }}, | 
 | } | 
 |  | 
 | type shiftop struct { | 
 | 	name string | 
 | 	eval func(x *big.Int, i uint) *big.Int | 
 | } | 
 |  | 
 | var shiftops = []shiftop{ | 
 | 	shiftop{"<<", func(x *big.Int, i uint) *big.Int { return new(big.Int).Lsh(x, i) }}, | 
 | 	shiftop{">>", func(x *big.Int, i uint) *big.Int { return new(big.Int).Rsh(x, i) }}, | 
 | } | 
 |  | 
 | // valname returns the name of n as can be used as part of a variable name. | 
 | func valname(n *big.Int) string { | 
 | 	s := fmt.Sprintf("%d", n) | 
 | 	if s[0] == '-' { | 
 | 		s = "neg" + s[1:] | 
 | 	} | 
 | 	return s | 
 | } | 
 |  | 
 | func main() { | 
 | 	fmt.Println("package main") | 
 |  | 
 | 	// We make variables to hold all the different values we'd like to use. | 
 | 	// We use global variables to prevent any constant folding. | 
 | 	for _, t := range types { | 
 | 		for _, n := range t.testvalues() { | 
 | 			fmt.Printf("var %s_%s %s = %d\n", t.name, valname(n), t.name, n) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	fmt.Println("func main() {") | 
 |  | 
 | 	for _, t := range types { | 
 | 		// test binary ops | 
 | 		for _, op := range binops { | 
 | 			for _, x := range t.testvalues() { | 
 | 				for _, y := range t.testvalues() { | 
 | 					if (op.name == "/" || op.name == "%") && y.Sign() == 0 { | 
 | 						continue | 
 | 					} | 
 | 					r := t.trunc(op.eval(x, y)) | 
 | 					eqn := fmt.Sprintf("%s_%s %s %s_%s != %d", t.name, valname(x), op.name, t.name, valname(y), r) | 
 | 					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn) | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 		// test unary ops | 
 | 		for _, op := range unops { | 
 | 			for _, x := range t.testvalues() { | 
 | 				r := t.trunc(op.eval(x)) | 
 | 				eqn := fmt.Sprintf("%s %s_%s != %d", op.name, t.name, valname(x), r) | 
 | 				fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn) | 
 | 			} | 
 | 		} | 
 | 		// test shifts | 
 | 		for _, op := range shiftops { | 
 | 			for _, x := range t.testvalues() { | 
 |  | 
 | 				for _, i := range []uint{0, 1, t.bits - 2, t.bits - 1, t.bits, t.bits + 1} { | 
 | 					r := t.trunc(op.eval(x, i)) | 
 | 					eqn := fmt.Sprintf("%s_%s %s %d != %d", t.name, valname(x), op.name, i, r) | 
 | 					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn) | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	fmt.Println("}") | 
 | } |