commit d7ec2c509b Author: Sergey B Kirpichev Date: Mon Mar 1 11:29:16 2021 +0300 bpo-43420 Simple optimizations for Fraction._add/sub() diff --git a/Lib/fractions.py b/Lib/fractions.py index de3e23b759..12150f91e8 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -382,30 +382,53 @@ def reverse(b, a): def _add(a, b): """a + b""" + na, nb = a.numerator, b.numerator da, db = a.denominator, b.denominator - return Fraction(a.numerator * db + b.numerator * da, - da * db) + g = math.gcd(da, db) + if g == 1: + # This is the case with probability 6/pi**2 ~ 60.8%. + return Fraction(na * db + da * nb, da * db, _normalize=False) + else: + q1, q2 = da // g, db // g + n, d = na * q2 + nb * q1, q1 * q2 + g2 = math.gcd(n, g) + return Fraction(n // g2, d * (g // g2), _normalize=False) __add__, __radd__ = _operator_fallbacks(_add, operator.add) def _sub(a, b): """a - b""" + na, nb = a.numerator, b.numerator da, db = a.denominator, b.denominator - return Fraction(a.numerator * db - b.numerator * da, - da * db) + g = math.gcd(da, db) + if g == 1: + # This is the case with probability 6/pi**2 ~ 60.8%. + return Fraction(na * db - da * nb, da * db, _normalize=False) + else: + q1, q2 = da // g, db // g + n, d = na * q2 - nb * q1, q1 * q2 + g2 = math.gcd(n, g) + return Fraction(n // g2, d * (g // g2), _normalize=False) __sub__, __rsub__ = _operator_fallbacks(_sub, operator.sub) def _mul(a, b): """a * b""" - return Fraction(a.numerator * b.numerator, a.denominator * b.denominator) + na, da = a.numerator, a.denominator + nb, db = b.numerator, b.denominator + x1 = math.gcd(na, db) + x2 = math.gcd(nb, da) + return Fraction((na//x1)*(nb//x2), (da//x2)*(db//x1), _normalize=False) __mul__, __rmul__ = _operator_fallbacks(_mul, operator.mul) def _div(a, b): """a / b""" - return Fraction(a.numerator * b.denominator, - a.denominator * b.numerator) + na, da = a.numerator, a.denominator + nb, db = b.numerator, b.denominator + x1 = math.gcd(na, nb) + x2 = math.gcd(db, da) + return Fraction((na//x1)*(db//x2), (da//x2)*(nb//x1), _normalize=False) __truediv__, __rtruediv__ = _operator_fallbacks(_div, operator.truediv)