authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-15 22:17:22-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-16 02:22:19-05:00
log84d8584c5b315c24a00fa444d758a6b78f80f4a0
tree76abeff3b41fb696d59902b59ef7dd73ee0c61c6
parent92fc5947fc18ea077f0e02bc4758e9050270e4bb

implement bigint div and rem

See #405

3 files changed, 458 insertions(+), 11 deletions(-)

README.md+4-1
...@@ -125,17 +125,20 @@ libc. Create demo games using Zig....@@ -125,17 +125,20 @@ libc. Create demo games using Zig.
125125
126##### POSIX126##### POSIX
127127
128 * gcc >= 5.0.0 or clang >= 3.6.0
129 * cmake >= 2.8.5128 * cmake >= 2.8.5
129 * gcc >= 5.0.0 or clang >= 3.6.0
130 * LLVM, Clang, LLD libraries == 5.x, compiled with the same gcc or clang version above130 * LLVM, Clang, LLD libraries == 5.x, compiled with the same gcc or clang version above
131131
132##### Windows132##### Windows
133133
134 * cmake >= 2.8.5
134 * Microsoft Visual Studio 2015135 * Microsoft Visual Studio 2015
135 * LLVM, Clang, LLD libraries == 5.x, compiled with the same MSVC version above136 * LLVM, Clang, LLD libraries == 5.x, compiled with the same MSVC version above
136137
137#### Instructions138#### Instructions
138139
140##### POSIX
141
139If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`,142If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`,
140`ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to143`ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to
141(example below).144(example below).
src/bigint.cpp+432-10
...@@ -12,6 +12,9 @@...@@ -12,6 +12,9 @@
12#include "os.hpp"12#include "os.hpp"
13#include "softfloat.hpp"13#include "softfloat.hpp"
1414
15#include <limits>
16#include <algorithm>
17
15static void bigint_normalize(BigInt *dest) {18static void bigint_normalize(BigInt *dest) {
16 const uint64_t *digits = bigint_ptr(dest);19 const uint64_t *digits = bigint_ptr(dest);
1720
...@@ -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;
541544
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}
672675
676enum 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
685template <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)
704template <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)
720template <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.
744template <typename T>
745std::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.
753constexpr 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.
758constexpr 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.
763constexpr 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.
771static 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
892static 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
673void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2) {1037void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2) {
674 assert(op2->digit_count != 0); // division by zero1038 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 divisor1119 // 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}
test/cases/math.zig+22
...@@ -26,6 +26,28 @@ fn testDivision() {...@@ -26,6 +26,28 @@ fn testDivision() {
26 assert(divTrunc(i32, -5, 3) == -1);26 assert(divTrunc(i32, -5, 3) == -1);
27 assert(divTrunc(f32, 5.0, 3.0) == 1.0);27 assert(divTrunc(f32, 5.0, 3.0) == 1.0);
28 assert(divTrunc(f32, -5.0, 3.0) == -1.0);28 assert(divTrunc(f32, -5.0, 3.0) == -1.0);
29
30 comptime {
31 assert(
32 1194735857077236777412821811143690633098347576 %
33 508740759824825164163191790951174292733114988 ==
34 177254337427586449086438229241342047632117600);
35 assert(@rem(-1194735857077236777412821811143690633098347576,
36 508740759824825164163191790951174292733114988) ==
37 -177254337427586449086438229241342047632117600);
38 assert(1194735857077236777412821811143690633098347576 /
39 508740759824825164163191790951174292733114988 ==
40 2);
41 assert(@divTrunc(-1194735857077236777412821811143690633098347576,
42 508740759824825164163191790951174292733114988) ==
43 -2);
44 assert(@divTrunc(1194735857077236777412821811143690633098347576,
45 -508740759824825164163191790951174292733114988) ==
46 -2);
47 assert(@divTrunc(-1194735857077236777412821811143690633098347576,
48 -508740759824825164163191790951174292733114988) ==
49 2);
50 }
29}51}
30fn div(comptime T: type, a: T, b: T) -> T {52fn div(comptime T: type, a: T, b: T) -> T {
31 return a / b;53 return a / b;