mirror of https://github.com/python/cpython
Issue #28621: Sped up converting int to float by reusing faster bits counting
implementation. Patch by Adrian Wielgosik.
This commit is contained in:
parent
b74fecc396
commit
b2e64f903d
|
@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #28621: Sped up converting int to float by reusing faster bits counting
|
||||||
|
implementation. Patch by Adrian Wielgosik.
|
||||||
|
|
||||||
- Issue #28580: Optimize iterating split table values.
|
- Issue #28580: Optimize iterating split table values.
|
||||||
Patch by Xiang Zhang.
|
Patch by Xiang Zhang.
|
||||||
|
|
||||||
|
|
|
@ -708,12 +708,33 @@ _PyLong_Sign(PyObject *vv)
|
||||||
return Py_SIZE(v) == 0 ? 0 : (Py_SIZE(v) < 0 ? -1 : 1);
|
return Py_SIZE(v) == 0 ? 0 : (Py_SIZE(v) < 0 ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
|
||||||
|
2**k if d is nonzero, else 0. */
|
||||||
|
|
||||||
|
static const unsigned char BitLengthTable[32] = {
|
||||||
|
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
bits_in_digit(digit d)
|
||||||
|
{
|
||||||
|
int d_bits = 0;
|
||||||
|
while (d >= 32) {
|
||||||
|
d_bits += 6;
|
||||||
|
d >>= 6;
|
||||||
|
}
|
||||||
|
d_bits += (int)BitLengthTable[d];
|
||||||
|
return d_bits;
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
_PyLong_NumBits(PyObject *vv)
|
_PyLong_NumBits(PyObject *vv)
|
||||||
{
|
{
|
||||||
PyLongObject *v = (PyLongObject *)vv;
|
PyLongObject *v = (PyLongObject *)vv;
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
Py_ssize_t ndigits;
|
Py_ssize_t ndigits;
|
||||||
|
int msd_bits;
|
||||||
|
|
||||||
assert(v != NULL);
|
assert(v != NULL);
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
|
@ -724,12 +745,10 @@ _PyLong_NumBits(PyObject *vv)
|
||||||
if ((size_t)(ndigits - 1) > SIZE_MAX / (size_t)PyLong_SHIFT)
|
if ((size_t)(ndigits - 1) > SIZE_MAX / (size_t)PyLong_SHIFT)
|
||||||
goto Overflow;
|
goto Overflow;
|
||||||
result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
|
result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
|
||||||
do {
|
msd_bits = bits_in_digit(msd);
|
||||||
++result;
|
if (SIZE_MAX - msd_bits < result)
|
||||||
if (result == 0)
|
goto Overflow;
|
||||||
goto Overflow;
|
result += msd_bits;
|
||||||
msd >>= 1;
|
|
||||||
} while (msd);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -1414,26 +1433,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
|
||||||
Py_RETURN_NOTIMPLEMENTED; \
|
Py_RETURN_NOTIMPLEMENTED; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
|
|
||||||
2**k if d is nonzero, else 0. */
|
|
||||||
|
|
||||||
static const unsigned char BitLengthTable[32] = {
|
|
||||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
||||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
bits_in_digit(digit d)
|
|
||||||
{
|
|
||||||
int d_bits = 0;
|
|
||||||
while (d >= 32) {
|
|
||||||
d_bits += 6;
|
|
||||||
d >>= 6;
|
|
||||||
}
|
|
||||||
d_bits += (int)BitLengthTable[d];
|
|
||||||
return d_bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n]
|
/* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n]
|
||||||
* is modified in place, by adding y to it. Carries are propagated as far as
|
* is modified in place, by adding y to it. Carries are propagated as far as
|
||||||
* x[m-1], and the remaining carry (0 or 1) is returned.
|
* x[m-1], and the remaining carry (0 or 1) is returned.
|
||||||
|
@ -5079,7 +5078,8 @@ static PyObject *
|
||||||
long_bit_length(PyLongObject *v)
|
long_bit_length(PyLongObject *v)
|
||||||
{
|
{
|
||||||
PyLongObject *result, *x, *y;
|
PyLongObject *result, *x, *y;
|
||||||
Py_ssize_t ndigits, msd_bits = 0;
|
Py_ssize_t ndigits;
|
||||||
|
int msd_bits;
|
||||||
digit msd;
|
digit msd;
|
||||||
|
|
||||||
assert(v != NULL);
|
assert(v != NULL);
|
||||||
|
@ -5090,11 +5090,7 @@ long_bit_length(PyLongObject *v)
|
||||||
return PyLong_FromLong(0);
|
return PyLong_FromLong(0);
|
||||||
|
|
||||||
msd = v->ob_digit[ndigits-1];
|
msd = v->ob_digit[ndigits-1];
|
||||||
while (msd >= 32) {
|
msd_bits = bits_in_digit(msd);
|
||||||
msd_bits += 6;
|
|
||||||
msd >>= 6;
|
|
||||||
}
|
|
||||||
msd_bits += (long)(BitLengthTable[msd]);
|
|
||||||
|
|
||||||
if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT)
|
if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT)
|
||||||
return PyLong_FromSsize_t((ndigits-1)*PyLong_SHIFT + msd_bits);
|
return PyLong_FromSsize_t((ndigits-1)*PyLong_SHIFT + msd_bits);
|
||||||
|
|
Loading…
Reference in New Issue