10000 bpo-43420: Simple optimizations for Fraction's arithmetics by skirpichev · Pull Request #24779 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-43420: Simple optimizations for Fraction's arithmetics #24779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 22, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use Fraction's private attributes in arithmetic methods
That's slightly faster for small components.

Before:
$ ./python -m timeit -r11 -s 'from fractions import Fraction as F' \
-s 'a = F(10, 3)' -s 'b = F(6, 5)' 'a + b'
20000 loops, best of 11: 12.1 usec per loop
$ ./python -m timeit -r11 -s 'from fractions import Fraction as F' \
-s 'a = F(10, 3)' -s 'b = 7' 'a + b'
20000 loops, best of 11: 11.4 usec per loop

After:
$ ./python -m timeit -r11 -s 'from fractions import Fraction as F' \
-s 'a = F(10, 3)' -s 'b = F(6, 5)' 'a + b'
50000 loops, best of 11: 9.74 usec per loop
$ ./python -m timeit -r11 -s 'from fractions import Fraction as F' \
-s 'a = F(10, 3)' -s 'b = 7' 'a + b'
20000 loops, best of 11: 16.5 usec per loop

On the master:
$ ./python -m timeit -r11 -s 'from fractions import Fraction as F' \
-s 'a = F(10, 3)' -s 'b = F(6, 5)' 'a + b'
50000 loops, best of 11: 9.61 usec per loop
$ ./python -m timeit -r11 -s 'from fractions import Fraction as F' \
-s 'a = F(10, 3)' -s 'b = 7' 'a + b'
50000 loops, best of 11: 9.11 usec per loop
  • Loading branch information
skirpichev committed Mar 14, 2021
commit 046c84e8f970306b668d62cfacbd58f65b8c6e66
21 changes: 12 additions & 9 deletions Lib/fractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,10 @@ class doesn't subclass a concrete type, there's no

"""
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):
Expand All @@ -367,9 +369,10 @@ def forward(a, b):
forward.__doc__ = monomorphic_operator.__doc__

def reverse(b, a):
if isinstance(a, numbers.Rational):
# Includes ints.
if isinstance(a, Fraction):
return monomorphic_operator(a, b)
elif isinstance(a, numbers.Integral):
return monomorphic_operator(Fraction(a), b)
elif isinstance(a, numbers.Real):
return fallback_operator(float(a), float(b))
elif isinstance(a, numbers.Complex):
Expand Down Expand Up @@ -444,8 +447,8 @@ def reverse(b, a):
# common factors are removed by g1 == gcd(na, db).

def _add_sub_(a, b, pm=int.__add__):
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(pm(na * db, da * nb), da * db, _normalize=False)
Expand All @@ -465,8 +468,8 @@ def _add_sub_(a, b, pm=int.__add__):

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)
g2 = math.gcd(nb, da)
return Fraction((na // g1) * (nb // g2),
Expand All @@ -477,8 +480,8 @@ def _mul(a, b):
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)
g2 = math.gcd(db, da)
n, d = (na // g1) * (db // g2), (nb // g1) * (da // g2)
Expand Down
0