From: Mark Dickinson Date: Mon, 29 Aug 2016 16:26:43 +0000 (+0100) Subject: Issue #25402: in int-to-decimal-string conversion, reduce intermediate storage requir... X-Git-Tag: v3.6.0b1~530 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4e1de16f88cd8b99b2d154e647b63f2f6f8b58ae;p=python Issue #25402: in int-to-decimal-string conversion, reduce intermediate storage requirements and relax restriction on converting large integers. Patch by Serhiy Storchaka. --- diff --git a/Misc/NEWS b/Misc/NEWS index 32144d1311..9873abbab8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ What's New in Python 3.6.0 beta 1 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 returned by long_add, and remove an unnecessary check for small longs. Thanks Oren Milman for analysis and patch. diff --git a/Objects/longobject.c b/Objects/longobject.c index 89b6862605..ba23599535 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1591,6 +1591,7 @@ long_to_decimal_string_internal(PyObject *aa, Py_ssize_t size, strlen, size_a, i, j; digit *pout, *pin, rem, tenpow; int negative; + int d; enum PyUnicode_Kind kind; a = (PyLongObject *)aa; @@ -1608,15 +1609,17 @@ long_to_decimal_string_internal(PyObject *aa, But log2(a) < size_a * PyLong_SHIFT, and 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) { - PyErr_SetString(PyExc_OverflowError, - "int too large to format"); - return -1; - } - /* the expression size_a * PyLong_SHIFT is now safe from overflow */ - size = 1 + size_a * PyLong_SHIFT / (3 * _PyLong_DECIMAL_SHIFT); + d = (33 * _PyLong_DECIMAL_SHIFT) / + (10 * PyLong_SHIFT - 33 * _PyLong_DECIMAL_SHIFT); + assert(size_a < PY_SSIZE_T_MAX/2); + size = 1 + size_a + size_a / d; scratch = _PyLong_New(size); if (scratch == NULL) return -1;