mirror of https://github.com/python/cpython
Issue #12080: Fix a performance issue in Decimal._power_exact that caused some corner-case Decimal.__pow__ calls to take an unreasonably long time.
This commit is contained in:
parent
7d21401811
commit
a493ca3fae
111
Lib/decimal.py
111
Lib/decimal.py
|
@ -1942,9 +1942,9 @@ class Decimal(object):
|
||||||
nonzero. For efficiency, other._exp should not be too large,
|
nonzero. For efficiency, other._exp should not be too large,
|
||||||
so that 10**abs(other._exp) is a feasible calculation."""
|
so that 10**abs(other._exp) is a feasible calculation."""
|
||||||
|
|
||||||
# In the comments below, we write x for the value of self and
|
# In the comments below, we write x for the value of self and y for the
|
||||||
# y for the value of other. Write x = xc*10**xe and y =
|
# value of other. Write x = xc*10**xe and abs(y) = yc*10**ye, with xc
|
||||||
# yc*10**ye.
|
# and yc positive integers not divisible by 10.
|
||||||
|
|
||||||
# The main purpose of this method is to identify the *failure*
|
# The main purpose of this method is to identify the *failure*
|
||||||
# of x**y to be exactly representable with as little effort as
|
# of x**y to be exactly representable with as little effort as
|
||||||
|
@ -1952,13 +1952,12 @@ class Decimal(object):
|
||||||
# eliminate the possibility of x**y being exact. Only if all
|
# eliminate the possibility of x**y being exact. Only if all
|
||||||
# these tests are passed do we go on to actually compute x**y.
|
# these tests are passed do we go on to actually compute x**y.
|
||||||
|
|
||||||
# Here's the main idea. First normalize both x and y. We
|
# Here's the main idea. Express y as a rational number m/n, with m and
|
||||||
# express y as a rational m/n, with m and n relatively prime
|
# n relatively prime and n>0. Then for x**y to be exactly
|
||||||
# and n>0. Then for x**y to be exactly representable (at
|
# representable (at *any* precision), xc must be the nth power of a
|
||||||
# *any* precision), xc must be the nth power of a positive
|
# positive integer and xe must be divisible by n. If y is negative
|
||||||
# integer and xe must be divisible by n. If m is negative
|
# then additionally xc must be a power of either 2 or 5, hence a power
|
||||||
# then additionally xc must be a power of either 2 or 5, hence
|
# of 2**n or 5**n.
|
||||||
# a power of 2**n or 5**n.
|
|
||||||
#
|
#
|
||||||
# There's a limit to how small |y| can be: if y=m/n as above
|
# There's a limit to how small |y| can be: if y=m/n as above
|
||||||
# then:
|
# then:
|
||||||
|
@ -2030,21 +2029,43 @@ class Decimal(object):
|
||||||
return None
|
return None
|
||||||
# now xc is a power of 2; e is its exponent
|
# now xc is a power of 2; e is its exponent
|
||||||
e = _nbits(xc)-1
|
e = _nbits(xc)-1
|
||||||
# find e*y and xe*y; both must be integers
|
|
||||||
if ye >= 0:
|
# We now have:
|
||||||
y_as_int = yc*10**ye
|
#
|
||||||
e = e*y_as_int
|
# x = 2**e * 10**xe, e > 0, and y < 0.
|
||||||
xe = xe*y_as_int
|
#
|
||||||
else:
|
# The exact result is:
|
||||||
ten_pow = 10**-ye
|
#
|
||||||
e, remainder = divmod(e*yc, ten_pow)
|
# x**y = 5**(-e*y) * 10**(e*y + xe*y)
|
||||||
if remainder:
|
#
|
||||||
return None
|
# provided that both e*y and xe*y are integers. Note that if
|
||||||
xe, remainder = divmod(xe*yc, ten_pow)
|
# 5**(-e*y) >= 10**p, then the result can't be expressed
|
||||||
if remainder:
|
# exactly with p digits of precision.
|
||||||
|
#
|
||||||
|
# Using the above, we can guard against large values of ye.
|
||||||
|
# 93/65 is an upper bound for log(10)/log(5), so if
|
||||||
|
#
|
||||||
|
# ye >= len(str(93*p//65))
|
||||||
|
#
|
||||||
|
# then
|
||||||
|
#
|
||||||
|
# -e*y >= -y >= 10**ye > 93*p/65 > p*log(10)/log(5),
|
||||||
|
#
|
||||||
|
# so 5**(-e*y) >= 10**p, and the coefficient of the result
|
||||||
|
# can't be expressed in p digits.
|
||||||
|
|
||||||
|
# emax >= largest e such that 5**e < 10**p.
|
||||||
|
emax = p*93//65
|
||||||
|
if ye >= len(str(emax)):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if e*65 >= p*93: # 93/65 > log(10)/log(5)
|
# Find -e*y and -xe*y; both must be integers
|
||||||
|
e = _decimal_lshift_exact(e * yc, ye)
|
||||||
|
xe = _decimal_lshift_exact(xe * yc, ye)
|
||||||
|
if e is None or xe is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if e > emax:
|
||||||
return None
|
return None
|
||||||
xc = 5**e
|
xc = 5**e
|
||||||
|
|
||||||
|
@ -2058,19 +2079,20 @@ class Decimal(object):
|
||||||
while xc % 5 == 0:
|
while xc % 5 == 0:
|
||||||
xc //= 5
|
xc //= 5
|
||||||
e -= 1
|
e -= 1
|
||||||
if ye >= 0:
|
|
||||||
y_as_integer = yc*10**ye
|
# Guard against large values of ye, using the same logic as in
|
||||||
e = e*y_as_integer
|
# the 'xc is a power of 2' branch. 10/3 is an upper bound for
|
||||||
xe = xe*y_as_integer
|
# log(10)/log(2).
|
||||||
else:
|
emax = p*10//3
|
||||||
ten_pow = 10**-ye
|
if ye >= len(str(emax)):
|
||||||
e, remainder = divmod(e*yc, ten_pow)
|
|
||||||
if remainder:
|
|
||||||
return None
|
return None
|
||||||
xe, remainder = divmod(xe*yc, ten_pow)
|
|
||||||
if remainder:
|
e = _decimal_lshift_exact(e * yc, ye)
|
||||||
|
xe = _decimal_lshift_exact(xe * yc, ye)
|
||||||
|
if e is None or xe is None:
|
||||||
return None
|
return None
|
||||||
if e*3 >= p*10: # 10/3 > log(10)/log(2)
|
|
||||||
|
if e > emax:
|
||||||
return None
|
return None
|
||||||
xc = 2**e
|
xc = 2**e
|
||||||
else:
|
else:
|
||||||
|
@ -5463,6 +5485,27 @@ def _nbits(n, correction = {
|
||||||
hex_n = "%x" % n
|
hex_n = "%x" % n
|
||||||
return 4*len(hex_n) - correction[hex_n[0]]
|
return 4*len(hex_n) - correction[hex_n[0]]
|
||||||
|
|
||||||
|
def _decimal_lshift_exact(n, e):
|
||||||
|
""" Given integers n and e, return n * 10**e if it's an integer, else None.
|
||||||
|
|
||||||
|
The computation is designed to avoid computing large powers of 10
|
||||||
|
unnecessarily.
|
||||||
|
|
||||||
|
>>> _decimal_lshift_exact(3, 4)
|
||||||
|
30000
|
||||||
|
>>> _decimal_lshift_exact(300, -999999999) # returns None
|
||||||
|
|
||||||
|
"""
|
||||||
|
if n == 0:
|
||||||
|
return 0
|
||||||
|
elif e >= 0:
|
||||||
|
return n * 10**e
|
||||||
|
else:
|
||||||
|
# val_n = largest power of 10 dividing n.
|
||||||
|
str_n = str(abs(n))
|
||||||
|
val_n = len(str_n) - len(str_n.rstrip('0'))
|
||||||
|
return None if val_n < -e else n // 10**-e
|
||||||
|
|
||||||
def _sqrt_nearest(n, a):
|
def _sqrt_nearest(n, a):
|
||||||
"""Closest integer to the square root of the positive integer n. a is
|
"""Closest integer to the square root of the positive integer n. a is
|
||||||
an initial approximation to the square root. Any positive integer
|
an initial approximation to the square root. Any positive integer
|
||||||
|
|
|
@ -222,12 +222,25 @@ extr1700 power 10 1e-999999999 -> 1.000000000000000 Inexact Rounded
|
||||||
extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded
|
extr1701 power 100.0 -557.71e-742888888 -> 1.000000000000000 Inexact Rounded
|
||||||
extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded
|
extr1702 power 10 1e-100 -> 1.000000000000000 Inexact Rounded
|
||||||
|
|
||||||
|
-- Another one (see issue #12080). Thanks again to Stefan Krah.
|
||||||
|
extr1703 power 4 -1.2e-999999999 -> 1.000000000000000 Inexact Rounded
|
||||||
|
|
||||||
-- A couple of interesting exact cases for power. Note that the specification
|
-- A couple of interesting exact cases for power. Note that the specification
|
||||||
-- requires these to be reported as Inexact.
|
-- requires these to be reported as Inexact.
|
||||||
extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded
|
extr1710 power 1e375 56e-3 -> 1.000000000000000E+21 Inexact Rounded
|
||||||
extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded
|
extr1711 power 10000 0.75 -> 1000.000000000000 Inexact Rounded
|
||||||
extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded
|
extr1712 power 1e-24 0.875 -> 1.000000000000000E-21 Inexact Rounded
|
||||||
|
|
||||||
|
-- Some more exact cases, exercising power with negative second argument.
|
||||||
|
extr1720 power 400 -0.5 -> 0.05000000000000000 Inexact Rounded
|
||||||
|
extr1721 power 4096 -0.75 -> 0.001953125000000000 Inexact Rounded
|
||||||
|
extr1722 power 625e4 -0.25 -> 0.02000000000000000 Inexact Rounded
|
||||||
|
|
||||||
|
-- Nonexact cases, to exercise some of the early exit conditions from
|
||||||
|
-- _power_exact.
|
||||||
|
extr1730 power 2048 -0.75 -> 0.003284751622084822 Inexact Rounded
|
||||||
|
|
||||||
|
|
||||||
-- Tests for the is_* boolean operations
|
-- Tests for the is_* boolean operations
|
||||||
precision: 9
|
precision: 9
|
||||||
maxExponent: 999
|
maxExponent: 999
|
||||||
|
|
|
@ -16,6 +16,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #12080: Fix a performance issue in Decimal._power_exact that caused
|
||||||
|
some corner-case Decimal.__pow__ calls to take an unreasonably long time.
|
||||||
|
|
||||||
- Named tuples now work correctly with vars().
|
- Named tuples now work correctly with vars().
|
||||||
|
|
||||||
- sys.setcheckinterval() now updates the current ticker count as well as updating
|
- sys.setcheckinterval() now updates the current ticker count as well as updating
|
||||||
|
|
Loading…
Reference in New Issue