8000 [3.12] gh-118164: str(10**10000) hangs if the C _decimal module is missing (GH-118503) by miss-islington · Pull Request #118584 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

[3.12] gh-118164: str(10**10000) hangs if the C _decimal module is missing (GH-118503) #118584

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 1 commit into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 15 additions & 4 deletions Lib/_pydecimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -2131,10 +2131,16 @@ def _power_exact(self, other, p):
else:
return None

if xc >= 10**p:
# An exact power of 10 is representable, but can convert to a
# string of any length. But an exact power of 10 shouldn't be
# possible at this point.
assert xc > 1, self
assert xc % 10 != 0, self
strxc = str(xc)
if len(strxc) > p:
return None
xe = -e-xe
return _dec_from_triple(0, str(xc), xe)
return _dec_from_triple(0, strxc, xe)

# now y is positive; find m and n such that y = m/n
if ye >= 0:
Expand Down Expand Up @@ -2184,13 +2190,18 @@ def _power_exact(self, other, p):
return None
xc = xc**m
xe *= m
if xc > 10**p:
# An exact power of 10 is representable, but can convert to a string
# of any length. But an exact power of 10 shouldn't be possible at
# this point.
assert xc > 1, self
assert xc % 10 != 0, self
str_xc = str(xc)
if len(str_xc) > p:
return None

# by this point the result *is* exactly representable
# adjust the exponent to get as close as possible to the ideal
# exponent, if necessary
str_xc = str(xc)
if other._isinteger() and other._sign == 0:
ideal_exponent = self._exp*int(other)
zeros = min(xe-ideal_exponent, p-len(str_xc))
Expand Down
25 changes: 24 additions & 1 deletion Lib/test/test_decimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -4722,9 +4722,33 @@ def test_py_exact_power(self):

c.prec = 1
x = Decimal("152587890625") ** Decimal('-0.5')
self.assertEqual(x, Decimal('3e-6'))
c.prec = 2 8000
x = Decimal("152587890625") ** Decimal('-0.5')
self.assertEqual(x, Decimal('2.6e-6'))
c.prec = 3
x = Decimal("152587890625") ** Decimal('-0.5')
self.assertEqual(x, Decimal('2.56e-6'))
c.prec = 28
x = Decimal("152587890625") ** Decimal('-0.5')
self.assertEqual(x, Decimal('2.56e-6'))

c.prec = 201
x = Decimal(2**578) ** Decimal("-0.5")

# See https://github.com/python/cpython/issues/118027
# Testing for an exact power could appear to hang, in the Python
# version, as it attempted to compute 10**(MAX_EMAX + 1).
# Fixed via https://github.com/python/cpython/pull/118503.
c.prec = P.MAX_PREC
c.Emax = P.MAX_EMAX
c.Emin = P.MIN_EMIN
c.traps[P.Inexact] = 1
D2 = Decimal(2)
# If the bug is still present, the next statement won't complete.
res = D2 ** 117
self.assertEqual(res, 1 << 117)

def test_py_immutability_operations(self):
# Do operations and check that it didn't change internal objects.
Decimal = P.Decimal
Expand Down Expand Up @@ -5737,7 +5761,6 @@ def test_format_fallback_rounding(self):
with C.localcontext(rounding=C.ROUND_DOWN):
self.assertEqual(format(y, '#.1f'), '6.0')


@requires_docstrings
@requires_cdecimal
class SignatureTest(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The Python implementation of the ``decimal`` module could appear to hang in relatively small power cases (like ``2**117``) if context precision was set to a very high value. A different method to check for exactly representable results is used now that doesn't rely on computing ``10**precision`` (which could be effectively too large to compute).
Loading
0