fractions.py revision dc2964b0d849389bffde95b8f76fd112049e114f
1d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin# Originally contributed by Sjoerd Mullender. 2d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin# Significantly modified by Jeffrey Yasskin <jyasskin at gmail.com>. 3d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin"""Rational, infinite-precision, real numbers.""" 5d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 6d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinfrom __future__ import division 7d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinimport math 8d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinimport numbers 9d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinimport operator 1045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskinimport re 11d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 12d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin__all__ = ["Rational"] 13d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 14d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey YasskinRationalAbc = numbers.Rational 15d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 16d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 173e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskindef gcd(a, b): 183e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin """Calculate the Greatest Common Divisor of a and b. 19d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 20d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Unless b==0, the result will have the same sign as b (so that when 21d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b is divided by it, the result comes out positive). 22d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 23d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin while b: 24d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a, b = b, a%b 25d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a 26d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 27d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 2845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin_RATIONAL_FORMAT = re.compile( 293e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin r'^\s*(?P<sign>[-+]?)(?P<num>\d+)' 303e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin r'(?:/(?P<denom>\d+)|\.(?P<decimal>\d+))?\s*$') 3145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 3245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 33d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskinclass Rational(RationalAbc): 34d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """This class implements rational numbers. 35d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 36d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Rational(8, 6) will produce a rational number equivalent to 37d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4/3. Both arguments must be Integral. The numerator defaults to 0 38d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin and the denominator defaults to 1 so that Rational(3) == 3 and 39d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Rational() == 0. 40d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin Rationals can also be constructed from strings of the form 423e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin '[-+]?[0-9]+((/|.)[0-9]+)?', optionally surrounded by spaces. 4345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 44d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 45d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 46dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin __slots__ = ('_numerator', '_denominator') 47d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # We're immutable, so use __new__ not __init__ 4945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin def __new__(cls, numerator=0, denominator=1): 5045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """Constructs a Rational. 5145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 5263c77b61751c2d15754b6381d085eb5ca2e26501Raymond Hettinger Takes a string like '3/2' or '1.5', another Rational, or a 533e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator/denominator pair. 5445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 5545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """ 5645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin self = super(Rational, cls).__new__(cls) 5745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 5845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if denominator == 1: 5945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if isinstance(numerator, basestring): 6045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # Handle construction from strings. 6145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin input = numerator 6245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin m = _RATIONAL_FORMAT.match(input) 6345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if m is None: 6445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin raise ValueError('Invalid literal for Rational: ' + input) 653e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator = m.group('num') 663e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin decimal = m.group('decimal') 673e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin if decimal: 683e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin # The literal is a decimal number. 693e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator = int(numerator + decimal) 703e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin denominator = 10**len(decimal) 713e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin else: 723e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin # The literal is an integer or fraction. 733e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin numerator = int(numerator) 743e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin # Default denominator to 1. 753e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin denominator = int(m.group('denom') or 1) 763e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin 7745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if m.group('sign') == '-': 7845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin numerator = -numerator 7945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 8045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin elif (not isinstance(numerator, numbers.Integral) and 8145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin isinstance(numerator, RationalAbc)): 8245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # Handle copies from other rationals. 8345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin other_rational = numerator 8445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin numerator = other_rational.numerator 8545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin denominator = other_rational.denominator 86d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 87d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if (not isinstance(numerator, numbers.Integral) or 88d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin not isinstance(denominator, numbers.Integral)): 89d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin raise TypeError("Rational(%(numerator)s, %(denominator)s):" 90d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin " Both arguments must be integral." % locals()) 91d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 92d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if denominator == 0: 93d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin raise ZeroDivisionError('Rational(%s, 0)' % numerator) 94d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 953e1a3736169fbd7e1a2234899faa64e5de75bc3eJeffrey Yasskin g = gcd(numerator, denominator) 96dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin self._numerator = int(numerator // g) 97dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin self._denominator = int(denominator // g) 9845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return self 99d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 100d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin @classmethod 101d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def from_float(cls, f): 10245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """Converts a finite float to a rational number, exactly. 10345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 10445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin Beware that Rational.from_float(0.3) != Rational(3, 10). 10545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 10645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """ 107d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if not isinstance(f, float): 108d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin raise TypeError("%s.from_float() only takes floats, not %r (%s)" % 109d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin (cls.__name__, f, type(f).__name__)) 110d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if math.isnan(f) or math.isinf(f): 111d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin raise TypeError("Cannot convert %r to %s." % (f, cls.__name__)) 1123ea7b41b5805c60a05e697211d0bfc14a62a19fbJeffrey Yasskin return cls(*f.as_integer_ratio()) 113d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 11445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin @classmethod 11545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin def from_decimal(cls, dec): 11645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin """Converts a finite Decimal instance to a rational number, exactly.""" 11745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin from decimal import Decimal 11845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if not isinstance(dec, Decimal): 11945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin raise TypeError( 12045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin "%s.from_decimal() only takes Decimals, not %r (%s)" % 12145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin (cls.__name__, dec, type(dec).__name__)) 12245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if not dec.is_finite(): 12345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin # Catches infinities and nans. 12445169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin raise TypeError("Cannot convert %s to %s." % (dec, cls.__name__)) 12545169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin sign, digits, exp = dec.as_tuple() 12645169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin digits = int(''.join(map(str, digits))) 12745169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if sign: 12845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin digits = -digits 12945169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin if exp >= 0: 13045169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return cls(digits * 10 ** exp) 13145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin else: 13245169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return cls(digits, 10 ** -exp) 13345169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin 134cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger @classmethod 135cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger def from_continued_fraction(cls, seq): 136cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 'Build a Rational from a continued fraction expessed as a sequence' 137cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n, d = 1, 0 138cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger for e in reversed(seq): 139cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n, d = d, n 140cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n += e * d 141f336c8b7e91f389c8af4255f589849b16ee3dcb5Raymond Hettinger return cls(n, d) if seq else cls(0) 142cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 143cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger def as_continued_fraction(self): 144cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 'Return continued fraction expressed as a list' 145cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n = self.numerator 146cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger d = self.denominator 147cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger cf = [] 148cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger while d: 149cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger e = int(n // d) 150cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger cf.append(e) 151cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n -= e * d 152cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger n, d = d, n 153cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger return cf 154cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 1559c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger def approximate(self, max_denominator): 1569c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger 'Best rational approximation with a denominator <= max_denominator' 157cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger # XXX First cut at algorithm 158cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger # Still needs rounding rules as specified at 159cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger # http://en.wikipedia.org/wiki/Continued_fraction 1609c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger if self.denominator <= max_denominator: 1619c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger return self 1629c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger cf = self.as_continued_fraction() 163eb461904eb277c5a92a7d2672f941cb095cf1a93Raymond Hettinger result = Rational(0) 164cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger for i in range(1, len(cf)): 1659c6d81f5dd083ad536106bf723f705d70ddbe258Raymond Hettinger new = self.from_continued_fraction(cf[:i]) 166cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger if new.denominator > max_denominator: 167cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger break 168cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger result = new 169cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger return result 170cf10926088c1e8a4f2d3097e095fa0fd7d5d681aRaymond Hettinger 171dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin @property 172dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin def numerator(a): 173dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin return a._numerator 174dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin 175dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin @property 176dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin def denominator(a): 177dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin return a._denominator 178dc2964b0d849389bffde95b8f76fd112049e114fJeffrey Yasskin 179d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __repr__(self): 180d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """repr(self)""" 18145169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return ('Rational(%r,%r)' % (self.numerator, self.denominator)) 182d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 183d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __str__(self): 184d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """str(self)""" 185d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if self.denominator == 1: 186d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return str(self.numerator) 187d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 18845169fbc800d573ddd01d3f440f264caaa93c622Jeffrey Yasskin return '%s/%s' % (self.numerator, self.denominator) 189d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 190d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _operator_fallbacks(monomorphic_operator, fallback_operator): 191d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """Generates forward and reverse operators given a purely-rational 192d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin operator and a function from the operator module. 193d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 194d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Use this like: 195d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __op__, __rop__ = _operator_fallbacks(just_rational_op, operator.op) 196d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 197b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin In general, we want to implement the arithmetic operations so 198b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin that mixed-mode operations either call an implementation whose 199b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin author knew about the types of both arguments, or convert both 200b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin to the nearest built in type and do the operation there. In 201b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Rational, that means that we define __add__ and __radd__ as: 202b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 203b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin def __add__(self, other): 2042df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # Both types have numerators/denominator attributes, 2052df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # so do the operation directly 206b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin if isinstance(other, (int, long, Rational)): 207b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return Rational(self.numerator * other.denominator + 208b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin other.numerator * self.denominator, 209b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin self.denominator * other.denominator) 2102df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # float and complex don't have those operations, but we 2112df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # know about those types, so special case them. 212b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, float): 213b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return float(self) + other 214b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, complex): 215b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return complex(self) + other 2162df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger # Let the other type take over. 2172df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger return NotImplemented 218b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 219b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin def __radd__(self, other): 220b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin # radd handles more types than add because there's 221b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin # nothing left to fall back to. 222b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin if isinstance(other, RationalAbc): 223b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return Rational(self.numerator * other.denominator + 224b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin other.numerator * self.denominator, 225b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin self.denominator * other.denominator) 226b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, Real): 227b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return float(other) + float(self) 228b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin elif isinstance(other, Complex): 229b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin return complex(other) + complex(self) 2302df20a3e0816537db68618cef0603e89773beac4Raymond Hettinger return NotImplemented 231b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 232b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 233b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin There are 5 different cases for a mixed-type addition on 234b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Rational. I'll refer to all of the above code that doesn't 235b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin refer to Rational, float, or complex as "boilerplate". 'r' 236b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin will be an instance of Rational, which is a subtype of 237b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin RationalAbc (r : Rational <: RationalAbc), and b : B <: 238b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Complex. The first three involve 'r + b': 239b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 240b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 1. If B <: Rational, int, float, or complex, we handle 241b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin that specially, and all is well. 242b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 2. If Rational falls back to the boilerplate code, and it 243b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin were to return a value from __add__, we'd miss the 244b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin possibility that B defines a more intelligent __radd__, 245b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin so the boilerplate should return NotImplemented from 246b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin __add__. In particular, we don't handle RationalAbc 247b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin here, even though we could get an exact answer, in case 248b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin the other type wants to do something special. 249b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 3. If B <: Rational, Python tries B.__radd__ before 250b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Rational.__add__. This is ok, because it was 251b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin implemented with knowledge of Rational, so it can 252b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin handle those instances before delegating to Real or 253b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin Complex. 254b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 255b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin The next two situations describe 'b + r'. We assume that b 256b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin didn't know about Rational in its implementation, and that it 257b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin uses similar boilerplate code: 258b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 259b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 4. If B <: RationalAbc, then __radd_ converts both to the 260b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin builtin rational type (hey look, that's us) and 261b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin proceeds. 262b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 5. Otherwise, __radd__ tries to find the nearest common 263b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin base ABC, and fall back to its builtin type. Since this 264b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin class doesn't subclass a concrete type, there's no 265b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin implementation to fall back to, so we need to try as 266b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin hard as possible to return an actual value, or the user 267b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin will get a TypeError. 268b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin 269d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 270d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def forward(a, b): 271b23dea6adb7eaf3f415e05b129afa01fa1c4dd5cJeffrey Yasskin if isinstance(b, (int, long, Rational)): 272d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return monomorphic_operator(a, b) 273d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(b, float): 274d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(float(a), b) 275d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(b, complex): 276d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(complex(a), b) 277d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 278d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return NotImplemented 279d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin forward.__name__ = '__' + fallback_operator.__name__ + '__' 280d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin forward.__doc__ = monomorphic_operator.__doc__ 281d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 282d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def reverse(b, a): 283d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(a, RationalAbc): 284d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Includes ints. 285d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return monomorphic_operator(a, b) 286d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(a, numbers.Real): 287d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(float(a), float(b)) 288d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin elif isinstance(a, numbers.Complex): 289d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return fallback_operator(complex(a), complex(b)) 290d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 291d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return NotImplemented 292d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin reverse.__name__ = '__r' + fallback_operator.__name__ + '__' 293d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin reverse.__doc__ = monomorphic_operator.__doc__ 294d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 295d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return forward, reverse 296d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 297d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _add(a, b): 298d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a + b""" 299d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator * b.denominator + 300d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b.numerator * a.denominator, 301d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator * b.denominator) 302d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 303d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __add__, __radd__ = _operator_fallbacks(_add, operator.add) 304d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 305d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _sub(a, b): 306d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a - b""" 307d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator * b.denominator - 308d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b.numerator * a.denominator, 309d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator * b.denominator) 310d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 311d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub) 312d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 313d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _mul(a, b): 314d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a * b""" 315d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator * b.numerator, a.denominator * b.denominator) 316d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 317d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul) 318d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 319d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _div(a, b): 320d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a / b""" 321d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator * b.denominator, 322d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator * b.numerator) 323d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 324d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv) 325d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin __div__, __rdiv__ = _operator_fallbacks(_div, operator.div) 326d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 327909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger def __floordiv__(a, b): 328909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger """a // b""" 329909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # Will be math.floor(a / b) in 3.0. 330d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin div = a / b 331d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(div, RationalAbc): 332d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # trunc(math.floor(div)) doesn't work if the rational is 333d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # more precise than a float because the intermediate 334d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # rounding may cross an integer boundary. 335d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return div.numerator // div.denominator 336d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 337d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return math.floor(div) 338d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 339d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __rfloordiv__(b, a): 340d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a // b""" 341d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Will be math.floor(a / b) in 3.0. 342909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger div = a / b 343909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger if isinstance(div, RationalAbc): 344909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # trunc(math.floor(div)) doesn't work if the rational is 345909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # more precise than a float because the intermediate 346909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger # rounding may cross an integer boundary. 347909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return div.numerator // div.denominator 348909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger else: 349909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return math.floor(div) 350d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 351d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __mod__(a, b): 352d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a % b""" 353909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger div = a // b 354909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return a - b * div 355d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 356d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __rmod__(b, a): 357d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a % b""" 358909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger div = a // b 359909e334e8a525e8430f1532c0ecf133f19d3d185Raymond Hettinger return a - b * div 360d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 361d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __pow__(a, b): 362d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a ** b 363d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 364d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin If b is not an integer, the result will be a float or complex 365d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin since roots are generally irrational. If b is an integer, the 366d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin result will be rational. 367d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 368d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 369d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, RationalAbc): 370d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if b.denominator == 1: 371d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin power = b.numerator 372d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if power >= 0: 373d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator ** power, 374d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator ** power) 375d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 376d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.denominator ** -power, 377d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.numerator ** -power) 378d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 379d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # A fractional power will generally produce an 380d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # irrational number. 381d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return float(a) ** float(b) 382d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 383d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return float(a) ** b 384d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 385d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __rpow__(b, a): 386d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a ** b""" 387d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if b.denominator == 1 and b.numerator >= 0: 388d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # If a is an int, keep it that way if possible. 389d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a ** b.numerator 390d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 391d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(a, RationalAbc): 392d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator, a.denominator) ** b 393d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 394d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if b.denominator == 1: 395d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a ** b.numerator 396d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 397d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a ** float(b) 398d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 399d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __pos__(a): 400d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """+a: Coerces a subclass instance to Rational""" 401d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(a.numerator, a.denominator) 402d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 403d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __neg__(a): 404d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """-a""" 405d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(-a.numerator, a.denominator) 406d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 407d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __abs__(a): 408d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """abs(a)""" 409d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return Rational(abs(a.numerator), a.denominator) 410d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 411d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __trunc__(a): 412d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """trunc(a)""" 413d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if a.numerator < 0: 414d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return -(-a.numerator // a.denominator) 415d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 416d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a.numerator // a.denominator 417d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 4185b0e27e50d33f33515f31ff6fec123f5e2be9d73Raymond Hettinger __int__ = __trunc__ 4195b0e27e50d33f33515f31ff6fec123f5e2be9d73Raymond Hettinger 420d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __hash__(self): 421d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """hash(self) 422d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 423d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Tricky because values that are exactly representable as a 424d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin float must have the same hash as that float. 425d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 426d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 427921cb5d3a3e823c6c225681d8e99f7baa8920f3eRaymond Hettinger # XXX since this method is expensive, consider caching the result 428d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if self.denominator == 1: 429d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Get integers right. 430d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return hash(self.numerator) 431d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Expensive check, but definitely correct. 432d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if self == float(self): 433d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return hash(float(self)) 434d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 435d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # Use tuple's hash to avoid a high collision rate on 436d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # simple fractions. 437d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return hash((self.numerator, self.denominator)) 438d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 439d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __eq__(a, b): 440d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a == b""" 441d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, RationalAbc): 442d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return (a.numerator == b.numerator and 443d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin a.denominator == b.denominator) 444d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, numbers.Complex) and b.imag == 0: 445d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b = b.real 446d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, float): 447d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a == a.from_float(b) 448d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin else: 449d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # XXX: If b.__eq__ is implemented like this method, it may 450d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # give the wrong answer after float(a) changes a's 451d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # value. Better ways of doing this are welcome. 452d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return float(a) == b 453d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 454d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def _subtractAndCompareToZero(a, b, op): 455d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """Helper function for comparison operators. 456d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 457d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin Subtracts b from a, exactly if possible, and compares the 458d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin result with 0 using op, in such a way that the comparison 459d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin won't recurse. If the difference raises a TypeError, returns 460d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin NotImplemented instead. 461d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 462d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """ 463d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, numbers.Complex) and b.imag == 0: 464d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b = b.real 465d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(b, float): 466d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin b = a.from_float(b) 467d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin try: 468d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # XXX: If b <: Real but not <: RationalAbc, this is likely 469d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # to fall back to a float. If the actual values differ by 470d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # less than MIN_FLOAT, this could falsely call them equal, 471d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # which would make <= inconsistent with ==. Better ways of 472d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin # doing this are welcome. 473d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin diff = a - b 474d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin except TypeError: 475d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return NotImplemented 476d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin if isinstance(diff, RationalAbc): 477d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return op(diff.numerator, 0) 478d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return op(diff, 0) 479d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 480d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __lt__(a, b): 481d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a < b""" 482d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.lt) 483d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 484d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __gt__(a, b): 485d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a > b""" 486d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.gt) 487d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 488d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __le__(a, b): 489d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a <= b""" 490d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.le) 491d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 492d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __ge__(a, b): 493d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a >= b""" 494d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a._subtractAndCompareToZero(b, operator.ge) 495d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin 496d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin def __nonzero__(a): 497d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin """a != 0""" 498d7b00334f3cbf7a802e875238b9f2bd95e190436Jeffrey Yasskin return a.numerator != 0 499a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 500a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger # support for pickling, copy, and deepcopy 501a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 502a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger def __reduce__(self): 503a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return (self.__class__, (str(self),)) 504a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 505a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger def __copy__(self): 506a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger if type(self) == Rational: 507a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self # I'm immutable; therefore I am my own clone 508a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self.__class__(self.numerator, self.denominator) 509a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger 510a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger def __deepcopy__(self, memo): 511a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger if type(self) == Rational: 512a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self # My components are also immutable 513a6216749fb88fb508cd469839d77d4264a881bd4Raymond Hettinger return self.__class__(self.numerator, self.denominator) 514