github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/test/64bit.go (about) 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 }