14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""Tests for binary operators on subtypes of built-in types."""
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport unittest
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom test import test_support
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef gcd(a, b):
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Greatest common divisor using Euclid's algorithm."""
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    while a:
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a, b = b%a, a
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return b
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isint(x):
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether an object is an instance of int or long."""
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return isinstance(x, int) or isinstance(x, long)
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isnum(x):
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test whether an object is an instance of a built-in numeric type."""
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    for T in int, long, float, complex:
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isinstance(x, T):
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return 1
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return 0
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef isRat(x):
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Test wheter an object is an instance of the Rat class."""
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    return isinstance(x, Rat)
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass Rat(object):
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Rational number implemented as a normalized pair of longs."""
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __slots__ = ['_Rat__num', '_Rat__den']
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __init__(self, num=0L, den=1L):
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Constructor: Rat([num[, den]]).
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        The arguments must be ints or longs, and default to (0, 1)."""
374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not isint(num):
384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise TypeError, "Rat numerator must be int or long (%r)" % num
394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if not isint(den):
404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise TypeError, "Rat denominator must be int or long (%r)" % den
414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        # But the zero is always on
424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if den == 0:
434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            raise ZeroDivisionError, "zero denominator"
444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        g = gcd(den, num)
454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__num = long(num//g)
464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.__den = long(den//g)
474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _get_num(self):
494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Accessor function for read-only 'num' attribute of Rat."""
504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__num
514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    num = property(_get_num, None)
524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def _get_den(self):
544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Accessor function for read-only 'den' attribute of Rat."""
554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__den
564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    den = property(_get_den, None)
574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __repr__(self):
594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Convert a Rat to an string resembling a Rat constructor call."""
604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return "Rat(%d, %d)" % (self.__num, self.__den)
614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __str__(self):
634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Convert a Rat to a string resembling a decimal numeric value."""
644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return str(float(self))
654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __float__(self):
674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Convert a Rat to a float."""
684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return self.__num*1.0/self.__den
694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __int__(self):
714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Convert a Rat to an int; self.den must be 1."""
724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.__den == 1:
734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                return int(self.__num)
754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except OverflowError:
764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                raise OverflowError, ("%s too large to convert to int" %
774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                                      repr(self))
784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise ValueError, "can't convert %s to int" % repr(self)
794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __long__(self):
814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Convert a Rat to an long; self.den must be 1."""
824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if self.__den == 1:
834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return long(self.__num)
844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        raise ValueError, "can't convert %s to long" % repr(self)
854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __add__(self, other):
874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Add two Rats, or a Rat and a number."""
884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            other = Rat(other)
904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(self.__num*other.__den + other.__num*self.__den,
924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       self.__den*other.__den)
934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return float(self) + other
954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __radd__ = __add__
984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __sub__(self, other):
1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Subtract two Rats, or a Rat and a number."""
1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            other = Rat(other)
1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(self.__num*other.__den - other.__num*self.__den,
1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       self.__den*other.__den)
1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return float(self) - other
1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rsub__(self, other):
1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Subtract two Rats, or a Rat and a number (reversed args)."""
1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            other = Rat(other)
1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(other.__num*self.__den - self.__num*other.__den,
1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                       self.__den*other.__den)
1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return other - float(self)
1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __mul__(self, other):
1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Multiply two Rats, or a Rat and a number."""
1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(self.__num*other.__num, self.__den*other.__den)
1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(self.__num*other, self.__den)
1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return float(self)*other
1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __rmul__ = __mul__
1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __truediv__(self, other):
1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Divide two Rats, or a Rat and a number."""
1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(self.__num*other.__den, self.__den*other.__num)
1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(self.__num, self.__den*other)
1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return float(self) / other
1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __div__ = __truediv__
1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rtruediv__(self, other):
1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Divide two Rats, or a Rat and a number (reversed args)."""
1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(other.__num*self.__den, other.__den*self.__num)
1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return Rat(other*self.__den, self.__num)
1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return other / float(self)
1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __rdiv__ = __rtruediv__
1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __floordiv__(self, other):
1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Divide two Rats, returning the floored result."""
1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            other = Rat(other)
1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        elif not isRat(other):
1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NotImplemented
1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        x = self/other
1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return x.__num // x.__den
1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rfloordiv__(self, other):
1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Divide two Rats, returning the floored result (reversed args)."""
1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        x = other/self
1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return x.__num // x.__den
1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __divmod__(self, other):
1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Divide two Rats, returning quotient and remainder."""
1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            other = Rat(other)
1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        elif not isRat(other):
1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NotImplemented
1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        x = self//other
1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return (x, self - other * x)
1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rdivmod__(self, other):
1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Divide two Rats, returning quotient and remainder (reversed args)."""
1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            other = Rat(other)
1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        elif not isRat(other):
1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return NotImplemented
1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return divmod(other, self)
1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __mod__(self, other):
1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Take one Rat modulo another."""
1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return divmod(self, other)[1]
1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __rmod__(self, other):
1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Take one Rat modulo another (reversed args)."""
1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return divmod(other, self)[1]
1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __eq__(self, other):
1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Compare two Rats for equality."""
1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isint(other):
1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.__den == 1 and self.__num == other
2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isRat(other):
2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return self.__num == other.__num and self.__den == other.__den
2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        if isnum(other):
2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            return float(self) == other
2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return NotImplemented
2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __ne__(self, other):
2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        """Compare two Rats for inequality."""
2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return not self == other
2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # Silence Py3k warning
2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    __hash__ = None
2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass RatTestCase(unittest.TestCase):
2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    """Unit tests for Rat class and its support utilities."""
2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_gcd(self):
2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(10, 12), 2)
2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(10, 15), 5)
2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(10, 11), 1)
2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(100, 15), 5)
2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(-10, 2), -2)
2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(10, -2), 2)
2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(gcd(-10, -2), -2)
2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for i in range(1, 20):
2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            for j in range(1, 20):
2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(gcd(i, j) > 0)
2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(gcd(-i, j) < 0)
2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(gcd(i, -j) > 0)
2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.assertTrue(gcd(-i, -j) < 0)
2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_constructor(self):
2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = Rat(10, 15)
2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.num, 2)
2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.den, 3)
2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = Rat(10L, 15L)
2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.num, 2)
2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.den, 3)
2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = Rat(10, -15)
2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.num, -2)
2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.den, 3)
2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = Rat(-10, 15)
2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.num, -2)
2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.den, 3)
2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = Rat(-10, -15)
2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.num, 2)
2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.den, 3)
2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        a = Rat(7)
2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.num, 7)
2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(a.den, 1)
2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        try:
2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            a = Rat(1, 0)
2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        except ZeroDivisionError:
2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            pass
2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        else:
2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            self.fail("Rat(1, 0) didn't raise ZeroDivisionError")
2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        for bad in "0", 0.0, 0j, (), [], {}, None, Rat, unittest:
2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                a = Rat(bad)
2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except TypeError:
2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("Rat(%r) didn't raise TypeError" % bad)
2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            try:
2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                a = Rat(1, bad)
2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            except TypeError:
2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                pass
2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm            else:
2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm                self.fail("Rat(1, %r) didn't raise TypeError" % bad)
2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_add(self):
2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(2, 3) + Rat(1, 3), 1)
2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(2, 3) + 1, Rat(5, 3))
2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(1 + Rat(2, 3), Rat(5, 3))
2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(1.0 + Rat(1, 2), 1.5)
2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(1, 2) + 1.0, 1.5)
2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_sub(self):
2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(7, 2) - Rat(7, 5), Rat(21, 10))
2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(7, 5) - 1, Rat(2, 5))
2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(1 - Rat(3, 5), Rat(2, 5))
2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(3, 2) - 1.0, 0.5)
2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(1.0 - Rat(1, 2), 0.5)
2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_mul(self):
2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(2, 3) * Rat(5, 7), Rat(10, 21))
2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10, 3) * 3, 10)
2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(3 * Rat(10, 3), 10)
2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10, 5) * 0.5, 1.0)
2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(0.5 * Rat(10, 5), 1.0)
2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_div(self):
2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10, 3) / Rat(5, 7), Rat(14, 3))
2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10, 3) / 3, Rat(10, 9))
2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(2 / Rat(5), Rat(2, 5))
2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(3.0 * Rat(1, 2), 1.5)
2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(1, 2) * 3.0, 1.5)
2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_floordiv(self):
2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10) // Rat(4), 2)
3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10, 3) // Rat(4, 3), 2)
3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10) // 4, 2)
3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(10 // Rat(4), 2)
3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_eq(self):
3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10), Rat(20, 2))
3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10), 10)
3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(10, Rat(10))
3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(Rat(10), 10.0)
3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        self.assertEqual(10.0, Rat(10))
3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def test_future_div(self):
3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        exec future_test
3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    # XXX Ran out of steam; TO DO: divmod, div, future division
3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfuture_test = """
3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmfrom __future__ import division
3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmself.assertEqual(Rat(10, 3) / Rat(5, 7), Rat(14, 3))
3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmself.assertEqual(Rat(10, 3) / 3, Rat(10, 9))
3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmself.assertEqual(2 / Rat(5), Rat(2, 5))
3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmself.assertEqual(3.0 * Rat(1, 2), 1.5)
3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmself.assertEqual(Rat(1, 2) * 3.0, 1.5)
3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmself.assertEqual(eval('1/2'), 0.5)
3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test_main():
3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_support.run_unittest(RatTestCase)
3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == "__main__":
3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    test_main()
332