1 /* 128 bit integer arithmetic. 2 * 3 * Not optimized for speed. 4 * 5 * Copyright: Copyright D Language Foundation 2022. 6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 7 * Authors: Walter Bright 8 * Source: $(DRUNTIMESRC core/_int128.d) 9 */ 10 11 module core.int128; 12 13 nothrow: 14 @safe: 15 @nogc: 16 17 alias I = long; 18 alias U = ulong; 19 enum Ubits = uint(U.sizeof * 8); 20 21 version (DigitalMars) 22 { 23 /* The alignment should follow target.stackAlign(), 24 * which is `isXmmSupported() ? 16 : (is64bit ? 8 : 4) 25 */ 26 version (D_SIMD) 27 private enum Cent_alignment = 16; 28 else version (X86_64) 29 private enum Cent_alignment = 8; 30 else 31 private enum Cent_alignment = 4; 32 } 33 else 34 { 35 version (X86_64) private enum Cent_alignment = 16; 36 else private enum Cent_alignment = (size_t.sizeof * 2); 37 } 38 39 align(Cent_alignment) struct Cent 40 { 41 version (LittleEndian) 42 { 43 U lo; // low 64 bits 44 U hi; // high 64 bits 45 } 46 else 47 { 48 U hi; // high 64 bits 49 U lo; // low 64 bits 50 } 51 } 52 53 enum Cent One = { lo:1 }; 54 enum Cent Zero = { lo:0 }; 55 enum Cent MinusOne = neg(One); 56 57 /***************************** 58 * Test against 0 59 * Params: 60 * c = Cent to test 61 * Returns: 62 * true if != 0 63 */ 64 pure 65 bool tst(Cent c) 66 { 67 return c.hi || c.lo; 68 } 69 70 71 /***************************** 72 * Complement 73 * Params: 74 * c = Cent to complement 75 * Returns: 76 * complemented value 77 */ 78 pure 79 Cent com(Cent c) 80 { 81 c.lo = ~c.lo; 82 c.hi = ~c.hi; 83 return c; 84 } 85 86 /***************************** 87 * Negate 88 * Params: 89 * c = Cent to negate 90 * Returns: 91 * negated value 92 */ 93 pure 94 Cent neg(Cent c) 95 { 96 if (c.lo == 0) 97 c.hi = -c.hi; 98 else 99 { 100 c.lo = -c.lo; 101 c.hi = ~c.hi; 102 } 103 return c; 104 } 105 106 /***************************** 107 * Increment 108 * Params: 109 * c = Cent to increment 110 * Returns: 111 * incremented value 112 */ 113 pure 114 Cent inc(Cent c) 115 { 116 return add(c, One); 117 } 118 119 /***************************** 120 * Decrement 121 * Params: 122 * c = Cent to decrement 123 * Returns: 124 * incremented value 125 */ 126 pure 127 Cent dec(Cent c) 128 { 129 return sub(c, One); 130 } 131 132 /***************************** 133 * Shift left one bit 134 * Params: 135 * c = Cent to shift 136 * Returns: 137 * shifted value 138 */ 139 pure 140 Cent shl1(Cent c) 141 { 142 c.hi = (c.hi << 1) | (cast(I)c.lo < 0); 143 c.lo <<= 1; 144 return c; 145 } 146 147 /***************************** 148 * Unsigned shift right one bit 149 * Params: 150 * c = Cent to shift 151 * Returns: 152 * shifted value 153 */ 154 pure 155 Cent shr1(Cent c) 156 { 157 c.lo = (c.lo >> 1) | ((c.hi & 1) << (Ubits - 1)); 158 c.hi >>= 1; 159 return c; 160 } 161 162 163 /***************************** 164 * Arithmetic shift right one bit 165 * Params: 166 * c = Cent to shift 167 * Returns: 168 * shifted value 169 */ 170 pure 171 Cent sar1(Cent c) 172 { 173 c.lo = (c.lo >> 1) | ((c.hi & 1) << (Ubits - 1)); 174 c.hi = cast(I)c.hi >> 1; 175 return c; 176 } 177 178 /***************************** 179 * Shift left n bits 180 * Params: 181 * c = Cent to shift 182 * n = number of bits to shift 183 * Returns: 184 * shifted value 185 */ 186 pure 187 Cent shl(Cent c, uint n) 188 { 189 if (n >= Ubits * 2) 190 return Zero; 191 192 if (n >= Ubits) 193 { 194 c.hi = c.lo << (n - Ubits); 195 c.lo = 0; 196 } 197 else 198 { 199 c.hi = ((c.hi << n) | (c.lo >> (Ubits - n - 1) >> 1)); 200 c.lo = c.lo << n; 201 } 202 return c; 203 } 204 205 /***************************** 206 * Unsigned shift right n bits 207 * Params: 208 * c = Cent to shift 209 * n = number of bits to shift 210 * Returns: 211 * shifted value 212 */ 213 pure 214 Cent shr(Cent c, uint n) 215 { 216 if (n >= Ubits * 2) 217 return Zero; 218 219 if (n >= Ubits) 220 { 221 c.lo = c.hi >> (n - Ubits); 222 c.hi = 0; 223 } 224 else 225 { 226 c.lo = ((c.lo >> n) | (c.hi << (Ubits - n - 1) << 1)); 227 c.hi = c.hi >> n; 228 } 229 return c; 230 } 231 232 /***************************** 233 * Arithmetic shift right n bits 234 * Params: 235 * c = Cent to shift 236 * n = number of bits to shift 237 * Returns: 238 * shifted value 239 */ 240 pure 241 Cent sar(Cent c, uint n) 242 { 243 const signmask = -(c.hi >> (Ubits - 1)); 244 const signshift = (Ubits * 2) - n; 245 c = shr(c, n); 246 247 // Sign extend all bits beyond the precision of Cent. 248 if (n >= Ubits * 2) 249 { 250 c.hi = signmask; 251 c.lo = signmask; 252 } 253 else if (signshift >= Ubits * 2) 254 { 255 } 256 else if (signshift >= Ubits) 257 { 258 c.hi &= ~(U.max << (signshift - Ubits)); 259 c.hi |= signmask << (signshift - Ubits); 260 } 261 else 262 { 263 c.hi = signmask; 264 c.lo &= ~(U.max << signshift); 265 c.lo |= signmask << signshift; 266 } 267 return c; 268 } 269 270 /***************************** 271 * Rotate left one bit 272 * Params: 273 * c = Cent to rotate 274 * Returns: 275 * rotated value 276 */ 277 pure 278 Cent rol1(Cent c) 279 { 280 int carry = cast(I)c.hi < 0; 281 282 c.hi = (c.hi << 1) | (cast(I)c.lo < 0); 283 c.lo = (c.lo << 1) | carry; 284 return c; 285 } 286 287 /***************************** 288 * Rotate right one bit 289 * Params: 290 * c = Cent to rotate 291 * Returns: 292 * rotated value 293 */ 294 pure 295 Cent ror1(Cent c) 296 { 297 int carry = c.lo & 1; 298 c.lo = (c.lo >> 1) | (cast(U)(c.hi & 1) << (Ubits - 1)); 299 c.hi = (c.hi >> 1) | (cast(U)carry << (Ubits - 1)); 300 return c; 301 } 302 303 304 /***************************** 305 * Rotate left n bits 306 * Params: 307 * c = Cent to rotate 308 * n = number of bits to rotate 309 * Returns: 310 * rotated value 311 */ 312 pure 313 Cent rol(Cent c, uint n) 314 { 315 n &= Ubits * 2 - 1; 316 Cent l = shl(c, n); 317 Cent r = shr(c, Ubits * 2 - n); 318 return or(l, r); 319 } 320 321 /***************************** 322 * Rotate right n bits 323 * Params: 324 * c = Cent to rotate 325 * n = number of bits to rotate 326 * Returns: 327 * rotated value 328 */ 329 pure 330 Cent ror(Cent c, uint n) 331 { 332 n &= Ubits * 2 - 1; 333 Cent r = shr(c, n); 334 Cent l = shl(c, Ubits * 2 - n); 335 return or(r, l); 336 } 337 338 /**************************** 339 * And c1 & c2. 340 * Params: 341 * c1 = operand 1 342 * c2 = operand 2 343 * Returns: 344 * c1 & c2 345 */ 346 pure 347 Cent and(Cent c1, Cent c2) 348 { 349 const Cent ret = { lo:c1.lo & c2.lo, hi:c1.hi & c2.hi }; 350 return ret; 351 } 352 353 /**************************** 354 * Or c1 | c2. 355 * Params: 356 * c1 = operand 1 357 * c2 = operand 2 358 * Returns: 359 * c1 | c2 360 */ 361 pure 362 Cent or(Cent c1, Cent c2) 363 { 364 const Cent ret = { lo:c1.lo | c2.lo, hi:c1.hi | c2.hi }; 365 return ret; 366 } 367 368 /**************************** 369 * Xor c1 ^ c2. 370 * Params: 371 * c1 = operand 1 372 * c2 = operand 2 373 * Returns: 374 * c1 ^ c2 375 */ 376 pure 377 Cent xor(Cent c1, Cent c2) 378 { 379 const Cent ret = { lo:c1.lo ^ c2.lo, hi:c1.hi ^ c2.hi }; 380 return ret; 381 } 382 383 /**************************** 384 * Add c1 to c2. 385 * Params: 386 * c1 = operand 1 387 * c2 = operand 2 388 * Returns: 389 * c1 + c2 390 */ 391 pure 392 Cent add(Cent c1, Cent c2) 393 { 394 U r = cast(U)(c1.lo + c2.lo); 395 const Cent ret = { lo:r, hi:cast(U)(c1.hi + c2.hi + (r < c1.lo)) }; 396 return ret; 397 } 398 399 /**************************** 400 * Subtract c2 from c1. 401 * Params: 402 * c1 = operand 1 403 * c2 = operand 2 404 * Returns: 405 * c1 - c2 406 */ 407 pure 408 Cent sub(Cent c1, Cent c2) 409 { 410 return add(c1, neg(c2)); 411 } 412 413 /**************************** 414 * Multiply c1 * c2. 415 * Params: 416 * c1 = operand 1 417 * c2 = operand 2 418 * Returns: 419 * c1 * c2 420 */ 421 pure 422 Cent mul(Cent c1, Cent c2) 423 { 424 enum mulmask = (1UL << (Ubits / 2)) - 1; 425 enum mulshift = Ubits / 2; 426 427 // This algorithm splits the operands into 4 words, then computes and sums 428 // the partial products of each part. 429 const c2l0 = c2.lo & mulmask; 430 const c2l1 = c2.lo >> mulshift; 431 const c2h0 = c2.hi & mulmask; 432 const c2h1 = c2.hi >> mulshift; 433 434 const c1l0 = c1.lo & mulmask; 435 U r0 = c1l0 * c2l0; 436 U r1 = c1l0 * c2l1 + (r0 >> mulshift); 437 U r2 = c1l0 * c2h0 + (r1 >> mulshift); 438 U r3 = c1l0 * c2h1 + (r2 >> mulshift); 439 440 const c1l1 = c1.lo >> mulshift; 441 r1 = c1l1 * c2l0 + (r1 & mulmask); 442 r2 = c1l1 * c2l1 + (r2 & mulmask) + (r1 >> mulshift); 443 r3 = c1l1 * c2h0 + (r3 & mulmask) + (r2 >> mulshift); 444 445 const c1h0 = c1.hi & mulmask; 446 r2 = c1h0 * c2l0 + (r2 & mulmask); 447 r3 = c1h0 * c2l1 + (r3 & mulmask) + (r2 >> mulshift); 448 449 const c1h1 = c1.hi >> mulshift; 450 r3 = c1h1 * c2l0 + (r3 & mulmask); 451 452 const Cent ret = { lo:(r0 & mulmask) + (r1 & mulmask) * (mulmask + 1), 453 hi:(r2 & mulmask) + (r3 & mulmask) * (mulmask + 1) }; 454 return ret; 455 } 456 457 458 /**************************** 459 * Unsigned divide c1 / c2. 460 * Params: 461 * c1 = dividend 462 * c2 = divisor 463 * Returns: 464 * quotient c1 / c2 465 */ 466 pure 467 Cent udiv(Cent c1, Cent c2) 468 { 469 Cent modulus; 470 return udivmod(c1, c2, modulus); 471 } 472 473 /**************************** 474 * Unsigned divide c1 / c2. The remainder after division is stored to modulus. 475 * Params: 476 * c1 = dividend 477 * c2 = divisor 478 * modulus = set to c1 % c2 479 * Returns: 480 * quotient c1 / c2 481 */ 482 pure 483 Cent udivmod(Cent c1, Cent c2, out Cent modulus) 484 { 485 //printf("udiv c1(%llx,%llx) c2(%llx,%llx)\n", c1.lo, c1.hi, c2.lo, c2.hi); 486 // Based on "Unsigned Doubleword Division" in Hacker's Delight 487 import core.bitop; 488 489 // Divides a 128-bit dividend by a 64-bit divisor. 490 // The result must fit in 64 bits. 491 static U udivmod128_64(Cent c1, U c2, out U modulus) 492 { 493 // We work in base 2^^32 494 enum base = 1UL << 32; 495 enum divmask = (1UL << (Ubits / 2)) - 1; 496 enum divshift = Ubits / 2; 497 498 // Check for overflow and divide by 0 499 if (c1.hi >= c2) 500 { 501 modulus = 0UL; 502 return ~0UL; 503 } 504 505 // Computes [num1 num0] / den 506 static uint udiv96_64(U num1, uint num0, U den) 507 { 508 // Extract both digits of the denominator 509 const den1 = cast(uint)(den >> divshift); 510 const den0 = cast(uint)(den & divmask); 511 // Estimate ret as num1 / den1, and then correct it 512 U ret = num1 / den1; 513 const t2 = (num1 % den1) * base + num0; 514 const t1 = ret * den0; 515 if (t1 > t2) 516 ret -= (t1 - t2 > den) ? 2 : 1; 517 return cast(uint)ret; 518 } 519 520 // Determine the normalization factor. We multiply c2 by this, so that its leading 521 // digit is at least half base. In binary this means just shifting left by the number 522 // of leading zeros, so that there's a 1 in the MSB. 523 // We also shift number by the same amount. This cannot overflow because c1.hi < c2. 524 const shift = (Ubits - 1) - bsr(c2); 525 c2 <<= shift; 526 U num2 = c1.hi; 527 num2 <<= shift; 528 num2 |= (c1.lo >> (-shift & 63)) & (-cast(I)shift >> 63); 529 c1.lo <<= shift; 530 531 // Extract the low digits of the numerator (after normalizing) 532 const num1 = cast(uint)(c1.lo >> divshift); 533 const num0 = cast(uint)(c1.lo & divmask); 534 535 // Compute q1 = [num2 num1] / c2 536 const q1 = udiv96_64(num2, num1, c2); 537 // Compute the true (partial) remainder 538 const rem = num2 * base + num1 - q1 * c2; 539 // Compute q0 = [rem num0] / c2 540 const q0 = udiv96_64(rem, num0, c2); 541 542 modulus = (rem * base + num0 - q0 * c2) >> shift; 543 return (cast(U)q1 << divshift) | q0; 544 } 545 546 // Special cases 547 if (!tst(c2)) 548 { 549 // Divide by zero 550 modulus = Zero; 551 return com(modulus); 552 } 553 if (c1.hi == 0 && c2.hi == 0) 554 { 555 // Single precision divide 556 const Cent rem = { lo:c1.lo % c2.lo }; 557 modulus = rem; 558 const Cent ret = { lo:c1.lo / c2.lo }; 559 return ret; 560 } 561 if (c1.hi == 0) 562 { 563 // Numerator is smaller than the divisor 564 modulus = c1; 565 return Zero; 566 } 567 if (c2.hi == 0) 568 { 569 // Divisor is a 64-bit value, so we just need one 128/64 division. 570 // If c1 / c2 would overflow, break c1 up into two halves. 571 const q1 = (c1.hi < c2.lo) ? 0 : (c1.hi / c2.lo); 572 if (q1) 573 c1.hi = c1.hi % c2.lo; 574 Cent rem; 575 const q0 = udivmod128_64(c1, c2.lo, rem.lo); 576 modulus = rem; 577 const Cent ret = { lo:q0, hi:q1 }; 578 return ret; 579 } 580 581 // Full cent precision division. 582 // Here c2 >= 2^^64 583 // We know that c2.hi != 0, so count leading zeros is OK 584 // We have 0 <= shift <= 63 585 const shift = (Ubits - 1) - bsr(c2.hi); 586 587 // Normalize the divisor so its MSB is 1 588 // v1 = (c2 << shift) >> 64 589 U v1 = shl(c2, shift).hi; 590 591 // To ensure no overflow. 592 Cent u1 = shr1(c1); 593 594 // Get quotient from divide unsigned operation. 595 U rem_ignored; 596 const Cent q1 = { lo:udivmod128_64(u1, v1, rem_ignored) }; 597 598 // Undo normalization and division of c1 by 2. 599 Cent quotient = shr(shl(q1, shift), 63); 600 601 // Make quotient correct or too small by 1 602 if (tst(quotient)) 603 quotient = dec(quotient); 604 605 // Now quotient is correct. 606 // Compute rem = c1 - (quotient * c2); 607 Cent rem = sub(c1, mul(quotient, c2)); 608 609 // Check if remainder is larger than the divisor 610 if (uge(rem, c2)) 611 { 612 // Increment quotient 613 quotient = inc(quotient); 614 // Subtract c2 from remainder 615 rem = sub(rem, c2); 616 } 617 modulus = rem; 618 //printf("quotient "); print(quotient); 619 //printf("modulus "); print(modulus); 620 return quotient; 621 } 622 623 624 /**************************** 625 * Signed divide c1 / c2. 626 * Params: 627 * c1 = dividend 628 * c2 = divisor 629 * Returns: 630 * quotient c1 / c2 631 */ 632 pure 633 Cent div(Cent c1, Cent c2) 634 { 635 Cent modulus; 636 return divmod(c1, c2, modulus); 637 } 638 639 /**************************** 640 * Signed divide c1 / c2. The remainder after division is stored to modulus. 641 * Params: 642 * c1 = dividend 643 * c2 = divisor 644 * modulus = set to c1 % c2 645 * Returns: 646 * quotient c1 / c2 647 */ 648 pure 649 Cent divmod(Cent c1, Cent c2, out Cent modulus) 650 { 651 /* Muck about with the signs so we can use the unsigned divide 652 */ 653 if (cast(I)c1.hi < 0) 654 { 655 if (cast(I)c2.hi < 0) 656 { 657 Cent r = udivmod(neg(c1), neg(c2), modulus); 658 modulus = neg(modulus); 659 return r; 660 } 661 Cent r = neg(udivmod(neg(c1), c2, modulus)); 662 modulus = neg(modulus); 663 return r; 664 } 665 else if (cast(I)c2.hi < 0) 666 { 667 return neg(udivmod(c1, neg(c2), modulus)); 668 } 669 else 670 return udivmod(c1, c2, modulus); 671 } 672 673 /**************************** 674 * If c1 > c2 unsigned 675 * Params: 676 * c1 = operand 1 677 * c2 = operand 2 678 * Returns: 679 * true if c1 > c2 680 */ 681 pure 682 bool ugt(Cent c1, Cent c2) 683 { 684 return (c1.hi == c2.hi) ? (c1.lo > c2.lo) : (c1.hi > c2.hi); 685 } 686 687 /**************************** 688 * If c1 >= c2 unsigned 689 * Params: 690 * c1 = operand 1 691 * c2 = operand 2 692 * Returns: 693 * true if c1 >= c2 694 */ 695 pure 696 bool uge(Cent c1, Cent c2) 697 { 698 return !ugt(c2, c1); 699 } 700 701 /**************************** 702 * If c1 < c2 unsigned 703 * Params: 704 * c1 = operand 1 705 * c2 = operand 2 706 * Returns: 707 * true if c1 < c2 708 */ 709 pure 710 bool ult(Cent c1, Cent c2) 711 { 712 return ugt(c2, c1); 713 } 714 715 /**************************** 716 * If c1 <= c2 unsigned 717 * Params: 718 * c1 = operand 1 719 * c2 = operand 2 720 * Returns: 721 * true if c1 <= c2 722 */ 723 pure 724 bool ule(Cent c1, Cent c2) 725 { 726 return !ugt(c1, c2); 727 } 728 729 /**************************** 730 * If c1 > c2 signed 731 * Params: 732 * c1 = operand 1 733 * c2 = operand 2 734 * Returns: 735 * true if c1 > c2 736 */ 737 pure 738 bool gt(Cent c1, Cent c2) 739 { 740 return (c1.hi == c2.hi) 741 ? (c1.lo > c2.lo) 742 : (cast(I)c1.hi > cast(I)c2.hi); 743 } 744 745 /**************************** 746 * If c1 >= c2 signed 747 * Params: 748 * c1 = operand 1 749 * c2 = operand 2 750 * Returns: 751 * true if c1 >= c2 752 */ 753 pure 754 bool ge(Cent c1, Cent c2) 755 { 756 return !gt(c2, c1); 757 } 758 759 /**************************** 760 * If c1 < c2 signed 761 * Params: 762 * c1 = operand 1 763 * c2 = operand 2 764 * Returns: 765 * true if c1 < c2 766 */ 767 pure 768 bool lt(Cent c1, Cent c2) 769 { 770 return gt(c2, c1); 771 } 772 773 /**************************** 774 * If c1 <= c2 signed 775 * Params: 776 * c1 = operand 1 777 * c2 = operand 2 778 * Returns: 779 * true if c1 <= c2 780 */ 781 pure 782 bool le(Cent c1, Cent c2) 783 { 784 return !gt(c1, c2); 785 } 786 787 /*******************************************************/ 788 789 version (unittest) 790 { 791 version (none) 792 { 793 import core.stdc.stdio; 794 795 @trusted 796 void print(Cent c) 797 { 798 printf("%lld, %lld\n", cast(ulong)c.lo, cast(ulong)c.hi); 799 printf("x%llx, x%llx\n", cast(ulong)c.lo, cast(ulong)c.hi); 800 } 801 } 802 } 803 804 unittest 805 { 806 const Cent C0 = Zero; 807 const Cent C1 = One; 808 const Cent C2 = { lo:2 }; 809 const Cent C3 = { lo:3 }; 810 const Cent C5 = { lo:5 }; 811 const Cent C10 = { lo:10 }; 812 const Cent C20 = { lo:20 }; 813 const Cent C30 = { lo:30 }; 814 const Cent C100 = { lo:100 }; 815 816 const Cent Cm1 = neg(One); 817 const Cent Cm3 = neg(C3); 818 const Cent Cm10 = neg(C10); 819 820 const Cent C3_1 = { lo:1, hi:3 }; 821 const Cent C3_2 = { lo:2, hi:3 }; 822 const Cent C4_8 = { lo:8, hi:4 }; 823 const Cent C5_0 = { lo:0, hi:5 }; 824 const Cent C7_1 = { lo:1, hi:7 }; 825 const Cent C7_9 = { lo:9, hi:7 }; 826 const Cent C9_3 = { lo:3, hi:9 }; 827 const Cent C10_0 = { lo:0, hi:10 }; 828 const Cent C10_1 = { lo:1, hi:10 }; 829 const Cent C10_3 = { lo:3, hi:10 }; 830 const Cent C11_3 = { lo:3, hi:11 }; 831 const Cent C20_0 = { lo:0, hi:20 }; 832 const Cent C90_30 = { lo:30, hi:90 }; 833 834 const Cent Cm10_0 = inc(com(C10_0)); // Cent(lo=0, hi=-10); 835 const Cent Cm10_1 = inc(com(C10_1)); // Cent(lo=-1, hi=-11); 836 const Cent Cm10_3 = inc(com(C10_3)); // Cent(lo=-3, hi=-11); 837 const Cent Cm20_0 = inc(com(C20_0)); // Cent(lo=0, hi=-20); 838 839 enum Cent Cs_3 = { lo:3, hi:I.min }; 840 841 const Cent Cbig_1 = { lo:0xa3ccac1832952398, hi:0xc3ac542864f652f8 }; 842 const Cent Cbig_2 = { lo:0x5267b85f8a42fc20, hi:0 }; 843 const Cent Cbig_3 = { lo:0xf0000000ffffffff, hi:0 }; 844 845 /************************/ 846 847 assert( ugt(C1, C0) ); 848 assert( ult(C1, C2) ); 849 assert( uge(C1, C0) ); 850 assert( ule(C1, C2) ); 851 852 assert( !ugt(C0, C1) ); 853 assert( !ult(C2, C1) ); 854 assert( !uge(C0, C1) ); 855 assert( !ule(C2, C1) ); 856 857 assert( !ugt(C1, C1) ); 858 assert( !ult(C1, C1) ); 859 assert( uge(C1, C1) ); 860 assert( ule(C2, C2) ); 861 862 assert( ugt(C10_3, C10_1) ); 863 assert( ugt(C11_3, C10_3) ); 864 assert( !ugt(C9_3, C10_3) ); 865 assert( !ugt(C9_3, C9_3) ); 866 867 assert( gt(C2, C1) ); 868 assert( !gt(C1, C2) ); 869 assert( !gt(C1, C1) ); 870 assert( gt(C0, Cm1) ); 871 assert( gt(Cm1, neg(C10))); 872 assert( !gt(Cm1, Cm1) ); 873 assert( !gt(Cm1, C0) ); 874 875 assert( !lt(C2, C1) ); 876 assert( !le(C2, C1) ); 877 assert( ge(C2, C1) ); 878 879 assert(neg(C10_0) == Cm10_0); 880 assert(neg(C10_1) == Cm10_1); 881 assert(neg(C10_3) == Cm10_3); 882 883 assert(add(C7_1,C3_2) == C10_3); 884 assert(sub(C1,C2) == Cm1); 885 886 assert(inc(C3_1) == C3_2); 887 assert(dec(C3_2) == C3_1); 888 889 assert(shl(C10,0) == C10); 890 assert(shl(C10,Ubits) == C10_0); 891 assert(shl(C10,1) == C20); 892 assert(shl(C10,Ubits * 2) == C0); 893 assert(shr(C10_0,0) == C10_0); 894 assert(shr(C10_0,Ubits) == C10); 895 assert(shr(C10_0,Ubits - 1) == C20); 896 assert(shr(C10_0,Ubits + 1) == C5); 897 assert(shr(C10_0,Ubits * 2) == C0); 898 assert(sar(C10_0,0) == C10_0); 899 assert(sar(C10_0,Ubits) == C10); 900 assert(sar(C10_0,Ubits - 1) == C20); 901 assert(sar(C10_0,Ubits + 1) == C5); 902 assert(sar(C10_0,Ubits * 2) == C0); 903 assert(sar(Cm1,Ubits * 2) == Cm1); 904 905 assert(shl1(C10) == C20); 906 assert(shr1(C10_0) == C5_0); 907 assert(sar1(C10_0) == C5_0); 908 assert(sar1(Cm1) == Cm1); 909 910 Cent modulus; 911 912 assert(udiv(C10,C2) == C5); 913 assert(udivmod(C10,C2, modulus) == C5); assert(modulus == C0); 914 assert(udivmod(C10,C3, modulus) == C3); assert(modulus == C1); 915 assert(udivmod(C10,C0, modulus) == Cm1); assert(modulus == C0); 916 assert(udivmod(C2,C90_30, modulus) == C0); assert(modulus == C2); 917 assert(udiv(mul(C90_30, C2), C2) == C90_30); 918 assert(udiv(mul(C90_30, C2), C90_30) == C2); 919 920 assert(div(C10,C3) == C3); 921 assert(divmod( C10, C3, modulus) == C3); assert(modulus == C1); 922 assert(divmod(Cm10, C3, modulus) == Cm3); assert(modulus == Cm1); 923 assert(divmod( C10, Cm3, modulus) == Cm3); assert(modulus == C1); 924 assert(divmod(Cm10, Cm3, modulus) == C3); assert(modulus == Cm1); 925 assert(divmod(C2, C90_30, modulus) == C0); assert(modulus == C2); 926 assert(div(mul(C90_30, C2), C2) == C90_30); 927 assert(div(mul(C90_30, C2), C90_30) == C2); 928 929 const Cent Cb1divb2 = { lo:0x4496aa309d4d4a2f, hi:U.max }; 930 const Cent Cb1modb2 = { lo:0xd83203d0fdc799b8, hi:U.max }; 931 assert(divmod(Cbig_1, Cbig_2, modulus) == Cb1divb2); 932 assert(modulus == Cb1modb2); 933 934 const Cent Cb1udivb2 = { lo:0x5fe0e9bace2bedad, hi:2 }; 935 const Cent Cb1umodb2 = { lo:0x2c923125a68721f8, hi:0 }; 936 assert(udivmod(Cbig_1, Cbig_2, modulus) == Cb1udivb2); 937 assert(modulus == Cb1umodb2); 938 939 const Cent Cb1divb3 = { lo:0xbfa6c02b5aff8b86, hi:U.max }; 940 const Cent Cb1udivb3 = { lo:0xd0b7d13b48cb350f, hi:0 }; 941 assert(div(Cbig_1, Cbig_3) == Cb1divb3); 942 assert(udiv(Cbig_1, Cbig_3) == Cb1udivb3); 943 944 assert(mul(Cm10, C1) == Cm10); 945 assert(mul(C1, Cm10) == Cm10); 946 assert(mul(C9_3, C10) == C90_30); 947 assert(mul(Cs_3, C10) == C30); 948 assert(mul(Cm10, Cm10) == C100); 949 assert(mul(C20_0, Cm1) == Cm20_0); 950 951 assert( or(C4_8, C3_1) == C7_9); 952 assert(and(C4_8, C7_9) == C4_8); 953 assert(xor(C4_8, C7_9) == C3_1); 954 955 assert(rol(Cm1, 1) == Cm1); 956 assert(ror(Cm1, 45) == Cm1); 957 assert(rol(ror(C7_9, 5), 5) == C7_9); 958 assert(rol(C7_9, 1) == rol1(C7_9)); 959 assert(ror(C7_9, 1) == ror1(C7_9)); 960 }