Traktor/myenv/Lib/site-packages/sympy/external/tests/test_pythonmpq.py
2024-05-26 05:12:46 +02:00

177 lines
5.7 KiB
Python

"""
test_pythonmpq.py
Test the PythonMPQ class for consistency with gmpy2's mpq type. If gmpy2 is
installed run the same tests for both.
"""
from fractions import Fraction
from decimal import Decimal
import pickle
from typing import Callable, List, Tuple, Type
from sympy.testing.pytest import raises
from sympy.external.pythonmpq import PythonMPQ
#
# If gmpy2 is installed then run the tests for both mpq and PythonMPQ.
# That should ensure consistency between the implementation here and mpq.
#
rational_types: List[Tuple[Callable, Type, Callable, Type]]
rational_types = [(PythonMPQ, PythonMPQ, int, int)]
try:
from gmpy2 import mpq, mpz
rational_types.append((mpq, type(mpq(1)), mpz, type(mpz(1))))
except ImportError:
pass
def test_PythonMPQ():
#
# Test PythonMPQ and also mpq if gmpy/gmpy2 is installed.
#
for Q, TQ, Z, TZ in rational_types:
def check_Q(q):
assert isinstance(q, TQ)
assert isinstance(q.numerator, TZ)
assert isinstance(q.denominator, TZ)
return q.numerator, q.denominator
# Check construction from different types
assert check_Q(Q(3)) == (3, 1)
assert check_Q(Q(3, 5)) == (3, 5)
assert check_Q(Q(Q(3, 5))) == (3, 5)
assert check_Q(Q(0.5)) == (1, 2)
assert check_Q(Q('0.5')) == (1, 2)
assert check_Q(Q(Fraction(3, 5))) == (3, 5)
# https://github.com/aleaxit/gmpy/issues/327
if Q is PythonMPQ:
assert check_Q(Q(Decimal('0.6'))) == (3, 5)
# Invalid types
raises(TypeError, lambda: Q([]))
raises(TypeError, lambda: Q([], []))
# Check normalisation of signs
assert check_Q(Q(2, 3)) == (2, 3)
assert check_Q(Q(-2, 3)) == (-2, 3)
assert check_Q(Q(2, -3)) == (-2, 3)
assert check_Q(Q(-2, -3)) == (2, 3)
# Check gcd calculation
assert check_Q(Q(12, 8)) == (3, 2)
# __int__/__float__
assert int(Q(5, 3)) == 1
assert int(Q(-5, 3)) == -1
assert float(Q(5, 2)) == 2.5
assert float(Q(-5, 2)) == -2.5
# __str__/__repr__
assert str(Q(2, 1)) == "2"
assert str(Q(1, 2)) == "1/2"
if Q is PythonMPQ:
assert repr(Q(2, 1)) == "MPQ(2,1)"
assert repr(Q(1, 2)) == "MPQ(1,2)"
else:
assert repr(Q(2, 1)) == "mpq(2,1)"
assert repr(Q(1, 2)) == "mpq(1,2)"
# __bool__
assert bool(Q(1, 2)) is True
assert bool(Q(0)) is False
# __eq__/__ne__
assert (Q(2, 3) == Q(2, 3)) is True
assert (Q(2, 3) == Q(2, 5)) is False
assert (Q(2, 3) != Q(2, 3)) is False
assert (Q(2, 3) != Q(2, 5)) is True
# __hash__
assert hash(Q(3, 5)) == hash(Fraction(3, 5))
# __reduce__
q = Q(2, 3)
assert pickle.loads(pickle.dumps(q)) == q
# __ge__/__gt__/__le__/__lt__
assert (Q(1, 3) < Q(2, 3)) is True
assert (Q(2, 3) < Q(2, 3)) is False
assert (Q(2, 3) < Q(1, 3)) is False
assert (Q(-2, 3) < Q(1, 3)) is True
assert (Q(1, 3) < Q(-2, 3)) is False
assert (Q(1, 3) <= Q(2, 3)) is True
assert (Q(2, 3) <= Q(2, 3)) is True
assert (Q(2, 3) <= Q(1, 3)) is False
assert (Q(-2, 3) <= Q(1, 3)) is True
assert (Q(1, 3) <= Q(-2, 3)) is False
assert (Q(1, 3) > Q(2, 3)) is False
assert (Q(2, 3) > Q(2, 3)) is False
assert (Q(2, 3) > Q(1, 3)) is True
assert (Q(-2, 3) > Q(1, 3)) is False
assert (Q(1, 3) > Q(-2, 3)) is True
assert (Q(1, 3) >= Q(2, 3)) is False
assert (Q(2, 3) >= Q(2, 3)) is True
assert (Q(2, 3) >= Q(1, 3)) is True
assert (Q(-2, 3) >= Q(1, 3)) is False
assert (Q(1, 3) >= Q(-2, 3)) is True
# __abs__/__pos__/__neg__
assert abs(Q(2, 3)) == abs(Q(-2, 3)) == Q(2, 3)
assert +Q(2, 3) == Q(2, 3)
assert -Q(2, 3) == Q(-2, 3)
# __add__/__radd__
assert Q(2, 3) + Q(5, 7) == Q(29, 21)
assert Q(2, 3) + 1 == Q(5, 3)
assert 1 + Q(2, 3) == Q(5, 3)
raises(TypeError, lambda: [] + Q(1))
raises(TypeError, lambda: Q(1) + [])
# __sub__/__rsub__
assert Q(2, 3) - Q(5, 7) == Q(-1, 21)
assert Q(2, 3) - 1 == Q(-1, 3)
assert 1 - Q(2, 3) == Q(1, 3)
raises(TypeError, lambda: [] - Q(1))
raises(TypeError, lambda: Q(1) - [])
# __mul__/__rmul__
assert Q(2, 3) * Q(5, 7) == Q(10, 21)
assert Q(2, 3) * 1 == Q(2, 3)
assert 1 * Q(2, 3) == Q(2, 3)
raises(TypeError, lambda: [] * Q(1))
raises(TypeError, lambda: Q(1) * [])
# __pow__/__rpow__
assert Q(2, 3) ** 2 == Q(4, 9)
assert Q(2, 3) ** 1 == Q(2, 3)
assert Q(-2, 3) ** 2 == Q(4, 9)
assert Q(-2, 3) ** -1 == Q(-3, 2)
if Q is PythonMPQ:
raises(TypeError, lambda: 1 ** Q(2, 3))
raises(TypeError, lambda: Q(1, 4) ** Q(1, 2))
raises(TypeError, lambda: [] ** Q(1))
raises(TypeError, lambda: Q(1) ** [])
# __div__/__rdiv__
assert Q(2, 3) / Q(5, 7) == Q(14, 15)
assert Q(2, 3) / 1 == Q(2, 3)
assert 1 / Q(2, 3) == Q(3, 2)
raises(TypeError, lambda: [] / Q(1))
raises(TypeError, lambda: Q(1) / [])
raises(ZeroDivisionError, lambda: Q(1, 2) / Q(0))
# __divmod__
if Q is PythonMPQ:
raises(TypeError, lambda: Q(2, 3) // Q(1, 3))
raises(TypeError, lambda: Q(2, 3) % Q(1, 3))
raises(TypeError, lambda: 1 // Q(1, 3))
raises(TypeError, lambda: 1 % Q(1, 3))
raises(TypeError, lambda: Q(2, 3) // 1)
raises(TypeError, lambda: Q(2, 3) % 1)