circuitpython/tests/basics/int_big_zeroone.py
Damien George 2c139bbf4e py/mpz: Fix bugs with bitwise of -0 by ensuring all 0's are positive.
This commit makes sure that the value zero is always encoded in an mpz_t as
neg=0 and len=0 (previously it was just len=0).

This invariant is needed for some of the bitwise operations that operate on
negative numbers, because they cannot handle -0.  For example
(-((1<<100)-(1<<100)))|1 was being computed as -65535, instead of 1.

Fixes issue #8042.

Signed-off-by: Damien George <damien@micropython.org>
2021-12-21 18:00:05 +11:00

66 lines
1.8 KiB
Python

# test [0,1,-1] edge cases of bignum
long_zero = (2**64) >> 65
long_neg_zero = -long_zero
long_one = long_zero + 1
long_neg_one = -long_one
cases = [long_zero, long_neg_zero, long_one, long_neg_one]
print(cases)
print([-c for c in cases])
print([~c for c in cases])
print([c >> 1 for c in cases])
print([c << 1 for c in cases])
# comparison of 0
print(long_zero == 0)
print(long_neg_zero == 0)
print(long_one - 1 == 0)
print(long_neg_one + 1 == 0)
print(long_zero < 1)
print(long_zero < -1)
print(long_zero > 1)
print(long_zero > -1)
print(long_neg_zero < 1)
print(long_neg_zero < -1)
print(long_neg_zero > 1)
print(long_neg_zero > -1)
# generate zeros that involve negative numbers
large = 1 << 70
large_plus_one = large + 1
zeros = (
large - large,
-large + large,
large + -large,
-(large - large),
large - large_plus_one + 1,
-large & (large - large),
-large ^ -large,
-large * (large - large),
(large - large) // -large,
-large // -large_plus_one,
-(large + large) % large,
(large + large) % -large,
-(large + large) % -large,
)
print(zeros)
# compute arithmetic operations that may have problems with -0
# (this checks that -0 is never generated in the zeros tuple)
cases = (0, 1, -1) + zeros
for lhs in cases:
print("-{} = {}".format(lhs, -lhs))
print("~{} = {}".format(lhs, ~lhs))
print("{} >> 1 = {}".format(lhs, lhs >> 1))
print("{} << 1 = {}".format(lhs, lhs << 1))
for rhs in cases:
print("{} == {} = {}".format(lhs, rhs, lhs == rhs))
print("{} + {} = {}".format(lhs, rhs, lhs + rhs))
print("{} - {} = {}".format(lhs, rhs, lhs - rhs))
print("{} * {} = {}".format(lhs, rhs, lhs * rhs))
print("{} | {} = {}".format(lhs, rhs, lhs | rhs))
print("{} & {} = {}".format(lhs, rhs, lhs & rhs))
print("{} ^ {} = {}".format(lhs, rhs, lhs ^ rhs))