0a59938574
For certain operands to mpn_div, the existing code path for `DIG_SIZE == MPZ_DBL_DIG_SIZE / 2` had a bug in it where borrow could still overflow in the `(x >= *n || *n - x <= borrow)` branch, ie `borrow + x - (mpz_dbl_dig_t)*n` overflows the borrow variable. In such cases the subsequent right-shift of borrow would not bring in the overflow bit, leading to an error in the result. An example division that had overflow when MPZ_DIG_SIZE = 16 is `(2 ** 48 - 1) ** 2 // (2 ** 48 - 1)`. This is fixed in this commit by simplifying the code and handling the low digits of borrow first, and then the upper bits (to shift down) separately. There is no longer a distinction between `DIG_SIZE < MPZ_DBL_DIG_SIZE / 2` and `DIG_SIZE == MPZ_DBL_DIG_SIZE / 2`. This commit also simplifies the second part of the calculation so that borrow does not need to be negated (instead the code just works knowing that borrow is negative and using + instead of - in calculations involving borrow). Fixes #6777. Signed-off-by: Damien George <damien@micropython.org>
15 lines
556 B
Python
15 lines
556 B
Python
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)
|
|
|
|
# these check edge cases where borrow overflows
|
|
print((2 ** 48 - 1) ** 2 // (2 ** 48 - 1))
|
|
print((2 ** 256 - 2 ** 32) ** 2 // (2 ** 256 - 2 ** 32))
|