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