github.com/ericlagergren/ctb@v0.0.0-20220810041818-96749d9c394d/xbits/xbits.go (about) 1 // Package xbits augments math/bits with larger integers. 2 package xbits 3 4 import ( 5 "crypto/subtle" 6 "encoding/binary" 7 "fmt" 8 "io" 9 "math/big" 10 "math/bits" 11 12 "github.com/elagergren/ctb/xbits/ct" 13 ) 14 15 // Uint256 is an unsigned 256-bit integer. 16 type Uint256 struct { 17 u0, u1, u2, u3 uint64 18 } 19 20 var ( 21 _ fmt.Stringer = Uint256{} 22 _ fmt.Formatter = Uint256{} 23 ) 24 25 // U256 creates a Uint256 from a uint64. 26 func U256(x uint64) Uint256 { 27 return Uint256{x, 0, 0, 0} 28 } 29 30 // Add returns x + y. 31 // 32 // This function's execution time does not depend on its inputs. 33 //go:noinline 34 func (x Uint256) Add(y Uint256) Uint256 { 35 var z Uint256 36 var c uint64 37 z.u0, c = bits.Add64(x.u0, y.u0, c) 38 z.u1, c = bits.Add64(x.u1, y.u1, c) 39 z.u2, c = bits.Add64(x.u2, y.u2, c) 40 z.u3, _ = bits.Add64(x.u3, y.u3, c) 41 return z 42 } 43 44 // And returns x & y. 45 // 46 // This function's execution time does not depend on its inputs. 47 func (x Uint256) And(y Uint256) Uint256 { 48 var z Uint256 49 z.u0 = x.u0 & y.u0 50 z.u1 = x.u1 & y.u1 51 z.u2 = x.u2 & y.u2 52 z.u3 = x.u3 & y.u3 53 return z 54 } 55 56 // Bit returns the value of bit at index i. 57 // 58 // That is, Bit returns (x>>i)&1. 59 // The index must be >= 0. 60 func (x Uint256) Bit(i int) uint { 61 if i < 0 { 62 panic("negative bit index") 63 } 64 if i >= 256 { 65 return 0 66 } 67 n := make([]uint64, 4) 68 n[0] = x.u0 69 n[1] = x.u1 70 n[2] = x.u2 71 n[3] = x.u3 72 return uint(n[i/64] >> (i % 64) & 1) 73 } 74 75 // BitLen returns the absolute value of x in bits. 76 // 77 // In other words, the number of bits needed to 78 // represent x. 79 func (x Uint256) BitLen() int { 80 switch { 81 case x.u3 != 0: 82 return 192 + bits.Len64(x.u3) 83 case x.u2 != 0: 84 return 128 + bits.Len64(x.u2) 85 case x.u1 != 0: 86 return 64 + bits.Len64(x.u1) 87 default: 88 return bits.Len64(x.u0) 89 } 90 } 91 92 // Cmp compares u and x and returns 93 // 94 // +1 if x > y 95 // 0 if x == y 96 // -1 if x < y 97 // 98 func (x Uint256) Cmp(y Uint256) int { 99 var z Uint256 100 var b uint64 101 z.u0, b = bits.Sub64(x.u0, y.u0, b) 102 z.u1, b = bits.Sub64(x.u1, y.u1, b) 103 z.u2, b = bits.Sub64(x.u2, y.u2, b) 104 z.u3, b = bits.Sub64(x.u3, y.u3, b) 105 106 r := z.u0 ^ z.u1 ^ z.u2 ^ z.u3 107 // If r == 0 then x == y 108 // If r != 0 then x != y 109 // If b == 0 then x > y 110 // If b == 1 then x <= y 111 if b == 0 { 112 return +1 113 } 114 if r == 0 { 115 return +0 116 } 117 return -1 118 } 119 120 // Exp returns x**y mod m. 121 func (x Uint256) Exp(y, m Uint256) Uint256 { 122 x1 := x 123 x2 := x.MulMod(x, m) 124 for i := 256 - 2; i >= 0; i-- { 125 if y.Bit(i) == 0 { 126 // x2 = x1*x2 mod m 127 x2 = x1.MulMod(x2, m) 128 // x1 = x1^2 mod m 129 x1 = x1.MulMod(x1, m) 130 } else { 131 // x1 = x1*x2 mod m 132 x1 = x1.MulMod(x2, m) 133 // x2 = x2^2 mod m 134 x2 = x2.MulMod(x2, m) 135 } 136 } 137 return x1 138 } 139 140 // FillBytes sets buf to x, storing it as a zero-extended 141 // big-endian byte slice, and returns buf. 142 // 143 // If x does not fit into buf, FillBytes will panic. 144 func (x Uint256) FillBytes(buf []byte) []byte { 145 binary.BigEndian.PutUint64(buf[24:], x.u0) 146 binary.BigEndian.PutUint64(buf[16:24], x.u1) 147 binary.BigEndian.PutUint64(buf[8:16], x.u2) 148 binary.BigEndian.PutUint64(buf[:8], x.u3) 149 return buf 150 } 151 152 func (x Uint256) Format(s fmt.State, ch rune) { 153 // Implementation borrowed from math/big. 154 155 var base int 156 switch ch { 157 case 'b': 158 base = 2 159 case 'o', 'O': 160 base = 8 161 case 'd', 's', 'v': 162 base = 10 163 case 'x', 'X': 164 base = 16 165 default: 166 fmt.Fprintf(s, "%%!%c(xbits.Uint256=%s)", ch, x.String()) 167 return 168 } 169 170 sign := "" 171 switch { 172 case s.Flag('+'): 173 sign = "+" 174 case s.Flag(' '): 175 sign = " " 176 } 177 178 prefix := "" 179 if s.Flag('#') { 180 switch ch { 181 case 'b': 182 prefix = "0b" 183 case 'o': 184 prefix = "0" 185 case 'x': 186 prefix = "0x" 187 case 'X': 188 prefix = "0X" 189 } 190 } 191 if ch == 'O' { 192 prefix = "0o" 193 } 194 195 digits := []byte(x.Text(base)) 196 if ch == 'X' { 197 for i, d := range digits { 198 if 'a' <= d && d <= 'z' { 199 digits[i] = 'A' + (d - 'a') 200 } 201 } 202 } 203 204 var left int 205 var zeros int 206 var right int 207 208 precision, precisionSet := s.Precision() 209 if precisionSet { 210 switch { 211 case len(digits) < precision: 212 zeros = precision - len(digits) 213 case len(digits) == 1 && digits[0] == '0' && precision == 0: 214 return 215 } 216 } 217 218 length := len(sign) + len(prefix) + zeros + len(digits) 219 if width, widthSet := s.Width(); widthSet && length < width { 220 switch d := width - length; { 221 case s.Flag('-'): 222 right = d 223 case s.Flag('0') && !precisionSet: 224 zeros = d 225 default: 226 left = d 227 } 228 } 229 230 writeMultiple(s, " ", left) 231 writeMultiple(s, sign, 1) 232 writeMultiple(s, prefix, 1) 233 writeMultiple(s, "0", zeros) 234 s.Write(digits) 235 writeMultiple(s, " ", right) 236 } 237 238 // write count copies of text to s 239 func writeMultiple(s fmt.State, text string, count int) { 240 if len(text) > 0 { 241 b := []byte(text) 242 for ; count > 0; count-- { 243 s.Write(b) 244 } 245 } 246 } 247 248 // Lsh returns x<<n. 249 // 250 // This function's execution time does not depend on its inputs. 251 func (x Uint256) Lsh(n uint) Uint256 { 252 s := n % 64 253 ŝ := 64 - s 254 255 // If n is in [0, 256) set i = n/64. 256 // Otherwise, set i = 4. 257 i := subtle.ConstantTimeSelect(int(ct.LessOrEq(n, 255)), int(n/64), 4) 258 259 res := make([]uint64, 8) 260 res[i+3] = x.u3<<s | x.u2>>ŝ 261 res[i+2] = x.u2<<s | x.u1>>ŝ 262 res[i+1] = x.u1<<s | x.u0>>ŝ 263 res[i+0] = x.u0 << s 264 265 var z Uint256 266 z.u0 = res[0] 267 z.u1 = res[1] 268 z.u2 = res[2] 269 z.u3 = res[3] 270 return z 271 } 272 273 // shr sets z = x<<n for n in [0, 64]. 274 func shl(z, x []uint64, n uint) uint64 { 275 s := n % 64 276 ŝ := 64 - s 277 278 c := x[len(z)-1] >> ŝ 279 for i := len(z) - 1; i > 0; i-- { 280 z[i] = x[i]<<s | x[i-1]>>ŝ 281 } 282 z[0] = x[0] << s 283 return c 284 } 285 286 // ModInverse returns the multiplicative inverse 287 // of x in the ring ℤ/nℤ. 288 // 289 // If x and n are not relatively prime, x has no 290 // multiplicative inverse in the ring ℤ/nℤ and 291 // ModInverse will panic. 292 func (x Uint256) ModInverse(n Uint256) Uint256 { 293 panic("TODO") 294 } 295 296 // Mul returns x * y. 297 // 298 // This function's execution time does not depend on its inputs. 299 func (x Uint256) Mul(y Uint256) Uint256 { 300 z := make([]uint64, 8) 301 mul512(z, x, y) 302 return Uint256{z[0], z[1], z[2], z[3]} 303 } 304 305 // MulMod returns x*y mod m. 306 func (x Uint256) MulMod(y, m Uint256) Uint256 { 307 z := make([]uint64, 8) 308 mul512(z, x, y) 309 310 if m.BitLen() <= 64 { 311 return U256(mod64(z, m.u0)) 312 } 313 314 v := make([]uint64, 4) 315 v[0] = m.u0 316 v[1] = m.u1 317 v[2] = m.u2 318 v[3] = m.u3 319 320 q := make([]uint64, 8) 321 r := div512(q, z, v) 322 return Uint256{r[0], r[1], r[2], r[3]} 323 } 324 325 // mul512 returns the 512-bit product of x*y. 326 // 327 // mul512 has the following conditions: 328 // 329 // len(z) == 8 330 // 331 // This function's execution time does not depend on its inputs. 332 func mul512(z []uint64, x, y Uint256) { 333 var ( 334 c uint64 335 z1, z0 uint64 336 ) 337 338 // y_0 * x 339 // 340 // Store in z[0:4] 341 342 c, z[0] = mul128(x.u0, y.u0, z[0]) 343 344 z1, z0 = mul128(x.u1, y.u0, z[1]) 345 lo, cc := bits.Add64(z0, c, 0) 346 c, z[1] = cc, lo 347 c += z1 348 349 z1, z0 = mul128(x.u2, y.u0, z[2]) 350 lo, cc = bits.Add64(z0, c, 0) 351 c, z[2] = cc, lo 352 c += z1 353 354 z1, z0 = mul128(x.u3, y.u0, z[3]) 355 lo, cc = bits.Add64(z0, c, 0) 356 c, z[3] = cc, lo 357 c += z1 358 359 z[4] = c 360 361 // y_1 * x 362 // 363 // Store in z[1:5] 364 365 c, z[1] = mul128(x.u0, y.u1, z[1]) 366 367 z1, z0 = mul128(x.u1, y.u1, z[2]) 368 lo, cc = bits.Add64(z0, c, 0) 369 c, z[2] = cc, lo 370 c += z1 371 372 z1, z0 = mul128(x.u2, y.u1, z[3]) 373 lo, cc = bits.Add64(z0, c, 0) 374 c, z[3] = cc, lo 375 c += z1 376 377 z1, z0 = mul128(x.u3, y.u1, z[4]) 378 lo, cc = bits.Add64(z0, c, 0) 379 c, z[4] = cc, lo 380 c += z1 381 382 z[5] = c 383 384 // y_2 * x 385 // 386 // Store in z[2:6] 387 388 c, z[2] = mul128(x.u0, y.u2, z[2]) 389 390 z1, z0 = mul128(x.u1, y.u2, z[3]) 391 lo, cc = bits.Add64(z0, c, 0) 392 c, z[3] = cc, lo 393 c += z1 394 395 z1, z0 = mul128(x.u2, y.u2, z[4]) 396 lo, cc = bits.Add64(z0, c, 0) 397 c, z[4] = cc, lo 398 c += z1 399 400 z1, z0 = mul128(x.u3, y.u2, z[5]) 401 lo, cc = bits.Add64(z0, c, 0) 402 c, z[5] = cc, lo 403 c += z1 404 405 z[6] = c 406 407 // y_3 * x 408 // 409 // Store in z[3:7] 410 411 c, z[3] = mul128(x.u0, y.u3, z[3]) 412 413 z1, z0 = mul128(x.u1, y.u3, z[4]) 414 lo, cc = bits.Add64(z0, c, 0) 415 c, z[4] = cc, lo 416 c += z1 417 418 z1, z0 = mul128(x.u2, y.u3, z[5]) 419 lo, cc = bits.Add64(z0, c, 0) 420 c, z[5] = cc, lo 421 c += z1 422 423 z1, z0 = mul128(x.u3, y.u3, z[6]) 424 lo, cc = bits.Add64(z0, c, 0) 425 c, z[6] = cc, lo 426 c += z1 427 428 z[7] = c 429 } 430 431 func mul128(x, y, c uint64) (z1, z0 uint64) { 432 hi, lo := bits.Mul64(x, y) 433 lo, c = bits.Add64(lo, c, 0) 434 return hi + c, lo 435 } 436 437 // LeadingZeros returns the number of leading 438 // zero bits in x. 439 // 440 // The result is 256 if x == 0. 441 func (x Uint256) LeadingZeros() int { 442 return 256 - x.BitLen() 443 } 444 445 // OnesCount returns the number of one bits 446 // in x. 447 // 448 // Also known as the "population count." 449 func (x Uint256) OnesCount() int { 450 var n int 451 n += bits.OnesCount64(x.u0) 452 n += bits.OnesCount64(x.u1) 453 n += bits.OnesCount64(x.u2) 454 n += bits.OnesCount64(x.u3) 455 return n 456 } 457 458 // Or returns x | y. 459 // 460 // This function's execution time does not depend on its inputs. 461 func (x Uint256) Or(y Uint256) Uint256 { 462 var z Uint256 463 z.u0 = x.u0 | y.u0 464 z.u1 = x.u1 | y.u1 465 z.u2 = x.u2 | y.u2 466 z.u3 = x.u3 | y.u3 467 return z 468 } 469 470 // Quo returns x / y. 471 // 472 // Quo implements truncated division, like Go. 473 func (x Uint256) Quo(y Uint256) Uint256 { 474 q, _ := x.QuoRem(y) 475 return q 476 } 477 478 // QuoRem returns x / y and x % y. 479 // 480 // QuoRem implements truncated division and 481 // modulus, like Go. 482 func (x Uint256) QuoRem(y Uint256) (Uint256, Uint256) { 483 // QuoRem is largely borrowed from math/big. 484 485 if l := y.BitLen(); l <= 64 { 486 if l == 0 { 487 panic("division by zero") 488 } 489 y := y.u0 490 rec := reciprocal(y) 491 var q Uint256 492 var r uint64 493 q.u3, r = divWW(r, x.u3, y, rec) 494 q.u2, r = divWW(r, x.u2, y, rec) 495 q.u1, r = divWW(r, x.u1, y, rec) 496 q.u0, r = divWW(r, x.u0, y, rec) 497 return q, U256(r) 498 } 499 500 u := make([]uint64, 5) 501 u[0] = x.u0 502 u[1] = x.u1 503 u[2] = x.u2 504 u[3] = x.u3 505 506 v := make([]uint64, 4) 507 v[0] = y.u0 508 v[1] = y.u1 509 v[2] = y.u2 510 v[3] = y.u3 511 512 q := make([]uint64, 5) 513 r := div512(q, u, v) 514 515 quo := Uint256{q[0], q[1], q[2], q[3]} 516 rem := Uint256{r[0], r[1], r[2], r[3]} 517 return quo, rem 518 } 519 520 // mod64 return u%v. 521 func mod64(uIn []uint64, v uint64) (r uint64) { 522 rec := reciprocal(v) 523 for i := len(uIn) - 1; i >= 0; i-- { 524 _, r = divWW(r, uIn[i], v, rec) 525 } 526 return r 527 } 528 529 // div512 sets q = u/v and returns r = u%v. 530 // 531 // div512 has the following conditions: 532 // 533 // len(v) >= 2 534 // len(u) >= len(v) + 1 535 // u[len(u)-1] must be zero (reserved for r) 536 // len(q) >= len(u) 537 // u must not alias z 538 // 539 // div512 reuses u as storage for r. 540 // div512 modifies v. 541 func div512(q, uIn, vIn []uint64) (r []uint64) { 542 _ = vIn[2-1] 543 _ = uIn[len(vIn)+1-1] 544 _ = q[len(uIn)-len(vIn)+1-1] 545 546 // Normalize v. 547 n := len(vIn) 548 for n > 0 && vIn[n-1] == 0 { 549 n-- 550 } 551 vIn = vIn[:n] 552 553 // Normalize u. 554 uIn[len(uIn)-1] = 0 555 m := len(uIn) - 1 556 for m > 0 && uIn[m-1] == 0 { 557 m-- 558 } 559 uIn = uIn[:m] 560 m -= n 561 562 // D1. 563 shift := uint(bits.LeadingZeros64(vIn[n-1])) 564 565 v := vIn 566 shl(v, vIn, shift) 567 568 u := uIn[:len(uIn)+1] 569 u[m] = shl(u[:len(uIn)], uIn, shift) 570 571 q = q[:m+1] 572 573 qhatv := make([]uint64, 8) 574 qhatvLen := n + 1 575 576 // D2. 577 vn1 := v[n-1] 578 rec := reciprocal(vn1) 579 for j := m; j >= 0; j-- { 580 // D3. 581 const mask = 1<<64 - 1 582 qhat := uint64(mask) 583 var ujn uint64 584 if j+n < len(u) { 585 ujn = u[j+n] 586 } 587 if ujn != vn1 { 588 var rhat uint64 589 qhat, rhat = divWW(ujn, u[j+n-1], vn1, rec) 590 591 // x1 | x2 = q̂v_{n-2} 592 vn2 := v[n-2] 593 x1, x2 := bits.Mul64(qhat, vn2) 594 // test if q̂v_{n-2} > br̂ + u_{j+n-2} 595 ujn2 := u[j+n-2] 596 for greaterThan(x1, x2, rhat, ujn2) { 597 qhat-- 598 prevRhat := rhat 599 rhat += vn1 600 // v[n-1] >= 0, so this tests for overflow. 601 if rhat < prevRhat { 602 break 603 } 604 x1, x2 = bits.Mul64(qhat, vn2) 605 } 606 } 607 608 // D4. 609 // Compute the remainder u - (q̂*v) << (_W*j). 610 // The subtraction may overflow if q̂ estimate was off by one. 611 qhatv[n] = mulAddVWW(qhatv[0:n], v, qhat, 0) 612 qhl := qhatvLen 613 if j+qhl > len(u) && qhatv[n] == 0 { 614 qhl-- 615 } 616 c := subVV(u[j:j+qhl], u[j:], qhatv) 617 if c != 0 { 618 c := addVV(u[j:j+n], u[j:], v) 619 // If n == qhl, the carry from subVV and the carry from addVV 620 // cancel out and don't affect u[j+n]. 621 if n < qhl { 622 u[j+n] += c 623 } 624 qhat-- 625 } 626 627 if j == m && m == len(q) && qhat == 0 { 628 continue 629 } 630 q[j] = qhat 631 } 632 shr(u, u, shift) 633 r = u 634 return r 635 } 636 637 // Rem returns x % y. 638 // 639 // Rem implements truncated modulus, like Go. 640 func (x Uint256) Rem(y Uint256) Uint256 { 641 _, r := x.QuoRem(y) 642 return r 643 } 644 645 // RotateLeft returns the value of x rotated left 646 // by (k mod 256) bits. 647 // 648 // This function's execution time does not depend on its inputs. 649 func (x Uint256) RotateLeft(k int) Uint256 { 650 const n = 256 651 s := uint(k) & (n - 1) 652 return x.Lsh(s).Or(x.Rsh(n - s)) 653 } 654 655 // RoateRight returns the value of x rotated right 656 // by (k mod 256) bits. 657 // 658 // This function's execution time does not depend on its inputs. 659 func (x Uint256) RotateRight(k int) Uint256 { 660 return x.RotateLeft(-k) 661 } 662 663 // Reverse returns the value of x with its bits in 664 // reversed order. 665 func (x Uint256) Reverse() Uint256 { 666 var z Uint256 667 z.u0 = bits.Reverse64(x.u0) 668 z.u1 = bits.Reverse64(x.u1) 669 z.u2 = bits.Reverse64(x.u2) 670 z.u3 = bits.Reverse64(x.u3) 671 return z 672 } 673 674 // ReverseBytes returns the value of x with its bytes 675 // in reversed order. 676 // 677 // This function's execution time does not depend on its inputs. 678 func (x Uint256) ReverseBytes() Uint256 { 679 var z Uint256 680 z.u0 = bits.ReverseBytes64(x.u0) 681 z.u1 = bits.ReverseBytes64(x.u1) 682 z.u2 = bits.ReverseBytes64(x.u2) 683 z.u3 = bits.ReverseBytes64(x.u3) 684 return z 685 } 686 687 // Rsh returns x>>n. 688 // 689 // This function's execution time does not depend on its inputs. 690 func (x Uint256) Rsh(n uint) Uint256 { 691 s := n % 64 692 ŝ := 64 - s 693 694 res := make([]uint64, 8) 695 res[0] = x.u0>>s | x.u1<<ŝ 696 res[1] = x.u1>>s | x.u2<<ŝ 697 res[2] = x.u2>>s | x.u3<<ŝ 698 res[3] = x.u3 >> s 699 700 // If n is in [0, 256) set i = n/64. 701 // Otherwise, set i = 4. 702 i := subtle.ConstantTimeSelect(int(ct.LessOrEq(n, 255)), int(n/64), 4) 703 704 var z Uint256 705 z.u0 = res[i+0] 706 z.u1 = res[i+1] 707 z.u2 = res[i+2] 708 z.u3 = res[i+3] 709 return z 710 } 711 712 // shr sets z = x>>n for n in [0, 64]. 713 func shr(z, x []uint64, n uint) uint64 { 714 s := n % 64 715 ŝ := 64 - s 716 717 c := x[0] << ŝ 718 z[0] = x[0]>>s | x[1]<<ŝ 719 z[1] = x[1]>>s | x[2]<<ŝ 720 z[2] = x[2]>>s | x[3]<<ŝ 721 z[3] = x[3] >> s 722 return c 723 } 724 725 // SetBytes sets z to the big-endian unsigned integer buf. 726 // 727 // SetBytes panics if buf overflows z (buf > 1<<256-1). 728 func (z *Uint256) SetBytes(buf []byte) { 729 if len(buf) > 32 { 730 panic("SetBytes: integer too large") 731 } 732 733 *z = Uint256{} 734 if len(buf) > 24 { 735 z.u3 = be64(buf[:len(buf)-24]) 736 buf = buf[len(buf)-24:] 737 } 738 if len(buf) > 16 { 739 z.u2 = be64(buf[:len(buf)-16]) 740 buf = buf[len(buf)-16:] 741 } 742 if len(buf) > 8 { 743 z.u1 = be64(buf[:len(buf)-8]) 744 buf = buf[len(buf)-8:] 745 } 746 if len(buf) > 0 { 747 z.u0 = be64(buf) 748 } 749 } 750 751 func be64(b []byte) uint64 { 752 switch len(b) { 753 case 8: 754 return binary.BigEndian.Uint64(b) 755 case 7: 756 _ = b[6] // bounds check hint to compiler; see golang.org/issue/14808 757 return uint64(b[6]) | uint64(b[5])<<8 | uint64(b[4])<<16 | 758 uint64(b[3])<<24 | uint64(b[2])<<32 | uint64(b[1])<<40 | 759 uint64(b[0])<<48 760 case 6: 761 _ = b[5] // bounds check hint to compiler; see golang.org/issue/14808 762 return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | 763 uint64(b[2])<<24 | uint64(b[1])<<32 | uint64(b[0])<<40 764 case 5: 765 _ = b[4] // bounds check hint to compiler; see golang.org/issue/14808 766 return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | 767 uint64(b[1])<<24 | uint64(b[0])<<32 768 case 4: 769 return uint64(binary.BigEndian.Uint32(b)) 770 case 3: 771 _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 772 return uint64(b[2]) | uint64(b[1])<<8 | uint64(b[0])<<16 773 case 2: 774 return uint64(binary.BigEndian.Uint16(b)) 775 case 1: 776 return uint64(b[0]) 777 case 0: 778 return 0 779 default: 780 panic("unreachable") 781 } 782 } 783 784 // Sub returns x - y. 785 // 786 // This function's execution time does not depend on its inputs. 787 func (x Uint256) Sub(y Uint256) Uint256 { 788 var z Uint256 789 var b uint64 790 z.u0, b = bits.Sub64(x.u0, y.u0, b) 791 z.u1, b = bits.Sub64(x.u1, y.u1, b) 792 z.u2, b = bits.Sub64(x.u2, y.u2, b) 793 z.u3, _ = bits.Sub64(x.u3, y.u3, b) 794 return z 795 } 796 797 func (x Uint256) String() string { 798 return x.Text(10) 799 } 800 801 // Text returns the textual representation of 802 // x in the provided base. 803 // 804 // The base must be in [2, 62]. 805 func (x Uint256) Text(base int) string { 806 var z big.Int 807 setInt(&z, x) 808 return z.Text(base) 809 } 810 811 // TrailingZeros returns the number of trailing 812 // zero bits in x. 813 // 814 // The result is 256 if x == 0. 815 func (x Uint256) TrailingZeros() int { 816 switch { 817 case x.u0 != 0: 818 return bits.TrailingZeros64(x.u0) 819 case x.u1 != 0: 820 return 64 + bits.TrailingZeros64(x.u1) 821 case x.u2 != 0: 822 return 128 + bits.TrailingZeros64(x.u2) 823 default: 824 return 192 + bits.TrailingZeros64(x.u3) 825 } 826 } 827 828 // Uint64 returns the uint64 representation of x. 829 // 830 // The result is undefined if x cannot be 831 // represented as a uint64. 832 func (x Uint256) Uint64() uint64 { 833 return x.u0 834 } 835 836 // Xor returns x ^ y. 837 // 838 // This function's execution time does not depend on its inputs. 839 func (x Uint256) Xor(y Uint256) Uint256 { 840 var z Uint256 841 z.u0 = x.u0 ^ y.u0 842 z.u1 = x.u1 ^ y.u1 843 z.u2 = x.u2 ^ y.u2 844 z.u3 = x.u3 ^ y.u3 845 return z 846 } 847 848 // Rand256 returns a Uint256 in [0, max). 849 // 850 // Rand256 panics if max = 0. 851 func Rand256(rand io.Reader, max Uint256) (Uint256, error) { 852 // Implementation borrowed from crypto/rand. 853 if max.BitLen() == 0 { 854 panic("xbits: argument to Rand256 is 0") 855 } 856 n := max.Sub(U256(1)) 857 // bitLen is the maximum bit length needed to encode a value < max. 858 bitLen := n.BitLen() 859 if bitLen == 0 { 860 // the only valid result is 0 861 return U256(0), nil 862 } 863 // k is the maximum byte length needed to encode a value < max. 864 k := (bitLen + 7) / 8 865 // b is the number of bits in the most significant byte of max-1. 866 b := uint(bitLen % 8) 867 if b == 0 { 868 b = 8 869 } 870 871 bytes := make([]byte, k) 872 for { 873 _, err := io.ReadFull(rand, bytes) 874 if err != nil { 875 return U256(0), err 876 } 877 878 // Clear bits in the first byte to increase the probability 879 // that the candidate is < max. 880 bytes[0] &= uint8(int(1<<b) - 1) 881 882 n.SetBytes(bytes) 883 if n.Cmp(max) < 0 { 884 return n, nil 885 } 886 } 887 } 888 889 func setInt(z *big.Int, x Uint256) { 890 const _W = bits.UintSize 891 if _W == 64 { 892 z.SetBits([]big.Word{ 893 big.Word(x.u0), 894 big.Word(x.u1), 895 big.Word(x.u2), 896 big.Word(x.u3), 897 }) 898 } else { 899 // _W == 32 900 z.SetBits([]big.Word{ 901 big.Word(x.u0), 902 big.Word(x.u0 >> 32), 903 big.Word(x.u1), 904 big.Word(x.u1 >> 32), 905 big.Word(x.u2), 906 big.Word(x.u2 >> 32), 907 big.Word(x.u3), 908 big.Word(x.u3 >> 32), 909 }) 910 } 911 }