Source file test/64bit.go

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

View as plain text