summaryrefslogtreecommitdiffstats
path: root/test/fixedbugs/issue9604b.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/fixedbugs/issue9604b.go')
-rw-r--r--test/fixedbugs/issue9604b.go180
1 files changed, 180 insertions, 0 deletions
diff --git a/test/fixedbugs/issue9604b.go b/test/fixedbugs/issue9604b.go
new file mode 100644
index 0000000..d32116b
--- /dev/null
+++ b/test/fixedbugs/issue9604b.go
@@ -0,0 +1,180 @@
+// 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
+// +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("}")
+}