github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/stdlibs/math/bits/bits_test.gno (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bits 6 7 import ( 8 "testing" 9 ) 10 11 func TestLeadingZeros(t *testing.T) { 12 for i := 0; i < 256; i++ { 13 nlz := tab[i].nlz 14 for k := 0; k < 64-8; k++ { 15 x := uint64(i) << uint(k) 16 if x <= 1<<8-1 { 17 got := LeadingZeros8(uint8(x)) 18 want := nlz - k + (8 - 8) 19 if x == 0 { 20 want = 8 21 } 22 if got != want { 23 t.Fatalf("LeadingZeros8(%#02x) == %d; want %d", x, got, want) 24 } 25 } 26 27 if x <= 1<<16-1 { 28 got := LeadingZeros16(uint16(x)) 29 want := nlz - k + (16 - 8) 30 if x == 0 { 31 want = 16 32 } 33 if got != want { 34 t.Fatalf("LeadingZeros16(%#04x) == %d; want %d", x, got, want) 35 } 36 } 37 38 if x <= 1<<32-1 { 39 got := LeadingZeros32(uint32(x)) 40 want := nlz - k + (32 - 8) 41 if x == 0 { 42 want = 32 43 } 44 if got != want { 45 t.Fatalf("LeadingZeros32(%#08x) == %d; want %d", x, got, want) 46 } 47 if UintSize == 32 { 48 got = LeadingZeros(uint(x)) 49 if got != want { 50 t.Fatalf("LeadingZeros(%#08x) == %d; want %d", x, got, want) 51 } 52 } 53 } 54 55 if x <= 1<<64-1 { 56 got := LeadingZeros64(uint64(x)) 57 want := nlz - k + (64 - 8) 58 if x == 0 { 59 want = 64 60 } 61 if got != want { 62 t.Fatalf("LeadingZeros64(%#016x) == %d; want %d", x, got, want) 63 } 64 if UintSize == 64 { 65 got = LeadingZeros(uint(x)) 66 if got != want { 67 t.Fatalf("LeadingZeros(%#016x) == %d; want %d", x, got, want) 68 } 69 } 70 } 71 } 72 } 73 } 74 75 // Exported (global) variable serving as input for some 76 // of the benchmarks to ensure side-effect free calls 77 // are not optimized away. 78 var Input uint64 = DeBruijn64 79 80 // Exported (global) variable to store function results 81 // during benchmarking to ensure side-effect free calls 82 // are not optimized away. 83 var Output int 84 85 func BenchmarkLeadingZeros(b *testing.B) { 86 var s int 87 for i := 0; i < b.N; i++ { 88 s += LeadingZeros(uint(Input) >> (uint(i) % UintSize)) 89 } 90 Output = s 91 } 92 93 func BenchmarkLeadingZeros8(b *testing.B) { 94 var s int 95 for i := 0; i < b.N; i++ { 96 s += LeadingZeros8(uint8(Input) >> (uint(i) % 8)) 97 } 98 Output = s 99 } 100 101 func BenchmarkLeadingZeros16(b *testing.B) { 102 var s int 103 for i := 0; i < b.N; i++ { 104 s += LeadingZeros16(uint16(Input) >> (uint(i) % 16)) 105 } 106 Output = s 107 } 108 109 func BenchmarkLeadingZeros32(b *testing.B) { 110 var s int 111 for i := 0; i < b.N; i++ { 112 s += LeadingZeros32(uint32(Input) >> (uint(i) % 32)) 113 } 114 Output = s 115 } 116 117 func BenchmarkLeadingZeros64(b *testing.B) { 118 var s int 119 for i := 0; i < b.N; i++ { 120 s += LeadingZeros64(uint64(Input) >> (uint(i) % 64)) 121 } 122 Output = s 123 } 124 125 func TestTrailingZeros(t *testing.T) { 126 for i := 0; i < 256; i++ { 127 ntz := tab[i].ntz 128 for k := 0; k < 64-8; k++ { 129 x := uint64(i) << uint(k) 130 want := ntz + k 131 if x <= 1<<8-1 { 132 got := TrailingZeros8(uint8(x)) 133 if x == 0 { 134 want = 8 135 } 136 if got != want { 137 t.Fatalf("TrailingZeros8(%#02x) == %d; want %d", x, got, want) 138 } 139 } 140 141 if x <= 1<<16-1 { 142 got := TrailingZeros16(uint16(x)) 143 if x == 0 { 144 want = 16 145 } 146 if got != want { 147 t.Fatalf("TrailingZeros16(%#04x) == %d; want %d", x, got, want) 148 } 149 } 150 151 if x <= 1<<32-1 { 152 got := TrailingZeros32(uint32(x)) 153 if x == 0 { 154 want = 32 155 } 156 if got != want { 157 t.Fatalf("TrailingZeros32(%#08x) == %d; want %d", x, got, want) 158 } 159 if UintSize == 32 { 160 got = TrailingZeros(uint(x)) 161 if got != want { 162 t.Fatalf("TrailingZeros(%#08x) == %d; want %d", x, got, want) 163 } 164 } 165 } 166 167 if x <= 1<<64-1 { 168 got := TrailingZeros64(uint64(x)) 169 if x == 0 { 170 want = 64 171 } 172 if got != want { 173 t.Fatalf("TrailingZeros64(%#016x) == %d; want %d", x, got, want) 174 } 175 if UintSize == 64 { 176 got = TrailingZeros(uint(x)) 177 if got != want { 178 t.Fatalf("TrailingZeros(%#016x) == %d; want %d", x, got, want) 179 } 180 } 181 } 182 } 183 } 184 } 185 186 func BenchmarkTrailingZeros(b *testing.B) { 187 var s int 188 for i := 0; i < b.N; i++ { 189 s += TrailingZeros(uint(Input) << (uint(i) % UintSize)) 190 } 191 Output = s 192 } 193 194 func BenchmarkTrailingZeros8(b *testing.B) { 195 var s int 196 for i := 0; i < b.N; i++ { 197 s += TrailingZeros8(uint8(Input) << (uint(i) % 8)) 198 } 199 Output = s 200 } 201 202 func BenchmarkTrailingZeros16(b *testing.B) { 203 var s int 204 for i := 0; i < b.N; i++ { 205 s += TrailingZeros16(uint16(Input) << (uint(i) % 16)) 206 } 207 Output = s 208 } 209 210 func BenchmarkTrailingZeros32(b *testing.B) { 211 var s int 212 for i := 0; i < b.N; i++ { 213 s += TrailingZeros32(uint32(Input) << (uint(i) % 32)) 214 } 215 Output = s 216 } 217 218 func BenchmarkTrailingZeros64(b *testing.B) { 219 var s int 220 for i := 0; i < b.N; i++ { 221 s += TrailingZeros64(uint64(Input) << (uint(i) % 64)) 222 } 223 Output = s 224 } 225 226 func TestOnesCount(t *testing.T) { 227 var x uint64 228 for i := 0; i <= 64; i++ { 229 testOnesCount(t, x, i) 230 x = x<<1 | 1 231 } 232 233 for i := 64; i >= 0; i-- { 234 testOnesCount(t, x, i) 235 x = x << 1 236 } 237 238 for i := 0; i < 256; i++ { 239 for k := 0; k < 64-8; k++ { 240 testOnesCount(t, uint64(i)<<uint(k), tab[i].pop) 241 } 242 } 243 } 244 245 func testOnesCount(t *testing.T, x uint64, want int) { 246 if x <= 1<<8-1 { 247 got := OnesCount8(uint8(x)) 248 if got != want { 249 t.Fatalf("OnesCount8(%#02x) == %d; want %d", uint8(x), got, want) 250 } 251 } 252 253 if x <= 1<<16-1 { 254 got := OnesCount16(uint16(x)) 255 if got != want { 256 t.Fatalf("OnesCount16(%#04x) == %d; want %d", uint16(x), got, want) 257 } 258 } 259 260 if x <= 1<<32-1 { 261 got := OnesCount32(uint32(x)) 262 if got != want { 263 t.Fatalf("OnesCount32(%#08x) == %d; want %d", uint32(x), got, want) 264 } 265 if UintSize == 32 { 266 got = OnesCount(uint(x)) 267 if got != want { 268 t.Fatalf("OnesCount(%#08x) == %d; want %d", uint32(x), got, want) 269 } 270 } 271 } 272 273 if x <= 1<<64-1 { 274 got := OnesCount64(uint64(x)) 275 if got != want { 276 t.Fatalf("OnesCount64(%#016x) == %d; want %d", x, got, want) 277 } 278 if UintSize == 64 { 279 got = OnesCount(uint(x)) 280 if got != want { 281 t.Fatalf("OnesCount(%#016x) == %d; want %d", x, got, want) 282 } 283 } 284 } 285 } 286 287 func BenchmarkOnesCount(b *testing.B) { 288 var s int 289 for i := 0; i < b.N; i++ { 290 s += OnesCount(uint(Input)) 291 } 292 Output = s 293 } 294 295 func BenchmarkOnesCount8(b *testing.B) { 296 var s int 297 for i := 0; i < b.N; i++ { 298 s += OnesCount8(uint8(Input)) 299 } 300 Output = s 301 } 302 303 func BenchmarkOnesCount16(b *testing.B) { 304 var s int 305 for i := 0; i < b.N; i++ { 306 s += OnesCount16(uint16(Input)) 307 } 308 Output = s 309 } 310 311 func BenchmarkOnesCount32(b *testing.B) { 312 var s int 313 for i := 0; i < b.N; i++ { 314 s += OnesCount32(uint32(Input)) 315 } 316 Output = s 317 } 318 319 func BenchmarkOnesCount64(b *testing.B) { 320 var s int 321 for i := 0; i < b.N; i++ { 322 s += OnesCount64(uint64(Input)) 323 } 324 Output = s 325 } 326 327 func TestRotateLeft(t *testing.T) { 328 var m uint64 = DeBruijn64 329 330 for k := uint(0); k < 128; k++ { 331 x8 := uint8(m) 332 got8 := RotateLeft8(x8, int(k)) 333 want8 := x8<<(k&0x7) | x8>>(8-k&0x7) 334 if got8 != want8 { 335 t.Fatalf("RotateLeft8(%#02x, %d) == %#02x; want %#02x", x8, k, got8, want8) 336 } 337 got8 = RotateLeft8(want8, -int(k)) 338 if got8 != x8 { 339 t.Fatalf("RotateLeft8(%#02x, -%d) == %#02x; want %#02x", want8, k, got8, x8) 340 } 341 342 x16 := uint16(m) 343 got16 := RotateLeft16(x16, int(k)) 344 want16 := x16<<(k&0xf) | x16>>(16-k&0xf) 345 if got16 != want16 { 346 t.Fatalf("RotateLeft16(%#04x, %d) == %#04x; want %#04x", x16, k, got16, want16) 347 } 348 got16 = RotateLeft16(want16, -int(k)) 349 if got16 != x16 { 350 t.Fatalf("RotateLeft16(%#04x, -%d) == %#04x; want %#04x", want16, k, got16, x16) 351 } 352 353 x32 := uint32(m) 354 got32 := RotateLeft32(x32, int(k)) 355 want32 := x32<<(k&0x1f) | x32>>(32-k&0x1f) 356 if got32 != want32 { 357 t.Fatalf("RotateLeft32(%#08x, %d) == %#08x; want %#08x", x32, k, got32, want32) 358 } 359 got32 = RotateLeft32(want32, -int(k)) 360 if got32 != x32 { 361 t.Fatalf("RotateLeft32(%#08x, -%d) == %#08x; want %#08x", want32, k, got32, x32) 362 } 363 if UintSize == 32 { 364 x := uint(m) 365 got := RotateLeft(x, int(k)) 366 want := x<<(k&0x1f) | x>>(32-k&0x1f) 367 if got != want { 368 t.Fatalf("RotateLeft(%#08x, %d) == %#08x; want %#08x", x, k, got, want) 369 } 370 got = RotateLeft(want, -int(k)) 371 if got != x { 372 t.Fatalf("RotateLeft(%#08x, -%d) == %#08x; want %#08x", want, k, got, x) 373 } 374 } 375 376 x64 := uint64(m) 377 got64 := RotateLeft64(x64, int(k)) 378 want64 := x64<<(k&0x3f) | x64>>(64-k&0x3f) 379 if got64 != want64 { 380 t.Fatalf("RotateLeft64(%#016x, %d) == %#016x; want %#016x", x64, k, got64, want64) 381 } 382 got64 = RotateLeft64(want64, -int(k)) 383 if got64 != x64 { 384 t.Fatalf("RotateLeft64(%#016x, -%d) == %#016x; want %#016x", want64, k, got64, x64) 385 } 386 if UintSize == 64 { 387 x := uint(m) 388 got := RotateLeft(x, int(k)) 389 want := x<<(k&0x3f) | x>>(64-k&0x3f) 390 if got != want { 391 t.Fatalf("RotateLeft(%#016x, %d) == %#016x; want %#016x", x, k, got, want) 392 } 393 got = RotateLeft(want, -int(k)) 394 if got != x { 395 t.Fatalf("RotateLeft(%#08x, -%d) == %#08x; want %#08x", want, k, got, x) 396 } 397 } 398 } 399 } 400 401 func BenchmarkRotateLeft(b *testing.B) { 402 var s uint 403 for i := 0; i < b.N; i++ { 404 s += RotateLeft(uint(Input), i) 405 } 406 Output = int(s) 407 } 408 409 func BenchmarkRotateLeft8(b *testing.B) { 410 var s uint8 411 for i := 0; i < b.N; i++ { 412 s += RotateLeft8(uint8(Input), i) 413 } 414 Output = int(s) 415 } 416 417 func BenchmarkRotateLeft16(b *testing.B) { 418 var s uint16 419 for i := 0; i < b.N; i++ { 420 s += RotateLeft16(uint16(Input), i) 421 } 422 Output = int(s) 423 } 424 425 func BenchmarkRotateLeft32(b *testing.B) { 426 var s uint32 427 for i := 0; i < b.N; i++ { 428 s += RotateLeft32(uint32(Input), i) 429 } 430 Output = int(s) 431 } 432 433 func BenchmarkRotateLeft64(b *testing.B) { 434 var s uint64 435 for i := 0; i < b.N; i++ { 436 s += RotateLeft64(uint64(Input), i) 437 } 438 Output = int(s) 439 } 440 441 func TestReverse(t *testing.T) { 442 // test each bit 443 for i := uint(0); i < 64; i++ { 444 testReverse(t, uint64(1)<<i, uint64(1)<<(63-i)) 445 } 446 447 // test a few patterns 448 for _, test := range []struct { 449 x, r uint64 450 }{ 451 {0, 0}, 452 {0x1, 0x8 << 60}, 453 {0x2, 0x4 << 60}, 454 {0x3, 0xc << 60}, 455 {0x4, 0x2 << 60}, 456 {0x5, 0xa << 60}, 457 {0x6, 0x6 << 60}, 458 {0x7, 0xe << 60}, 459 {0x8, 0x1 << 60}, 460 {0x9, 0x9 << 60}, 461 {0xa, 0x5 << 60}, 462 {0xb, 0xd << 60}, 463 {0xc, 0x3 << 60}, 464 {0xd, 0xb << 60}, 465 {0xe, 0x7 << 60}, 466 {0xf, 0xf << 60}, 467 {0x5686487, 0xe12616a000000000}, 468 {0x0123456789abcdef, 0xf7b3d591e6a2c480}, 469 } { 470 testReverse(t, test.x, test.r) 471 testReverse(t, test.r, test.x) 472 } 473 } 474 475 func testReverse(t *testing.T, x64, want64 uint64) { 476 x8 := uint8(x64) 477 got8 := Reverse8(x8) 478 want8 := uint8(want64 >> (64 - 8)) 479 if got8 != want8 { 480 t.Fatalf("Reverse8(%#02x) == %#02x; want %#02x", x8, got8, want8) 481 } 482 483 x16 := uint16(x64) 484 got16 := Reverse16(x16) 485 want16 := uint16(want64 >> (64 - 16)) 486 if got16 != want16 { 487 t.Fatalf("Reverse16(%#04x) == %#04x; want %#04x", x16, got16, want16) 488 } 489 490 x32 := uint32(x64) 491 got32 := Reverse32(x32) 492 want32 := uint32(want64 >> (64 - 32)) 493 if got32 != want32 { 494 t.Fatalf("Reverse32(%#08x) == %#08x; want %#08x", x32, got32, want32) 495 } 496 if UintSize == 32 { 497 x := uint(x32) 498 got := Reverse(x) 499 want := uint(want32) 500 if got != want { 501 t.Fatalf("Reverse(%#08x) == %#08x; want %#08x", x, got, want) 502 } 503 } 504 505 got64 := Reverse64(x64) 506 if got64 != want64 { 507 t.Fatalf("Reverse64(%#016x) == %#016x; want %#016x", x64, got64, want64) 508 } 509 if UintSize == 64 { 510 x := uint(x64) 511 got := Reverse(x) 512 want := uint(want64) 513 if got != want { 514 t.Fatalf("Reverse(%#08x) == %#016x; want %#016x", x, got, want) 515 } 516 } 517 } 518 519 func BenchmarkReverse(b *testing.B) { 520 var s uint 521 for i := 0; i < b.N; i++ { 522 s += Reverse(uint(i)) 523 } 524 Output = int(s) 525 } 526 527 func BenchmarkReverse8(b *testing.B) { 528 var s uint8 529 for i := 0; i < b.N; i++ { 530 s += Reverse8(uint8(i)) 531 } 532 Output = int(s) 533 } 534 535 func BenchmarkReverse16(b *testing.B) { 536 var s uint16 537 for i := 0; i < b.N; i++ { 538 s += Reverse16(uint16(i)) 539 } 540 Output = int(s) 541 } 542 543 func BenchmarkReverse32(b *testing.B) { 544 var s uint32 545 for i := 0; i < b.N; i++ { 546 s += Reverse32(uint32(i)) 547 } 548 Output = int(s) 549 } 550 551 func BenchmarkReverse64(b *testing.B) { 552 var s uint64 553 for i := 0; i < b.N; i++ { 554 s += Reverse64(uint64(i)) 555 } 556 Output = int(s) 557 } 558 559 func TestReverseBytes(t *testing.T) { 560 for _, test := range []struct { 561 x, r uint64 562 }{ 563 {0, 0}, 564 {0x01, 0x01 << 56}, 565 {0x0123, 0x2301 << 48}, 566 {0x012345, 0x452301 << 40}, 567 {0x01234567, 0x67452301 << 32}, 568 {0x0123456789, 0x8967452301 << 24}, 569 {0x0123456789ab, 0xab8967452301 << 16}, 570 {0x0123456789abcd, 0xcdab8967452301 << 8}, 571 {0x0123456789abcdef, 0xefcdab8967452301 << 0}, 572 } { 573 testReverseBytes(t, test.x, test.r) 574 testReverseBytes(t, test.r, test.x) 575 } 576 } 577 578 func testReverseBytes(t *testing.T, x64, want64 uint64) { 579 x16 := uint16(x64) 580 got16 := ReverseBytes16(x16) 581 want16 := uint16(want64 >> (64 - 16)) 582 if got16 != want16 { 583 t.Fatalf("ReverseBytes16(%#04x) == %#04x; want %#04x", x16, got16, want16) 584 } 585 586 x32 := uint32(x64) 587 got32 := ReverseBytes32(x32) 588 want32 := uint32(want64 >> (64 - 32)) 589 if got32 != want32 { 590 t.Fatalf("ReverseBytes32(%#08x) == %#08x; want %#08x", x32, got32, want32) 591 } 592 if UintSize == 32 { 593 x := uint(x32) 594 got := ReverseBytes(x) 595 want := uint(want32) 596 if got != want { 597 t.Fatalf("ReverseBytes(%#08x) == %#08x; want %#08x", x, got, want) 598 } 599 } 600 601 got64 := ReverseBytes64(x64) 602 if got64 != want64 { 603 t.Fatalf("ReverseBytes64(%#016x) == %#016x; want %#016x", x64, got64, want64) 604 } 605 if UintSize == 64 { 606 x := uint(x64) 607 got := ReverseBytes(x) 608 want := uint(want64) 609 if got != want { 610 t.Fatalf("ReverseBytes(%#016x) == %#016x; want %#016x", x, got, want) 611 } 612 } 613 } 614 615 func BenchmarkReverseBytes(b *testing.B) { 616 var s uint 617 for i := 0; i < b.N; i++ { 618 s += ReverseBytes(uint(i)) 619 } 620 Output = int(s) 621 } 622 623 func BenchmarkReverseBytes16(b *testing.B) { 624 var s uint16 625 for i := 0; i < b.N; i++ { 626 s += ReverseBytes16(uint16(i)) 627 } 628 Output = int(s) 629 } 630 631 func BenchmarkReverseBytes32(b *testing.B) { 632 var s uint32 633 for i := 0; i < b.N; i++ { 634 s += ReverseBytes32(uint32(i)) 635 } 636 Output = int(s) 637 } 638 639 func BenchmarkReverseBytes64(b *testing.B) { 640 var s uint64 641 for i := 0; i < b.N; i++ { 642 s += ReverseBytes64(uint64(i)) 643 } 644 Output = int(s) 645 } 646 647 func TestLen(t *testing.T) { 648 for i := 0; i < 256; i++ { 649 length := 8 - tab[i].nlz 650 for k := 0; k < 64-8; k++ { 651 x := uint64(i) << uint(k) 652 want := 0 653 if x != 0 { 654 want = length + k 655 } 656 if x <= 1<<8-1 { 657 got := Len8(uint8(x)) 658 if got != want { 659 t.Fatalf("Len8(%#02x) == %d; want %d", x, got, want) 660 } 661 } 662 663 if x <= 1<<16-1 { 664 got := Len16(uint16(x)) 665 if got != want { 666 t.Fatalf("Len16(%#04x) == %d; want %d", x, got, want) 667 } 668 } 669 670 if x <= 1<<32-1 { 671 got := Len32(uint32(x)) 672 if got != want { 673 t.Fatalf("Len32(%#08x) == %d; want %d", x, got, want) 674 } 675 if UintSize == 32 { 676 got := Len(uint(x)) 677 if got != want { 678 t.Fatalf("Len(%#08x) == %d; want %d", x, got, want) 679 } 680 } 681 } 682 683 if x <= 1<<64-1 { 684 got := Len64(uint64(x)) 685 if got != want { 686 t.Fatalf("Len64(%#016x) == %d; want %d", x, got, want) 687 } 688 if UintSize == 64 { 689 got := Len(uint(x)) 690 if got != want { 691 t.Fatalf("Len(%#016x) == %d; want %d", x, got, want) 692 } 693 } 694 } 695 } 696 } 697 } 698 699 const ( 700 _M = 1<<UintSize - 1 701 _M32 = 1<<32 - 1 702 _M64 = 1<<64 - 1 703 ) 704 705 func TestAddSubUint(t *testing.T) { 706 test := func(msg string, f func(x, y, c uint) (z, cout uint), x, y, c, z, cout uint) { 707 z1, cout1 := f(x, y, c) 708 if z1 != z || cout1 != cout { 709 t.Errorf("%s: got z:cout = %#x:%#x; want %#x:%#x", msg, z1, cout1, z, cout) 710 } 711 } 712 for _, a := range []struct{ x, y, c, z, cout uint }{ 713 {0, 0, 0, 0, 0}, 714 {0, 1, 0, 1, 0}, 715 {0, 0, 1, 1, 0}, 716 {0, 1, 1, 2, 0}, 717 {12345, 67890, 0, 80235, 0}, 718 {12345, 67890, 1, 80236, 0}, 719 {_M, 1, 0, 0, 1}, 720 {_M, 0, 1, 0, 1}, 721 {_M, 1, 1, 1, 1}, 722 {_M, _M, 0, _M - 1, 1}, 723 {_M, _M, 1, _M, 1}, 724 } { 725 test("Add", Add, a.x, a.y, a.c, a.z, a.cout) 726 test("Add symmetric", Add, a.y, a.x, a.c, a.z, a.cout) 727 test("Sub", Sub, a.z, a.x, a.c, a.y, a.cout) 728 test("Sub symmetric", Sub, a.z, a.y, a.c, a.x, a.cout) 729 // The above code can't test intrinsic implementation, because the passed function is not called directly. 730 // The following code uses a closure to test the intrinsic version in case the function is intrinsified. 731 test("Add intrinsic", func(x, y, c uint) (uint, uint) { return Add(x, y, c) }, a.x, a.y, a.c, a.z, a.cout) 732 test("Add intrinsic symmetric", func(x, y, c uint) (uint, uint) { return Add(x, y, c) }, a.y, a.x, a.c, a.z, a.cout) 733 test("Sub intrinsic", func(x, y, c uint) (uint, uint) { return Sub(x, y, c) }, a.z, a.x, a.c, a.y, a.cout) 734 test("Sub intrinsic symmetric", func(x, y, c uint) (uint, uint) { return Sub(x, y, c) }, a.z, a.y, a.c, a.x, a.cout) 735 736 } 737 } 738 739 func TestAddSubUint32(t *testing.T) { 740 test := func(msg string, f func(x, y, c uint32) (z, cout uint32), x, y, c, z, cout uint32) { 741 z1, cout1 := f(x, y, c) 742 if z1 != z || cout1 != cout { 743 t.Errorf("%s: got z:cout = %#x:%#x; want %#x:%#x", msg, z1, cout1, z, cout) 744 } 745 } 746 for _, a := range []struct{ x, y, c, z, cout uint32 }{ 747 {0, 0, 0, 0, 0}, 748 {0, 1, 0, 1, 0}, 749 {0, 0, 1, 1, 0}, 750 {0, 1, 1, 2, 0}, 751 {12345, 67890, 0, 80235, 0}, 752 {12345, 67890, 1, 80236, 0}, 753 {_M32, 1, 0, 0, 1}, 754 {_M32, 0, 1, 0, 1}, 755 {_M32, 1, 1, 1, 1}, 756 {_M32, _M32, 0, _M32 - 1, 1}, 757 {_M32, _M32, 1, _M32, 1}, 758 } { 759 test("Add32", Add32, a.x, a.y, a.c, a.z, a.cout) 760 test("Add32 symmetric", Add32, a.y, a.x, a.c, a.z, a.cout) 761 test("Sub32", Sub32, a.z, a.x, a.c, a.y, a.cout) 762 test("Sub32 symmetric", Sub32, a.z, a.y, a.c, a.x, a.cout) 763 } 764 } 765 766 func TestAddSubUint64(t *testing.T) { 767 test := func(msg string, f func(x, y, c uint64) (z, cout uint64), x, y, c, z, cout uint64) { 768 z1, cout1 := f(x, y, c) 769 if z1 != z || cout1 != cout { 770 t.Errorf("%s: got z:cout = %#x:%#x; want %#x:%#x", msg, z1, cout1, z, cout) 771 } 772 } 773 for _, a := range []struct{ x, y, c, z, cout uint64 }{ 774 {0, 0, 0, 0, 0}, 775 {0, 1, 0, 1, 0}, 776 {0, 0, 1, 1, 0}, 777 {0, 1, 1, 2, 0}, 778 {12345, 67890, 0, 80235, 0}, 779 {12345, 67890, 1, 80236, 0}, 780 {_M64, 1, 0, 0, 1}, 781 {_M64, 0, 1, 0, 1}, 782 {_M64, 1, 1, 1, 1}, 783 {_M64, _M64, 0, _M64 - 1, 1}, 784 {_M64, _M64, 1, _M64, 1}, 785 } { 786 test("Add64", Add64, a.x, a.y, a.c, a.z, a.cout) 787 test("Add64 symmetric", Add64, a.y, a.x, a.c, a.z, a.cout) 788 test("Sub64", Sub64, a.z, a.x, a.c, a.y, a.cout) 789 test("Sub64 symmetric", Sub64, a.z, a.y, a.c, a.x, a.cout) 790 // The above code can't test intrinsic implementation, because the passed function is not called directly. 791 // The following code uses a closure to test the intrinsic version in case the function is intrinsified. 792 test("Add64 intrinsic", func(x, y, c uint64) (uint64, uint64) { return Add64(x, y, c) }, a.x, a.y, a.c, a.z, a.cout) 793 test("Add64 intrinsic symmetric", func(x, y, c uint64) (uint64, uint64) { return Add64(x, y, c) }, a.y, a.x, a.c, a.z, a.cout) 794 test("Sub64 intrinsic", func(x, y, c uint64) (uint64, uint64) { return Sub64(x, y, c) }, a.z, a.x, a.c, a.y, a.cout) 795 test("Sub64 intrinsic symmetric", func(x, y, c uint64) (uint64, uint64) { return Sub64(x, y, c) }, a.z, a.y, a.c, a.x, a.cout) 796 } 797 } 798 799 func TestAdd64OverflowPanic(t *testing.T) { 800 // Test that 64-bit overflow panics fire correctly. 801 // These are designed to improve coverage of compiler intrinsics. 802 tests := []func(uint64, uint64) uint64{ 803 func(a, b uint64) uint64 { 804 x, c := Add64(a, b, 0) 805 if c > 0 { 806 panic("overflow") 807 } 808 return x 809 }, 810 func(a, b uint64) uint64 { 811 x, c := Add64(a, b, 0) 812 if c != 0 { 813 panic("overflow") 814 } 815 return x 816 }, 817 func(a, b uint64) uint64 { 818 x, c := Add64(a, b, 0) 819 if c == 1 { 820 panic("overflow") 821 } 822 return x 823 }, 824 func(a, b uint64) uint64 { 825 x, c := Add64(a, b, 0) 826 if c != 1 { 827 return x 828 } 829 panic("overflow") 830 }, 831 func(a, b uint64) uint64 { 832 x, c := Add64(a, b, 0) 833 if c == 0 { 834 return x 835 } 836 panic("overflow") 837 }, 838 } 839 for _, test := range tests { 840 shouldPanic := func(f func()) { 841 defer func() { 842 if err := recover(); err == nil { 843 t.Fatalf("expected panic") 844 } 845 }() 846 f() 847 } 848 849 // overflow 850 shouldPanic(func() { test(_M64, 1) }) 851 shouldPanic(func() { test(1, _M64) }) 852 shouldPanic(func() { test(_M64, _M64) }) 853 854 // no overflow 855 test(_M64, 0) 856 test(0, 0) 857 test(1, 1) 858 } 859 } 860 861 func TestSub64OverflowPanic(t *testing.T) { 862 // Test that 64-bit overflow panics fire correctly. 863 // These are designed to improve coverage of compiler intrinsics. 864 tests := []func(uint64, uint64) uint64{ 865 func(a, b uint64) uint64 { 866 x, c := Sub64(a, b, 0) 867 if c > 0 { 868 panic("overflow") 869 } 870 return x 871 }, 872 func(a, b uint64) uint64 { 873 x, c := Sub64(a, b, 0) 874 if c != 0 { 875 panic("overflow") 876 } 877 return x 878 }, 879 func(a, b uint64) uint64 { 880 x, c := Sub64(a, b, 0) 881 if c == 1 { 882 panic("overflow") 883 } 884 return x 885 }, 886 func(a, b uint64) uint64 { 887 x, c := Sub64(a, b, 0) 888 if c != 1 { 889 return x 890 } 891 panic("overflow") 892 }, 893 func(a, b uint64) uint64 { 894 x, c := Sub64(a, b, 0) 895 if c == 0 { 896 return x 897 } 898 panic("overflow") 899 }, 900 } 901 for _, test := range tests { 902 shouldPanic := func(f func()) { 903 defer func() { 904 if err := recover(); err == nil { 905 t.Fatalf("expected panic") 906 } 907 }() 908 f() 909 } 910 911 // overflow 912 shouldPanic(func() { test(0, 1) }) 913 shouldPanic(func() { test(1, _M64) }) 914 shouldPanic(func() { test(_M64-1, _M64) }) 915 916 // no overflow 917 test(_M64, 0) 918 test(0, 0) 919 test(1, 1) 920 } 921 } 922 923 func TestMulDiv(t *testing.T) { 924 testMul := func(msg string, f func(x, y uint) (hi, lo uint), x, y, hi, lo uint) { 925 hi1, lo1 := f(x, y) 926 if hi1 != hi || lo1 != lo { 927 t.Errorf("%s: got hi:lo = %#x:%#x; want %#x:%#x", msg, hi1, lo1, hi, lo) 928 } 929 } 930 testDiv := func(msg string, f func(hi, lo, y uint) (q, r uint), hi, lo, y, q, r uint) { 931 q1, r1 := f(hi, lo, y) 932 if q1 != q || r1 != r { 933 t.Errorf("%s: got q:r = %#x:%#x; want %#x:%#x", msg, q1, r1, q, r) 934 } 935 } 936 for _, a := range []struct { 937 x, y uint 938 hi, lo, r uint 939 }{ 940 {1 << (UintSize - 1), 2, 1, 0, 1}, 941 {_M, _M, _M - 1, 1, 42}, 942 } { 943 testMul("Mul", Mul, a.x, a.y, a.hi, a.lo) 944 testMul("Mul symmetric", Mul, a.y, a.x, a.hi, a.lo) 945 testDiv("Div", Div, a.hi, a.lo+a.r, a.y, a.x, a.r) 946 testDiv("Div symmetric", Div, a.hi, a.lo+a.r, a.x, a.y, a.r) 947 // The above code can't test intrinsic implementation, because the passed function is not called directly. 948 // The following code uses a closure to test the intrinsic version in case the function is intrinsified. 949 testMul("Mul intrinsic", func(x, y uint) (uint, uint) { return Mul(x, y) }, a.x, a.y, a.hi, a.lo) 950 testMul("Mul intrinsic symmetric", func(x, y uint) (uint, uint) { return Mul(x, y) }, a.y, a.x, a.hi, a.lo) 951 testDiv("Div intrinsic", func(hi, lo, y uint) (uint, uint) { return Div(hi, lo, y) }, a.hi, a.lo+a.r, a.y, a.x, a.r) 952 testDiv("Div intrinsic symmetric", func(hi, lo, y uint) (uint, uint) { return Div(hi, lo, y) }, a.hi, a.lo+a.r, a.x, a.y, a.r) 953 } 954 } 955 956 func TestMulDiv32(t *testing.T) { 957 testMul := func(msg string, f func(x, y uint32) (hi, lo uint32), x, y, hi, lo uint32) { 958 hi1, lo1 := f(x, y) 959 if hi1 != hi || lo1 != lo { 960 t.Errorf("%s: got hi:lo = %#x:%#x; want %#x:%#x", msg, hi1, lo1, hi, lo) 961 } 962 } 963 testDiv := func(msg string, f func(hi, lo, y uint32) (q, r uint32), hi, lo, y, q, r uint32) { 964 q1, r1 := f(hi, lo, y) 965 if q1 != q || r1 != r { 966 t.Errorf("%s: got q:r = %#x:%#x; want %#x:%#x", msg, q1, r1, q, r) 967 } 968 } 969 for _, a := range []struct { 970 x, y uint32 971 hi, lo, r uint32 972 }{ 973 {1 << 31, 2, 1, 0, 1}, 974 {0xc47dfa8c, 50911, 0x98a4, 0x998587f4, 13}, 975 {_M32, _M32, _M32 - 1, 1, 42}, 976 } { 977 testMul("Mul32", Mul32, a.x, a.y, a.hi, a.lo) 978 testMul("Mul32 symmetric", Mul32, a.y, a.x, a.hi, a.lo) 979 testDiv("Div32", Div32, a.hi, a.lo+a.r, a.y, a.x, a.r) 980 testDiv("Div32 symmetric", Div32, a.hi, a.lo+a.r, a.x, a.y, a.r) 981 } 982 } 983 984 func TestMulDiv64(t *testing.T) { 985 testMul := func(msg string, f func(x, y uint64) (hi, lo uint64), x, y, hi, lo uint64) { 986 hi1, lo1 := f(x, y) 987 if hi1 != hi || lo1 != lo { 988 t.Errorf("%s: got hi:lo = %#x:%#x; want %#x:%#x", msg, hi1, lo1, hi, lo) 989 } 990 } 991 testDiv := func(msg string, f func(hi, lo, y uint64) (q, r uint64), hi, lo, y, q, r uint64) { 992 q1, r1 := f(hi, lo, y) 993 if q1 != q || r1 != r { 994 t.Errorf("%s: got q:r = %#x:%#x; want %#x:%#x", msg, q1, r1, q, r) 995 } 996 } 997 for _, a := range []struct { 998 x, y uint64 999 hi, lo, r uint64 1000 }{ 1001 {1 << 63, 2, 1, 0, 1}, 1002 {0x3626229738a3b9, 0xd8988a9f1cc4a61, 0x2dd0712657fe8, 0x9dd6a3364c358319, 13}, 1003 {_M64, _M64, _M64 - 1, 1, 42}, 1004 } { 1005 testMul("Mul64", Mul64, a.x, a.y, a.hi, a.lo) 1006 testMul("Mul64 symmetric", Mul64, a.y, a.x, a.hi, a.lo) 1007 testDiv("Div64", Div64, a.hi, a.lo+a.r, a.y, a.x, a.r) 1008 testDiv("Div64 symmetric", Div64, a.hi, a.lo+a.r, a.x, a.y, a.r) 1009 // The above code can't test intrinsic implementation, because the passed function is not called directly. 1010 // The following code uses a closure to test the intrinsic version in case the function is intrinsified. 1011 testMul("Mul64 intrinsic", func(x, y uint64) (uint64, uint64) { return Mul64(x, y) }, a.x, a.y, a.hi, a.lo) 1012 testMul("Mul64 intrinsic symmetric", func(x, y uint64) (uint64, uint64) { return Mul64(x, y) }, a.y, a.x, a.hi, a.lo) 1013 testDiv("Div64 intrinsic", func(hi, lo, y uint64) (uint64, uint64) { return Div64(hi, lo, y) }, a.hi, a.lo+a.r, a.y, a.x, a.r) 1014 testDiv("Div64 intrinsic symmetric", func(hi, lo, y uint64) (uint64, uint64) { return Div64(hi, lo, y) }, a.hi, a.lo+a.r, a.x, a.y, a.r) 1015 } 1016 } 1017 1018 func TestDivPanicOverflow(t *testing.T) { 1019 // Expect a panic 1020 defer func() { 1021 if err := recover(); err == nil { 1022 t.Error("Div should have panicked when y<=hi") 1023 } else if err != overflowError { 1024 t.Errorf("Div expected panic: %q, got: %v ", overflowError, err) 1025 } 1026 }() 1027 q, r := Div(1, 0, 1) 1028 t.Errorf("undefined q, r = %v, %v calculated when Div should have panicked", q, r) 1029 } 1030 1031 func TestDiv32PanicOverflow(t *testing.T) { 1032 // Expect a panic 1033 defer func() { 1034 if err := recover(); err == nil { 1035 t.Error("Div32 should have panicked when y<=hi") 1036 } else if err != overflowError { 1037 t.Errorf("Div32 expected panic: %q, got: %v ", overflowError, err) 1038 } 1039 }() 1040 q, r := Div32(1, 0, 1) 1041 t.Errorf("undefined q, r = %v, %v calculated when Div32 should have panicked", q, r) 1042 } 1043 1044 func TestDiv64PanicOverflow(t *testing.T) { 1045 // Expect a panic 1046 defer func() { 1047 if err := recover(); err == nil { 1048 t.Error("Div64 should have panicked when y<=hi") 1049 } else if err != overflowError { 1050 t.Errorf("Div64 expected panic: %q, got: %v ", overflowError, err) 1051 } 1052 }() 1053 q, r := Div64(1, 0, 1) 1054 t.Errorf("undefined q, r = %v, %v calculated when Div64 should have panicked", q, r) 1055 } 1056 1057 func TestDivPanicZero(t *testing.T) { 1058 // Expect a panic 1059 defer func() { 1060 if err := recover(); err == nil { 1061 t.Error("Div should have panicked when y==0") 1062 } else if err != divideError { 1063 t.Errorf("Div expected panic: %q, got: %q ", divideError, err) 1064 } 1065 }() 1066 q, r := Div(1, 1, 0) 1067 t.Errorf("undefined q, r = %v, %v calculated when Div should have panicked", q, r) 1068 } 1069 1070 func TestDiv32PanicZero(t *testing.T) { 1071 // Expect a panic 1072 defer func() { 1073 if err := recover(); err == nil { 1074 t.Error("Div32 should have panicked when y==0") 1075 } else if err != divideError { 1076 t.Errorf("Div32 expected panic: %q, got: %q ", divideError, err) 1077 } 1078 }() 1079 q, r := Div32(1, 1, 0) 1080 t.Errorf("undefined q, r = %v, %v calculated when Div32 should have panicked", q, r) 1081 } 1082 1083 func TestDiv64PanicZero(t *testing.T) { 1084 // Expect a panic 1085 defer func() { 1086 if err := recover(); err == nil { 1087 t.Error("Div64 should have panicked when y==0") 1088 } else if err != divideError { 1089 t.Errorf("Div64 expected panic: %q, got: %q ", divideError, err) 1090 } 1091 }() 1092 q, r := Div64(1, 1, 0) 1093 t.Errorf("undefined q, r = %v, %v calculated when Div64 should have panicked", q, r) 1094 } 1095 1096 func TestRem32(t *testing.T) { 1097 // Sanity check: for non-overflowing dividends, the result is the 1098 // same as the rem returned by Div32 1099 hi, lo, y := uint32(510510), uint32(9699690), uint32(510510+1) // ensure hi < y 1100 for i := 0; i < 1000; i++ { 1101 r := Rem32(hi, lo, y) 1102 _, r2 := Div32(hi, lo, y) 1103 if r != r2 { 1104 t.Errorf("Rem32(%v, %v, %v) returned %v, but Div32 returned rem %v", hi, lo, y, r, r2) 1105 } 1106 y += 13 1107 } 1108 } 1109 1110 func TestRem32Overflow(t *testing.T) { 1111 // To trigger a quotient overflow, we need y <= hi 1112 hi, lo, y := uint32(510510), uint32(9699690), uint32(7) 1113 for i := 0; i < 1000; i++ { 1114 r := Rem32(hi, lo, y) 1115 _, r2 := Div64(0, uint64(hi)<<32|uint64(lo), uint64(y)) 1116 if r != uint32(r2) { 1117 t.Errorf("Rem32(%v, %v, %v) returned %v, but Div64 returned rem %v", hi, lo, y, r, r2) 1118 } 1119 y += 13 1120 } 1121 } 1122 1123 func TestRem64(t *testing.T) { 1124 // Sanity check: for non-overflowing dividends, the result is the 1125 // same as the rem returned by Div64 1126 hi, lo, y := uint64(510510), uint64(9699690), uint64(510510+1) // ensure hi < y 1127 for i := 0; i < 1000; i++ { 1128 r := Rem64(hi, lo, y) 1129 _, r2 := Div64(hi, lo, y) 1130 if r != r2 { 1131 t.Errorf("Rem64(%v, %v, %v) returned %v, but Div64 returned rem %v", hi, lo, y, r, r2) 1132 } 1133 y += 13 1134 } 1135 } 1136 1137 func TestRem64Overflow(t *testing.T) { 1138 Rem64Tests := []struct { 1139 hi, lo, y uint64 1140 rem uint64 1141 }{ 1142 // Testcases computed using Python 3, as: 1143 // >>> hi = 42; lo = 1119; y = 42 1144 // >>> ((hi<<64)+lo) % y 1145 {42, 1119, 42, 27}, 1146 {42, 1119, 38, 9}, 1147 {42, 1119, 26, 23}, 1148 {469, 0, 467, 271}, 1149 {469, 0, 113, 58}, 1150 {111111, 111111, 1171, 803}, 1151 {3968194946088682615, 3192705705065114702, 1000037, 56067}, 1152 } 1153 1154 for _, rt := range Rem64Tests { 1155 if rt.hi < rt.y { 1156 t.Fatalf("Rem64(%v, %v, %v) is not a test with quo overflow", rt.hi, rt.lo, rt.y) 1157 } 1158 rem := Rem64(rt.hi, rt.lo, rt.y) 1159 if rem != rt.rem { 1160 t.Errorf("Rem64(%v, %v, %v) returned %v, wanted %v", 1161 rt.hi, rt.lo, rt.y, rem, rt.rem) 1162 } 1163 } 1164 } 1165 1166 func BenchmarkAdd(b *testing.B) { 1167 var z, c uint 1168 for i := 0; i < b.N; i++ { 1169 z, c = Add(uint(Input), uint(i), c) 1170 } 1171 Output = int(z + c) 1172 } 1173 1174 func BenchmarkAdd32(b *testing.B) { 1175 var z, c uint32 1176 for i := 0; i < b.N; i++ { 1177 z, c = Add32(uint32(Input), uint32(i), c) 1178 } 1179 Output = int(z + c) 1180 } 1181 1182 func BenchmarkAdd64(b *testing.B) { 1183 var z, c uint64 1184 for i := 0; i < b.N; i++ { 1185 z, c = Add64(uint64(Input), uint64(i), c) 1186 } 1187 Output = int(z + c) 1188 } 1189 1190 func BenchmarkAdd64multiple(b *testing.B) { 1191 z0 := uint64(Input) 1192 z1 := uint64(Input) 1193 z2 := uint64(Input) 1194 z3 := uint64(Input) 1195 for i := 0; i < b.N; i++ { 1196 var c uint64 1197 z0, c = Add64(z0, uint64(i), c) 1198 z1, c = Add64(z1, uint64(i), c) 1199 z2, c = Add64(z2, uint64(i), c) 1200 z3, _ = Add64(z3, uint64(i), c) 1201 } 1202 Output = int(z0 + z1 + z2 + z3) 1203 } 1204 1205 func BenchmarkSub(b *testing.B) { 1206 var z, c uint 1207 for i := 0; i < b.N; i++ { 1208 z, c = Sub(uint(Input), uint(i), c) 1209 } 1210 Output = int(z + c) 1211 } 1212 1213 func BenchmarkSub32(b *testing.B) { 1214 var z, c uint32 1215 for i := 0; i < b.N; i++ { 1216 z, c = Sub32(uint32(Input), uint32(i), c) 1217 } 1218 Output = int(z + c) 1219 } 1220 1221 func BenchmarkSub64(b *testing.B) { 1222 var z, c uint64 1223 for i := 0; i < b.N; i++ { 1224 z, c = Sub64(uint64(Input), uint64(i), c) 1225 } 1226 Output = int(z + c) 1227 } 1228 1229 func BenchmarkSub64multiple(b *testing.B) { 1230 z0 := uint64(Input) 1231 z1 := uint64(Input) 1232 z2 := uint64(Input) 1233 z3 := uint64(Input) 1234 for i := 0; i < b.N; i++ { 1235 var c uint64 1236 z0, c = Sub64(z0, uint64(i), c) 1237 z1, c = Sub64(z1, uint64(i), c) 1238 z2, c = Sub64(z2, uint64(i), c) 1239 z3, _ = Sub64(z3, uint64(i), c) 1240 } 1241 Output = int(z0 + z1 + z2 + z3) 1242 } 1243 1244 func BenchmarkMul(b *testing.B) { 1245 var hi, lo uint 1246 for i := 0; i < b.N; i++ { 1247 hi, lo = Mul(uint(Input), uint(i)) 1248 } 1249 Output = int(hi + lo) 1250 } 1251 1252 func BenchmarkMul32(b *testing.B) { 1253 var hi, lo uint32 1254 for i := 0; i < b.N; i++ { 1255 hi, lo = Mul32(uint32(Input), uint32(i)) 1256 } 1257 Output = int(hi + lo) 1258 } 1259 1260 func BenchmarkMul64(b *testing.B) { 1261 var hi, lo uint64 1262 for i := 0; i < b.N; i++ { 1263 hi, lo = Mul64(uint64(Input), uint64(i)) 1264 } 1265 Output = int(hi + lo) 1266 } 1267 1268 func BenchmarkDiv(b *testing.B) { 1269 var q, r uint 1270 for i := 0; i < b.N; i++ { 1271 q, r = Div(1, uint(i), uint(Input)) 1272 } 1273 Output = int(q + r) 1274 } 1275 1276 func BenchmarkDiv32(b *testing.B) { 1277 var q, r uint32 1278 for i := 0; i < b.N; i++ { 1279 q, r = Div32(1, uint32(i), uint32(Input)) 1280 } 1281 Output = int(q + r) 1282 } 1283 1284 func BenchmarkDiv64(b *testing.B) { 1285 var q, r uint64 1286 for i := 0; i < b.N; i++ { 1287 q, r = Div64(1, uint64(i), uint64(Input)) 1288 } 1289 Output = int(q + r) 1290 } 1291 1292 // ---------------------------------------------------------------------------- 1293 // Testing support 1294 1295 type entry = struct { 1296 nlz, ntz, pop int 1297 } 1298 1299 // tab contains results for all uint8 values 1300 var tab [256]entry 1301 1302 func init() { 1303 tab[0] = entry{8, 8, 0} 1304 for i := 1; i < len(tab); i++ { 1305 // nlz 1306 x := i // x != 0 1307 n := 0 1308 for x&0x80 == 0 { 1309 n++ 1310 x <<= 1 1311 } 1312 tab[i].nlz = n 1313 1314 // ntz 1315 x = i // x != 0 1316 n = 0 1317 for x&1 == 0 { 1318 n++ 1319 x >>= 1 1320 } 1321 tab[i].ntz = n 1322 1323 // pop 1324 x = i // x != 0 1325 n = 0 1326 for x != 0 { 1327 n += int(x & 1) 1328 x >>= 1 1329 } 1330 tab[i].pop = n 1331 } 1332 }