Issue #6713: Improve decimal int -> string conversions. Thanks Gawain
Bolton for the suggestion and original patches.
This commit is contained in:
parent
4780c9a0e0
commit
4b9d473d0a
|
@ -18,7 +18,8 @@ Core and Builtins
|
||||||
- Issue #6922: Fix an infinite loop when trying to decode an invalid
|
- Issue #6922: Fix an infinite loop when trying to decode an invalid
|
||||||
UTF-32 stream with a non-raising error handler like "replace" or "ignore".
|
UTF-32 stream with a non-raising error handler like "replace" or "ignore".
|
||||||
|
|
||||||
- Issue #6713: Improve performance of integer -> string conversions.
|
- Issue #6713: Improve performance of base 10 int -> string and
|
||||||
|
long -> string conversions.
|
||||||
|
|
||||||
- Issue #1590864: Fix potential deadlock when mixing threads and fork().
|
- Issue #1590864: Fix potential deadlock when mixing threads and fork().
|
||||||
|
|
||||||
|
|
|
@ -436,12 +436,6 @@ int_print(PyIntObject *v, FILE *fp, int flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
int_repr(PyIntObject *v)
|
|
||||||
{
|
|
||||||
return _PyInt_Format(v, 10, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
int_compare(PyIntObject *v, PyIntObject *w)
|
int_compare(PyIntObject *v, PyIntObject *w)
|
||||||
{
|
{
|
||||||
|
@ -1113,6 +1107,26 @@ int_get1(PyIntObject *v, void *context) {
|
||||||
return PyInt_FromLong(1L);
|
return PyInt_FromLong(1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert an integer to a decimal string. On many platforms, this
|
||||||
|
will be significantly faster than the general arbitrary-base
|
||||||
|
conversion machinery in _PyInt_Format, thanks to optimization
|
||||||
|
opportunities offered by division by a compile-time constant. */
|
||||||
|
static PyObject *
|
||||||
|
int_to_decimal_string(PyIntObject *v) {
|
||||||
|
char buf[sizeof(long)*CHAR_BIT/3+6], *p, *bufend;
|
||||||
|
long n = v->ob_ival;
|
||||||
|
unsigned long absn;
|
||||||
|
p = bufend = buf + sizeof(buf);
|
||||||
|
absn = n < 0 ? -(unsigned long)n : n;
|
||||||
|
do {
|
||||||
|
*--p = '0' + absn % 10;
|
||||||
|
absn /= 10;
|
||||||
|
} while (absn);
|
||||||
|
if (n < 0)
|
||||||
|
*--p = '-';
|
||||||
|
return PyString_FromStringAndSize(p, bufend - p);
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert an integer to the given base. Returns a string.
|
/* Convert an integer to the given base. Returns a string.
|
||||||
If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'.
|
If base is 2, 8 or 16, add the proper prefix '0b', '0o' or '0x'.
|
||||||
If newstyle is zero, then use the pre-2.6 behavior of octal having
|
If newstyle is zero, then use the pre-2.6 behavior of octal having
|
||||||
|
@ -1137,6 +1151,10 @@ _PyInt_Format(PyIntObject *v, int base, int newstyle)
|
||||||
|
|
||||||
assert(base >= 2 && base <= 36);
|
assert(base >= 2 && base <= 36);
|
||||||
|
|
||||||
|
/* Special case base 10, for speed */
|
||||||
|
if (base == 10)
|
||||||
|
return int_to_decimal_string(v);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* I'd use i_divmod, except it doesn't produce the results
|
/* I'd use i_divmod, except it doesn't produce the results
|
||||||
I want when n is negative. So just duplicate the salient
|
I want when n is negative. So just duplicate the salient
|
||||||
|
@ -1169,7 +1187,7 @@ _PyInt_Format(PyIntObject *v, int base, int newstyle)
|
||||||
*--p = 'x';
|
*--p = 'x';
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
}
|
}
|
||||||
else if (base != 10) {
|
else {
|
||||||
*--p = '#';
|
*--p = '#';
|
||||||
*--p = '0' + base%10;
|
*--p = '0' + base%10;
|
||||||
if (base > 10)
|
if (base > 10)
|
||||||
|
@ -1341,13 +1359,13 @@ PyTypeObject PyInt_Type = {
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
(cmpfunc)int_compare, /* tp_compare */
|
(cmpfunc)int_compare, /* tp_compare */
|
||||||
(reprfunc)int_repr, /* tp_repr */
|
(reprfunc)int_to_decimal_string, /* tp_repr */
|
||||||
&int_as_number, /* tp_as_number */
|
&int_as_number, /* tp_as_number */
|
||||||
0, /* tp_as_sequence */
|
0, /* tp_as_sequence */
|
||||||
0, /* tp_as_mapping */
|
0, /* tp_as_mapping */
|
||||||
(hashfunc)int_hash, /* tp_hash */
|
(hashfunc)int_hash, /* tp_hash */
|
||||||
0, /* tp_call */
|
0, /* tp_call */
|
||||||
(reprfunc)int_repr, /* tp_str */
|
(reprfunc)int_to_decimal_string, /* tp_str */
|
||||||
PyObject_GenericGetAttr, /* tp_getattro */
|
PyObject_GenericGetAttr, /* tp_getattro */
|
||||||
0, /* tp_setattro */
|
0, /* tp_setattro */
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
|
|
Loading…
Reference in New Issue