| ... | @@ -12,6 +12,9 @@ | ... | @@ -12,6 +12,9 @@ |
| 12 | #include "os.hpp" | 12 | #include "os.hpp" |
| 13 | #include "softfloat.hpp" | 13 | #include "softfloat.hpp" |
| 14 | | 14 | |
| | 15 | #include <limits> |
| | 16 | #include <algorithm> |
| | 17 | |
| 15 | static void bigint_normalize(BigInt *dest) { | 18 | static void bigint_normalize(BigInt *dest) { |
| 16 | const uint64_t *digits = bigint_ptr(dest); | 19 | const uint64_t *digits = bigint_ptr(dest); |
| 17 | | 20 | |
| ... | @@ -539,7 +542,7 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -539,7 +542,7 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 539 | dest->data.digits[i] = x; | 542 | dest->data.digits[i] = x; |
| 540 | i += 1; | 543 | i += 1; |
| 541 | | 544 | |
| 542 | if (!found_digit) | 545 | if (!found_digit || i >= bigger_op->digit_count) |
| 543 | break; | 546 | break; |
| 544 | } | 547 | } |
| 545 | assert(overflow == 0); | 548 | assert(overflow == 0); |
| ... | @@ -670,19 +673,409 @@ void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t | ... | @@ -670,19 +673,409 @@ void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t |
| 670 | bigint_truncate(dest, &unwrapped, bit_count, is_signed); | 673 | bigint_truncate(dest, &unwrapped, bit_count, is_signed); |
| 671 | } | 674 | } |
| 672 | | 675 | |
| | 676 | enum ZeroBehavior { |
| | 677 | /// \brief The returned value is undefined. |
| | 678 | ZB_Undefined, |
| | 679 | /// \brief The returned value is numeric_limits<T>::max() |
| | 680 | ZB_Max, |
| | 681 | /// \brief The returned value is numeric_limits<T>::digits |
| | 682 | ZB_Width |
| | 683 | }; |
| | 684 | |
| | 685 | template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { |
| | 686 | static std::size_t count(T Val, ZeroBehavior) { |
| | 687 | if (!Val) |
| | 688 | return std::numeric_limits<T>::digits; |
| | 689 | |
| | 690 | // Bisection method. |
| | 691 | std::size_t ZeroBits = 0; |
| | 692 | for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { |
| | 693 | T Tmp = Val >> Shift; |
| | 694 | if (Tmp) |
| | 695 | Val = Tmp; |
| | 696 | else |
| | 697 | ZeroBits |= Shift; |
| | 698 | } |
| | 699 | return ZeroBits; |
| | 700 | } |
| | 701 | }; |
| | 702 | |
| | 703 | #if __GNUC__ >= 4 || defined(_MSC_VER) |
| | 704 | template <typename T> struct LeadingZerosCounter<T, 4> { |
| | 705 | static std::size_t count(T Val, ZeroBehavior ZB) { |
| | 706 | if (ZB != ZB_Undefined && Val == 0) |
| | 707 | return 32; |
| | 708 | |
| | 709 | #if defined(_MSC_VER) |
| | 710 | unsigned long Index; |
| | 711 | _BitScanReverse(&Index, Val); |
| | 712 | return Index ^ 31; |
| | 713 | #else |
| | 714 | return __builtin_clz(Val); |
| | 715 | #endif |
| | 716 | } |
| | 717 | }; |
| | 718 | |
| | 719 | #if !defined(_MSC_VER) || defined(_M_X64) |
| | 720 | template <typename T> struct LeadingZerosCounter<T, 8> { |
| | 721 | static std::size_t count(T Val, ZeroBehavior ZB) { |
| | 722 | if (ZB != ZB_Undefined && Val == 0) |
| | 723 | return 64; |
| | 724 | |
| | 725 | #if defined(_MSC_VER) |
| | 726 | unsigned long Index; |
| | 727 | _BitScanReverse64(&Index, Val); |
| | 728 | return Index ^ 63; |
| | 729 | #else |
| | 730 | return __builtin_clzll(Val); |
| | 731 | #endif |
| | 732 | } |
| | 733 | }; |
| | 734 | #endif |
| | 735 | #endif |
| | 736 | |
| | 737 | /// \brief Count number of 0's from the most significant bit to the least |
| | 738 | /// stopping at the first 1. |
| | 739 | /// |
| | 740 | /// Only unsigned integral types are allowed. |
| | 741 | /// |
| | 742 | /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are |
| | 743 | /// valid arguments. |
| | 744 | template <typename T> |
| | 745 | std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { |
| | 746 | static_assert(std::numeric_limits<T>::is_integer && |
| | 747 | !std::numeric_limits<T>::is_signed, |
| | 748 | "Only unsigned integral types are allowed."); |
| | 749 | return LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB); |
| | 750 | } |
| | 751 | |
| | 752 | /// Make a 64-bit integer from a high / low pair of 32-bit integers. |
| | 753 | constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { |
| | 754 | return ((uint64_t)High << 32) | (uint64_t)Low; |
| | 755 | } |
| | 756 | |
| | 757 | /// Return the high 32 bits of a 64 bit value. |
| | 758 | constexpr inline uint32_t Hi_32(uint64_t Value) { |
| | 759 | return static_cast<uint32_t>(Value >> 32); |
| | 760 | } |
| | 761 | |
| | 762 | /// Return the low 32 bits of a 64 bit value. |
| | 763 | constexpr inline uint32_t Lo_32(uint64_t Value) { |
| | 764 | return static_cast<uint32_t>(Value); |
| | 765 | } |
| | 766 | |
| | 767 | /// Implementation of Knuth's Algorithm D (Division of nonnegative integers) |
| | 768 | /// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The |
| | 769 | /// variables here have the same names as in the algorithm. Comments explain |
| | 770 | /// the algorithm and any deviation from it. |
| | 771 | static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, |
| | 772 | unsigned m, unsigned n) |
| | 773 | { |
| | 774 | assert(u && "Must provide dividend"); |
| | 775 | assert(v && "Must provide divisor"); |
| | 776 | assert(q && "Must provide quotient"); |
| | 777 | assert(u != v && u != q && v != q && "Must use different memory"); |
| | 778 | assert(n>1 && "n must be > 1"); |
| | 779 | |
| | 780 | // b denotes the base of the number system. In our case b is 2^32. |
| | 781 | const uint64_t b = uint64_t(1) << 32; |
| | 782 | |
| | 783 | // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of |
| | 784 | // u and v by d. Note that we have taken Knuth's advice here to use a power |
| | 785 | // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of |
| | 786 | // 2 allows us to shift instead of multiply and it is easy to determine the |
| | 787 | // shift amount from the leading zeros. We are basically normalizing the u |
| | 788 | // and v so that its high bits are shifted to the top of v's range without |
| | 789 | // overflow. Note that this can require an extra word in u so that u must |
| | 790 | // be of length m+n+1. |
| | 791 | unsigned shift = countLeadingZeros(v[n-1]); |
| | 792 | uint32_t v_carry = 0; |
| | 793 | uint32_t u_carry = 0; |
| | 794 | if (shift) { |
| | 795 | for (unsigned i = 0; i < m+n; ++i) { |
| | 796 | uint32_t u_tmp = u[i] >> (32 - shift); |
| | 797 | u[i] = (u[i] << shift) | u_carry; |
| | 798 | u_carry = u_tmp; |
| | 799 | } |
| | 800 | for (unsigned i = 0; i < n; ++i) { |
| | 801 | uint32_t v_tmp = v[i] >> (32 - shift); |
| | 802 | v[i] = (v[i] << shift) | v_carry; |
| | 803 | v_carry = v_tmp; |
| | 804 | } |
| | 805 | } |
| | 806 | u[m+n] = u_carry; |
| | 807 | |
| | 808 | // D2. [Initialize j.] Set j to m. This is the loop counter over the places. |
| | 809 | int j = m; |
| | 810 | do { |
| | 811 | // D3. [Calculate q'.]. |
| | 812 | // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') |
| | 813 | // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') |
| | 814 | // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease |
| | 815 | // qp by 1, increase rp by v[n-1], and repeat this test if rp < b. The test |
| | 816 | // on v[n-2] determines at high speed most of the cases in which the trial |
| | 817 | // value qp is one too large, and it eliminates all cases where qp is two |
| | 818 | // too large. |
| | 819 | uint64_t dividend = Make_64(u[j+n], u[j+n-1]); |
| | 820 | uint64_t qp = dividend / v[n-1]; |
| | 821 | uint64_t rp = dividend % v[n-1]; |
| | 822 | if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { |
| | 823 | qp--; |
| | 824 | rp += v[n-1]; |
| | 825 | if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) |
| | 826 | qp--; |
| | 827 | } |
| | 828 | |
| | 829 | // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with |
| | 830 | // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation |
| | 831 | // consists of a simple multiplication by a one-place number, combined with |
| | 832 | // a subtraction. |
| | 833 | // The digits (u[j+n]...u[j]) should be kept positive; if the result of |
| | 834 | // this step is actually negative, (u[j+n]...u[j]) should be left as the |
| | 835 | // true value plus b**(n+1), namely as the b's complement of |
| | 836 | // the true value, and a "borrow" to the left should be remembered. |
| | 837 | int64_t borrow = 0; |
| | 838 | for (unsigned i = 0; i < n; ++i) { |
| | 839 | uint64_t p = uint64_t(qp) * uint64_t(v[i]); |
| | 840 | int64_t subres = int64_t(u[j+i]) - borrow - Lo_32(p); |
| | 841 | u[j+i] = Lo_32(subres); |
| | 842 | borrow = Hi_32(p) - Hi_32(subres); |
| | 843 | } |
| | 844 | bool isNeg = u[j+n] < borrow; |
| | 845 | u[j+n] -= Lo_32(borrow); |
| | 846 | |
| | 847 | // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was |
| | 848 | // negative, go to step D6; otherwise go on to step D7. |
| | 849 | q[j] = Lo_32(qp); |
| | 850 | if (isNeg) { |
| | 851 | // D6. [Add back]. The probability that this step is necessary is very |
| | 852 | // small, on the order of only 2/b. Make sure that test data accounts for |
| | 853 | // this possibility. Decrease q[j] by 1 |
| | 854 | q[j]--; |
| | 855 | // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). |
| | 856 | // A carry will occur to the left of u[j+n], and it should be ignored |
| | 857 | // since it cancels with the borrow that occurred in D4. |
| | 858 | bool carry = false; |
| | 859 | for (unsigned i = 0; i < n; i++) { |
| | 860 | uint32_t limit = std::min(u[j+i],v[i]); |
| | 861 | u[j+i] += v[i] + carry; |
| | 862 | carry = u[j+i] < limit || (carry && u[j+i] == limit); |
| | 863 | } |
| | 864 | u[j+n] += carry; |
| | 865 | } |
| | 866 | |
| | 867 | // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. |
| | 868 | } while (--j >= 0); |
| | 869 | |
| | 870 | // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired |
| | 871 | // remainder may be obtained by dividing u[...] by d. If r is non-null we |
| | 872 | // compute the remainder (urem uses this). |
| | 873 | if (r) { |
| | 874 | // The value d is expressed by the "shift" value above since we avoided |
| | 875 | // multiplication by d by using a shift left. So, all we have to do is |
| | 876 | // shift right here. |
| | 877 | if (shift) { |
| | 878 | uint32_t carry = 0; |
| | 879 | for (int i = n-1; i >= 0; i--) { |
| | 880 | r[i] = (u[i] >> shift) | carry; |
| | 881 | carry = u[i] << (32 - shift); |
| | 882 | } |
| | 883 | } else { |
| | 884 | for (int i = n-1; i >= 0; i--) { |
| | 885 | r[i] = u[i]; |
| | 886 | } |
| | 887 | } |
| | 888 | } |
| | 889 | } |
| | 890 | |
| | 891 | // Implementation ported from LLVM/lib/Support/APInt.cpp |
| | 892 | static void bigint_unsigned_division(const BigInt *op1, const BigInt *op2, BigInt *Quotient, BigInt *Remainder) { |
| | 893 | Cmp cmp = bigint_cmp(op1, op2); |
| | 894 | if (cmp == CmpLT) { |
| | 895 | if (Quotient != nullptr) { |
| | 896 | bigint_init_unsigned(Quotient, 0); |
| | 897 | } |
| | 898 | if (Remainder != nullptr) { |
| | 899 | bigint_init_bigint(Remainder, op1); |
| | 900 | } |
| | 901 | return; |
| | 902 | } |
| | 903 | if (cmp == CmpEQ) { |
| | 904 | if (Quotient != nullptr) { |
| | 905 | bigint_init_unsigned(Quotient, 1); |
| | 906 | } |
| | 907 | if (Remainder != nullptr) { |
| | 908 | bigint_init_unsigned(Remainder, 0); |
| | 909 | } |
| | 910 | return; |
| | 911 | } |
| | 912 | |
| | 913 | const uint64_t *LHS = bigint_ptr(op1); |
| | 914 | const uint64_t *RHS = bigint_ptr(op2); |
| | 915 | unsigned lhsWords = op1->digit_count; |
| | 916 | unsigned rhsWords = op2->digit_count; |
| | 917 | |
| | 918 | // First, compose the values into an array of 32-bit words instead of |
| | 919 | // 64-bit words. This is a necessity of both the "short division" algorithm |
| | 920 | // and the Knuth "classical algorithm" which requires there to be native |
| | 921 | // operations for +, -, and * on an m bit value with an m*2 bit result. We |
| | 922 | // can't use 64-bit operands here because we don't have native results of |
| | 923 | // 128-bits. Furthermore, casting the 64-bit values to 32-bit values won't |
| | 924 | // work on large-endian machines. |
| | 925 | unsigned n = rhsWords * 2; |
| | 926 | unsigned m = (lhsWords * 2) - n; |
| | 927 | |
| | 928 | // Allocate space for the temporary values we need either on the stack, if |
| | 929 | // it will fit, or on the heap if it won't. |
| | 930 | uint32_t SPACE[128]; |
| | 931 | uint32_t *U = nullptr; |
| | 932 | uint32_t *V = nullptr; |
| | 933 | uint32_t *Q = nullptr; |
| | 934 | uint32_t *R = nullptr; |
| | 935 | if ((Remainder?4:3)*n+2*m+1 <= 128) { |
| | 936 | U = &SPACE[0]; |
| | 937 | V = &SPACE[m+n+1]; |
| | 938 | Q = &SPACE[(m+n+1) + n]; |
| | 939 | if (Remainder) |
| | 940 | R = &SPACE[(m+n+1) + n + (m+n)]; |
| | 941 | } else { |
| | 942 | U = new uint32_t[m + n + 1]; |
| | 943 | V = new uint32_t[n]; |
| | 944 | Q = new uint32_t[m+n]; |
| | 945 | if (Remainder) |
| | 946 | R = new uint32_t[n]; |
| | 947 | } |
| | 948 | |
| | 949 | // Initialize the dividend |
| | 950 | memset(U, 0, (m+n+1)*sizeof(uint32_t)); |
| | 951 | for (unsigned i = 0; i < lhsWords; ++i) { |
| | 952 | uint64_t tmp = LHS[i]; |
| | 953 | U[i * 2] = Lo_32(tmp); |
| | 954 | U[i * 2 + 1] = Hi_32(tmp); |
| | 955 | } |
| | 956 | U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. |
| | 957 | |
| | 958 | // Initialize the divisor |
| | 959 | memset(V, 0, (n)*sizeof(uint32_t)); |
| | 960 | for (unsigned i = 0; i < rhsWords; ++i) { |
| | 961 | uint64_t tmp = RHS[i]; |
| | 962 | V[i * 2] = Lo_32(tmp); |
| | 963 | V[i * 2 + 1] = Hi_32(tmp); |
| | 964 | } |
| | 965 | |
| | 966 | // initialize the quotient and remainder |
| | 967 | memset(Q, 0, (m+n) * sizeof(uint32_t)); |
| | 968 | if (Remainder) |
| | 969 | memset(R, 0, n * sizeof(uint32_t)); |
| | 970 | |
| | 971 | // Now, adjust m and n for the Knuth division. n is the number of words in |
| | 972 | // the divisor. m is the number of words by which the dividend exceeds the |
| | 973 | // divisor (i.e. m+n is the length of the dividend). These sizes must not |
| | 974 | // contain any zero words or the Knuth algorithm fails. |
| | 975 | for (unsigned i = n; i > 0 && V[i-1] == 0; i--) { |
| | 976 | n--; |
| | 977 | m++; |
| | 978 | } |
| | 979 | for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--) |
| | 980 | m--; |
| | 981 | |
| | 982 | // If we're left with only a single word for the divisor, Knuth doesn't work |
| | 983 | // so we implement the short division algorithm here. This is much simpler |
| | 984 | // and faster because we are certain that we can divide a 64-bit quantity |
| | 985 | // by a 32-bit quantity at hardware speed and short division is simply a |
| | 986 | // series of such operations. This is just like doing short division but we |
| | 987 | // are using base 2^32 instead of base 10. |
| | 988 | assert(n != 0 && "Divide by zero?"); |
| | 989 | if (n == 1) { |
| | 990 | uint32_t divisor = V[0]; |
| | 991 | uint32_t remainder = 0; |
| | 992 | for (int i = m; i >= 0; i--) { |
| | 993 | uint64_t partial_dividend = Make_64(remainder, U[i]); |
| | 994 | if (partial_dividend == 0) { |
| | 995 | Q[i] = 0; |
| | 996 | remainder = 0; |
| | 997 | } else if (partial_dividend < divisor) { |
| | 998 | Q[i] = 0; |
| | 999 | remainder = Lo_32(partial_dividend); |
| | 1000 | } else if (partial_dividend == divisor) { |
| | 1001 | Q[i] = 1; |
| | 1002 | remainder = 0; |
| | 1003 | } else { |
| | 1004 | Q[i] = Lo_32(partial_dividend / divisor); |
| | 1005 | remainder = Lo_32(partial_dividend - (Q[i] * divisor)); |
| | 1006 | } |
| | 1007 | } |
| | 1008 | if (R) |
| | 1009 | R[0] = remainder; |
| | 1010 | } else { |
| | 1011 | // Now we're ready to invoke the Knuth classical divide algorithm. In this |
| | 1012 | // case n > 1. |
| | 1013 | KnuthDiv(U, V, Q, R, m, n); |
| | 1014 | } |
| | 1015 | |
| | 1016 | // If the caller wants the quotient |
| | 1017 | if (Quotient) { |
| | 1018 | Quotient->digit_count = lhsWords; |
| | 1019 | Quotient->data.digits = allocate<uint64_t>(lhsWords); |
| | 1020 | Quotient->is_negative = false; |
| | 1021 | for (size_t i = 0; i < lhsWords; i += 1) { |
| | 1022 | Quotient->data.digits[i] = Make_64(Q[i*2+1], Q[i*2]); |
| | 1023 | } |
| | 1024 | } |
| | 1025 | |
| | 1026 | // If the caller wants the remainder |
| | 1027 | if (Remainder) { |
| | 1028 | Remainder->digit_count = rhsWords; |
| | 1029 | Remainder->data.digits = allocate<uint64_t>(rhsWords); |
| | 1030 | Remainder->is_negative = false; |
| | 1031 | for (size_t i = 0; i < rhsWords; i += 1) { |
| | 1032 | Remainder->data.digits[i] = Make_64(R[i*2+1], R[i*2]); |
| | 1033 | } |
| | 1034 | } |
| | 1035 | } |
| | 1036 | |
| 673 | void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2) { | 1037 | void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 674 | assert(op2->digit_count != 0); // division by zero | 1038 | assert(op2->digit_count != 0); // division by zero |
| 675 | if (op1->digit_count == 0) { | 1039 | if (op1->digit_count == 0) { |
| 676 | bigint_init_unsigned(dest, 0); | 1040 | bigint_init_unsigned(dest, 0); |
| 677 | return; | 1041 | return; |
| 678 | } | 1042 | } |
| 679 | if (op1->digit_count != 1 || op2->digit_count != 1) { | | |
| 680 | zig_panic("TODO bigint div_trunc with >1 digits"); | | |
| 681 | } | | |
| 682 | const uint64_t *op1_digits = bigint_ptr(op1); | 1043 | const uint64_t *op1_digits = bigint_ptr(op1); |
| 683 | const uint64_t *op2_digits = bigint_ptr(op2); | 1044 | const uint64_t *op2_digits = bigint_ptr(op2); |
| 684 | dest->data.digit = op1_digits[0] / op2_digits[0]; | 1045 | if (op1->digit_count == 1 && op2->digit_count == 1) { |
| 685 | dest->digit_count = 1; | 1046 | dest->data.digit = op1_digits[0] / op2_digits[0]; |
| | 1047 | dest->digit_count = 1; |
| | 1048 | dest->is_negative = op1->is_negative != op2->is_negative; |
| | 1049 | bigint_normalize(dest); |
| | 1050 | return; |
| | 1051 | } |
| | 1052 | if (op2->digit_count == 1 && op2_digits[0] == 1) { |
| | 1053 | // X / 1 == X |
| | 1054 | bigint_init_bigint(dest, op1); |
| | 1055 | dest->is_negative = op1->is_negative != op2->is_negative; |
| | 1056 | bigint_normalize(dest); |
| | 1057 | return; |
| | 1058 | } |
| | 1059 | |
| | 1060 | const BigInt *op1_positive; |
| | 1061 | BigInt op1_positive_data; |
| | 1062 | if (op1->is_negative) { |
| | 1063 | bigint_negate(&op1_positive_data, op1); |
| | 1064 | op1_positive = &op1_positive_data; |
| | 1065 | } else { |
| | 1066 | op1_positive = op1; |
| | 1067 | } |
| | 1068 | |
| | 1069 | const BigInt *op2_positive; |
| | 1070 | BigInt op2_positive_data; |
| | 1071 | if (op2->is_negative) { |
| | 1072 | bigint_negate(&op2_positive_data, op2); |
| | 1073 | op2_positive = &op2_positive_data; |
| | 1074 | } else { |
| | 1075 | op2_positive = op2; |
| | 1076 | } |
| | 1077 | |
| | 1078 | bigint_unsigned_division(op1_positive, op2_positive, dest, nullptr); |
| 686 | dest->is_negative = op1->is_negative != op2->is_negative; | 1079 | dest->is_negative = op1->is_negative != op2->is_negative; |
| 687 | bigint_normalize(dest); | 1080 | bigint_normalize(dest); |
| 688 | } | 1081 | } |
| ... | @@ -714,6 +1107,14 @@ void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -714,6 +1107,14 @@ void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 714 | } | 1107 | } |
| 715 | const uint64_t *op1_digits = bigint_ptr(op1); | 1108 | const uint64_t *op1_digits = bigint_ptr(op1); |
| 716 | const uint64_t *op2_digits = bigint_ptr(op2); | 1109 | const uint64_t *op2_digits = bigint_ptr(op2); |
| | 1110 | |
| | 1111 | if (op1->digit_count == 1 && op2->digit_count == 1) { |
| | 1112 | dest->data.digit = op1_digits[0] % op2_digits[0]; |
| | 1113 | dest->digit_count = 1; |
| | 1114 | dest->is_negative = op1->is_negative; |
| | 1115 | bigint_normalize(dest); |
| | 1116 | return; |
| | 1117 | } |
| 717 | if (op2->digit_count == 2 && op2_digits[0] == 0 && op2_digits[1] == 1) { | 1118 | if (op2->digit_count == 2 && op2_digits[0] == 0 && op2_digits[1] == 1) { |
| 718 | // special case this divisor | 1119 | // special case this divisor |
| 719 | bigint_init_unsigned(dest, op1_digits[0]); | 1120 | bigint_init_unsigned(dest, op1_digits[0]); |
| ... | @@ -721,11 +1122,32 @@ void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -721,11 +1122,32 @@ void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 721 | bigint_normalize(dest); | 1122 | bigint_normalize(dest); |
| 722 | return; | 1123 | return; |
| 723 | } | 1124 | } |
| 724 | if (op1->digit_count != 1 || op2->digit_count != 1) { | 1125 | |
| 725 | zig_panic("TODO bigint rem with >1 digits"); | 1126 | if (op2->digit_count == 1 && op2_digits[0] == 1) { |
| | 1127 | // X % 1 == 0 |
| | 1128 | bigint_init_unsigned(dest, 0); |
| | 1129 | return; |
| 726 | } | 1130 | } |
| 727 | dest->data.digit = op1_digits[0] % op2_digits[0]; | 1131 | |
| 728 | dest->digit_count = 1; | 1132 | const BigInt *op1_positive; |
| | 1133 | BigInt op1_positive_data; |
| | 1134 | if (op1->is_negative) { |
| | 1135 | bigint_negate(&op1_positive_data, op1); |
| | 1136 | op1_positive = &op1_positive_data; |
| | 1137 | } else { |
| | 1138 | op1_positive = op1; |
| | 1139 | } |
| | 1140 | |
| | 1141 | const BigInt *op2_positive; |
| | 1142 | BigInt op2_positive_data; |
| | 1143 | if (op2->is_negative) { |
| | 1144 | bigint_negate(&op2_positive_data, op2); |
| | 1145 | op2_positive = &op2_positive_data; |
| | 1146 | } else { |
| | 1147 | op2_positive = op2; |
| | 1148 | } |
| | 1149 | |
| | 1150 | bigint_unsigned_division(op1_positive, op2_positive, nullptr, dest); |
| 729 | dest->is_negative = op1->is_negative; | 1151 | dest->is_negative = op1->is_negative; |
| 730 | bigint_normalize(dest); | 1152 | bigint_normalize(dest); |
| 731 | } | 1153 | } |