diff --git a/py/mpz.c b/py/mpz.c index 2c0269981..100d2832c 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -491,7 +491,7 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, for (mpz_dig_t *den = den_dig, carry = 0; den < den_dig + den_len; ++den) { mpz_dig_t d = *den; *den = ((d << norm_shift) | carry) & DIG_MASK; - carry = d >> (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)d >> (DIG_SIZE - norm_shift); } // now need to shift numerator by same amount as denominator @@ -501,7 +501,7 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, for (mpz_dig_t *num = num_dig, carry = 0; num < num_dig + *num_len; ++num) { mpz_dig_t n = *num; *num = ((n << norm_shift) | carry) & DIG_MASK; - carry = n >> (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)n >> (DIG_SIZE - norm_shift); } // cache the leading digit of the denominator @@ -618,14 +618,14 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, for (mpz_dig_t *den = den_dig + den_len - 1, carry = 0; den >= den_dig; --den) { mpz_dig_t d = *den; *den = ((d >> norm_shift) | carry) & DIG_MASK; - carry = d << (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)d << (DIG_SIZE - norm_shift); } // unnormalise numerator (remainder now) for (mpz_dig_t *num = orig_num_dig + *num_len - 1, carry = 0; num >= orig_num_dig; --num) { mpz_dig_t n = *num; *num = ((n >> norm_shift) | carry) & DIG_MASK; - carry = n << (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)n << (DIG_SIZE - norm_shift); } // strip trailing zeros diff --git a/tests/basics/int_big_div.py b/tests/basics/int_big_div.py index 8dacf495d..642f051d4 100644 --- a/tests/basics/int_big_div.py +++ b/tests/basics/int_big_div.py @@ -1,3 +1,10 @@ for lhs in (1000000000000000000000000, 10000000000100000000000000, 10012003400000000000000007, 12349083434598210349871029923874109871234789): for rhs in range(1, 555): print(lhs // rhs) + +# these check an edge case on 64-bit machines where two mpz limbs +# are used and the most significant one has the MSB set +x = 0x8000000000000000 +print((x + 1) // x) +x = 0x86c60128feff5330 +print((x + 1) // x) diff --git a/tests/basics/int_big_mod.py b/tests/basics/int_big_mod.py index 77c0ffc46..f383553c1 100644 --- a/tests/basics/int_big_mod.py +++ b/tests/basics/int_big_mod.py @@ -8,3 +8,10 @@ for i in range(11): y = delta * (j)# - 5) # TODO reinstate negative number test when % is working with sign correctly if y != 0: print(x % y) + +# these check an edge case on 64-bit machines where two mpz limbs +# are used and the most significant one has the MSB set +x = 0x8000000000000000 +print((x + 1) % x) +x = 0x86c60128feff5330 +print((x + 1) % x)