"Fossies" - the Fresh Open Source Software Archive

Member "go/test/64bit.go" (26 Apr 2023, 25425 Bytes) of package /linux/misc/go1.20.4.src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    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 }