From 909982e82aa73fe5a75d5ab75fbaf84539a0c5e3 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Sun, 8 Jan 2023 11:34:20 +0300 Subject: gh-91851: Micro optimizations for arithmetic between Fractions (#25518) Adapted from https://github.com/python/cpython/pull/24779/commits/046c84e8f9 This makes arithmetic between Fractions with small components just as fast as before python/cpython#24779, at some expense of mixed arithmetic (e.g. Fraction + int). --- Lib/fractions.py | 22 ++++++++++++---------- .../2022-04-23-08-12-14.gh-issue-91851.Jd47V6.rst | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2022-04-23-08-12-14.gh-issue-91851.Jd47V6.rst diff --git a/Lib/fractions.py b/Lib/fractions.py index 9397411..bdba6c3 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -395,8 +395,10 @@ class Fraction(numbers.Rational): """ def forward(a, b): - if isinstance(b, (int, Fraction)): + if isinstance(b, Fraction): return monomorphic_operator(a, b) + elif isinstance(b, int): + return monomorphic_operator(a, Fraction(b)) elif isinstance(b, float): return fallback_operator(float(a), b) elif isinstance(b, complex): @@ -409,7 +411,7 @@ class Fraction(numbers.Rational): def reverse(b, a): if isinstance(a, numbers.Rational): # Includes ints. - return monomorphic_operator(a, b) + return monomorphic_operator(Fraction(a), b) elif isinstance(a, numbers.Real): return fallback_operator(float(a), float(b)) elif isinstance(a, numbers.Complex): @@ -491,8 +493,8 @@ class Fraction(numbers.Rational): def _add(a, b): """a + b""" - na, da = a.numerator, a.denominator - nb, db = b.numerator, b.denominator + na, da = a._numerator, a._denominator + nb, db = b._numerator, b._denominator g = math.gcd(da, db) if g == 1: return Fraction(na * db + da * nb, da * db, _normalize=False) @@ -507,8 +509,8 @@ class Fraction(numbers.Rational): def _sub(a, b): """a - b""" - na, da = a.numerator, a.denominator - nb, db = b.numerator, b.denominator + na, da = a._numerator, a._denominator + nb, db = b._numerator, b._denominator g = math.gcd(da, db) if g == 1: return Fraction(na * db - da * nb, da * db, _normalize=False) @@ -523,8 +525,8 @@ class Fraction(numbers.Rational): def _mul(a, b): """a * b""" - na, da = a.numerator, a.denominator - nb, db = b.numerator, b.denominator + na, da = a._numerator, a._denominator + nb, db = b._numerator, b._denominator g1 = math.gcd(na, db) if g1 > 1: na //= g1 @@ -540,8 +542,8 @@ class Fraction(numbers.Rational): def _div(a, b): """a / b""" # Same as _mul(), with inversed b. - na, da = a.numerator, a.denominator - nb, db = b.numerator, b.denominator + na, da = a._numerator, a._denominator + nb, db = b._numerator, b._denominator g1 = math.gcd(na, nb) if g1 > 1: na //= g1 diff --git a/Misc/NEWS.d/next/Library/2022-04-23-08-12-14.gh-issue-91851.Jd47V6.rst b/Misc/NEWS.d/next/Library/2022-04-23-08-12-14.gh-issue-91851.Jd47V6.rst new file mode 100644 index 0000000..a918bff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-04-23-08-12-14.gh-issue-91851.Jd47V6.rst @@ -0,0 +1 @@ +Optimize the :class:`~fractions.Fraction` arithmetics for small components. -- cgit v0.12