Source file test/fixedbugs/issue9604b.go

     1  // runoutput
     2  
     3  // Copyright 2015 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  // terribly slow on wasm
     8  //go:build !wasm
     9  
    10  package main
    11  
    12  import (
    13  	"fmt"
    14  	"math/big"
    15  	"unsafe"
    16  )
    17  
    18  var one = big.NewInt(1)
    19  
    20  type _type struct {
    21  	name   string
    22  	bits   uint
    23  	signed bool
    24  }
    25  
    26  // testvalues returns a list of all test values for this type.
    27  func (t *_type) testvalues() []*big.Int {
    28  	var a []*big.Int
    29  
    30  	a = append(a, big.NewInt(0))
    31  	a = append(a, big.NewInt(1))
    32  	a = append(a, big.NewInt(2))
    33  	if t.signed {
    34  		a = append(a, big.NewInt(-1))
    35  		a = append(a, big.NewInt(-2))
    36  		r := big.NewInt(1)
    37  		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(1)))
    38  		r = big.NewInt(1)
    39  		a = append(a, r.Lsh(r, t.bits-1).Sub(r, big.NewInt(2)))
    40  		r = big.NewInt(1)
    41  		a = append(a, r.Lsh(r, t.bits-1).Neg(r))
    42  		r = big.NewInt(1)
    43  		a = append(a, r.Lsh(r, t.bits-1).Neg(r).Add(r, big.NewInt(1)))
    44  	} else {
    45  		r := big.NewInt(1)
    46  		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(1)))
    47  		r = big.NewInt(1)
    48  		a = append(a, r.Lsh(r, t.bits).Sub(r, big.NewInt(2)))
    49  	}
    50  	return a
    51  }
    52  
    53  // trunc truncates a value to the range of the given type.
    54  func (t *_type) trunc(x *big.Int) *big.Int {
    55  	r := new(big.Int)
    56  	m := new(big.Int)
    57  	m.Lsh(one, t.bits)
    58  	m.Sub(m, one)
    59  	r.And(x, m)
    60  	if t.signed && r.Bit(int(t.bits)-1) == 1 {
    61  		m.Neg(one)
    62  		m.Lsh(m, t.bits)
    63  		r.Or(r, m)
    64  	}
    65  	return r
    66  }
    67  
    68  var types = []_type{
    69  	_type{"byte", 8, false},
    70  	_type{"int8", 8, true},
    71  	_type{"uint8", 8, false},
    72  	_type{"rune", 32, true},
    73  	_type{"int16", 16, true},
    74  	_type{"uint16", 16, false},
    75  	_type{"int32", 32, true},
    76  	_type{"uint32", 32, false},
    77  	_type{"int64", 64, true},
    78  	_type{"uint64", 64, false},
    79  	_type{"int", 8 * uint(unsafe.Sizeof(int(0))), true},
    80  	_type{"uint", 8 * uint(unsafe.Sizeof(uint(0))), false},
    81  	_type{"uintptr", 8 * uint(unsafe.Sizeof((*byte)(nil))), false},
    82  }
    83  
    84  type binop struct {
    85  	name string
    86  	eval func(x, y *big.Int) *big.Int
    87  }
    88  
    89  var binops = []binop{
    90  	binop{"+", func(x, y *big.Int) *big.Int { return new(big.Int).Add(x, y) }},
    91  	binop{"-", func(x, y *big.Int) *big.Int { return new(big.Int).Sub(x, y) }},
    92  	binop{"*", func(x, y *big.Int) *big.Int { return new(big.Int).Mul(x, y) }},
    93  	binop{"/", func(x, y *big.Int) *big.Int { return new(big.Int).Quo(x, y) }},
    94  	binop{"%", func(x, y *big.Int) *big.Int { return new(big.Int).Rem(x, y) }},
    95  	binop{"&", func(x, y *big.Int) *big.Int { return new(big.Int).And(x, y) }},
    96  	binop{"|", func(x, y *big.Int) *big.Int { return new(big.Int).Or(x, y) }},
    97  	binop{"^", func(x, y *big.Int) *big.Int { return new(big.Int).Xor(x, y) }},
    98  	binop{"&^", func(x, y *big.Int) *big.Int { return new(big.Int).AndNot(x, y) }},
    99  }
   100  
   101  type unop struct {
   102  	name string
   103  	eval func(x *big.Int) *big.Int
   104  }
   105  
   106  var unops = []unop{
   107  	unop{"+", func(x *big.Int) *big.Int { return new(big.Int).Set(x) }},
   108  	unop{"-", func(x *big.Int) *big.Int { return new(big.Int).Neg(x) }},
   109  	unop{"^", func(x *big.Int) *big.Int { return new(big.Int).Not(x) }},
   110  }
   111  
   112  type shiftop struct {
   113  	name string
   114  	eval func(x *big.Int, i uint) *big.Int
   115  }
   116  
   117  var shiftops = []shiftop{
   118  	shiftop{"<<", func(x *big.Int, i uint) *big.Int { return new(big.Int).Lsh(x, i) }},
   119  	shiftop{">>", func(x *big.Int, i uint) *big.Int { return new(big.Int).Rsh(x, i) }},
   120  }
   121  
   122  // valname returns the name of n as can be used as part of a variable name.
   123  func valname(n *big.Int) string {
   124  	s := fmt.Sprintf("%d", n)
   125  	if s[0] == '-' {
   126  		s = "neg" + s[1:]
   127  	}
   128  	return s
   129  }
   130  
   131  func main() {
   132  	fmt.Println("package main")
   133  
   134  	// We make variables to hold all the different values we'd like to use.
   135  	// We use global variables to prevent any constant folding.
   136  	for _, t := range types {
   137  		for _, n := range t.testvalues() {
   138  			fmt.Printf("var %s_%s %s = %d\n", t.name, valname(n), t.name, n)
   139  		}
   140  	}
   141  
   142  	fmt.Println("func main() {")
   143  
   144  	for _, t := range types {
   145  		// test binary ops
   146  		for _, op := range binops {
   147  			for _, x := range t.testvalues() {
   148  				for _, y := range t.testvalues() {
   149  					if (op.name == "/" || op.name == "%") && y.Sign() == 0 {
   150  						continue
   151  					}
   152  					r := t.trunc(op.eval(x, y))
   153  					eqn := fmt.Sprintf("%s_%s %s %s_%s != %d", t.name, valname(x), op.name, t.name, valname(y), r)
   154  					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
   155  				}
   156  			}
   157  		}
   158  		// test unary ops
   159  		for _, op := range unops {
   160  			for _, x := range t.testvalues() {
   161  				r := t.trunc(op.eval(x))
   162  				eqn := fmt.Sprintf("%s %s_%s != %d", op.name, t.name, valname(x), r)
   163  				fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
   164  			}
   165  		}
   166  		// test shifts
   167  		for _, op := range shiftops {
   168  			for _, x := range t.testvalues() {
   169  
   170  				for _, i := range []uint{0, 1, t.bits - 2, t.bits - 1, t.bits, t.bits + 1} {
   171  					r := t.trunc(op.eval(x, i))
   172  					eqn := fmt.Sprintf("%s_%s %s %d != %d", t.name, valname(x), op.name, i, r)
   173  					fmt.Printf("\tif %s { println(\"bad: %s\") }\n", eqn, eqn)
   174  				}
   175  			}
   176  		}
   177  	}
   178  
   179  	fmt.Println("}")
   180  }
   181  

View as plain text