Commit 4e1de16f authored by Mark Dickinson's avatar Mark Dickinson

Issue #25402: in int-to-decimal-string conversion, reduce intermediate storage...

Issue #25402: in int-to-decimal-string conversion, reduce intermediate storage requirements and relax restriction on converting large integers. Patch by Serhiy Storchaka.
parent 583c6e86
...@@ -10,6 +10,10 @@ What's New in Python 3.6.0 beta 1 ...@@ -10,6 +10,10 @@ What's New in Python 3.6.0 beta 1
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #25402: In int-to-decimal-string conversion, improve the estimate
of the intermediate memory required, and remove an unnecessarily strict
overflow check. Patch by Serhiy Storchaka.
- Issue #27214: In long_invert, be more careful about modifying object - Issue #27214: In long_invert, be more careful about modifying object
returned by long_add, and remove an unnecessary check for small longs. returned by long_add, and remove an unnecessary check for small longs.
Thanks Oren Milman for analysis and patch. Thanks Oren Milman for analysis and patch.
......
...@@ -1591,6 +1591,7 @@ long_to_decimal_string_internal(PyObject *aa, ...@@ -1591,6 +1591,7 @@ long_to_decimal_string_internal(PyObject *aa,
Py_ssize_t size, strlen, size_a, i, j; Py_ssize_t size, strlen, size_a, i, j;
digit *pout, *pin, rem, tenpow; digit *pout, *pin, rem, tenpow;
int negative; int negative;
int d;
enum PyUnicode_Kind kind; enum PyUnicode_Kind kind;
a = (PyLongObject *)aa; a = (PyLongObject *)aa;
...@@ -1608,15 +1609,17 @@ long_to_decimal_string_internal(PyObject *aa, ...@@ -1608,15 +1609,17 @@ long_to_decimal_string_internal(PyObject *aa,
But log2(a) < size_a * PyLong_SHIFT, and But log2(a) < size_a * PyLong_SHIFT, and
log2(_PyLong_DECIMAL_BASE) = log2(10) * _PyLong_DECIMAL_SHIFT log2(_PyLong_DECIMAL_BASE) = log2(10) * _PyLong_DECIMAL_SHIFT
> 3 * _PyLong_DECIMAL_SHIFT > 3.3 * _PyLong_DECIMAL_SHIFT
size_a * PyLong_SHIFT / (3.3 * _PyLong_DECIMAL_SHIFT) =
size_a + size_a / d < size_a + size_a / floor(d),
where d = (3.3 * _PyLong_DECIMAL_SHIFT) /
(PyLong_SHIFT - 3.3 * _PyLong_DECIMAL_SHIFT)
*/ */
if (size_a > PY_SSIZE_T_MAX / PyLong_SHIFT) { d = (33 * _PyLong_DECIMAL_SHIFT) /
PyErr_SetString(PyExc_OverflowError, (10 * PyLong_SHIFT - 33 * _PyLong_DECIMAL_SHIFT);
"int too large to format"); assert(size_a < PY_SSIZE_T_MAX/2);
return -1; size = 1 + size_a + size_a / d;
}
/* the expression size_a * PyLong_SHIFT is now safe from overflow */
size = 1 + size_a * PyLong_SHIFT / (3 * _PyLong_DECIMAL_SHIFT);
scratch = _PyLong_New(size); scratch = _PyLong_New(size);
if (scratch == NULL) if (scratch == NULL)
return -1; return -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment