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)