mirror of https://github.com/python/cpython
gh-123497: New limit for Python integers on 64-bit platforms (GH-123724)
Instead of be limited just by the size of addressable memory (2**63 bytes), Python integers are now also limited by the number of bits, so the number of bit now always fit in a 64-bit integer. Both limits are much larger than what might be available in practice, so it doesn't affect users. _PyLong_NumBits() and _PyLong_Frexp() are now always successful.
This commit is contained in:
parent
e0a41a5dd1
commit
d08c788822
|
@ -71,10 +71,9 @@ PyAPI_FUNC(int) _PyLong_Sign(PyObject *v);
|
||||||
absolute value of a long. For example, this returns 1 for 1 and -1, 2
|
absolute value of a long. For example, this returns 1 for 1 and -1, 2
|
||||||
for 2 and -2, and 2 for 3 and -3. It returns 0 for 0.
|
for 2 and -2, and 2 for 3 and -3. It returns 0 for 0.
|
||||||
v must not be NULL, and must be a normalized long.
|
v must not be NULL, and must be a normalized long.
|
||||||
(uint64_t)-1 is returned and OverflowError set if the true result doesn't
|
Always successful.
|
||||||
fit in a size_t.
|
|
||||||
*/
|
*/
|
||||||
PyAPI_FUNC(uint64_t) _PyLong_NumBits(PyObject *v);
|
PyAPI_FUNC(int64_t) _PyLong_NumBits(PyObject *v);
|
||||||
|
|
||||||
/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in
|
/* _PyLong_FromByteArray: View the n unsigned bytes as a binary integer in
|
||||||
base 256, and return a Python int with the same numeric value.
|
base 256, and return a Python int with the same numeric value.
|
||||||
|
|
|
@ -79,11 +79,10 @@ static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// _PyLong_Frexp returns a double x and an exponent e such that the
|
// _PyLong_Frexp returns a double x and an exponent e such that the
|
||||||
// true value is approximately equal to x * 2**e. e is >= 0. x is
|
// true value is approximately equal to x * 2**e. x is
|
||||||
// 0.0 if and only if the input is 0 (in which case, e and x are both
|
// 0.0 if and only if the input is 0 (in which case, e and x are both
|
||||||
// zeroes); otherwise, 0.5 <= abs(x) < 1.0. On overflow, which is
|
// zeroes); otherwise, 0.5 <= abs(x) < 1.0.
|
||||||
// possible if the number of bits doesn't fit into a Py_ssize_t, sets
|
// Always successful.
|
||||||
// OverflowError and returns -1.0 for x, 0 for e.
|
|
||||||
//
|
//
|
||||||
// Export for 'math' shared extension
|
// Export for 'math' shared extension
|
||||||
PyAPI_DATA(double) _PyLong_Frexp(PyLongObject *a, int64_t *e);
|
PyAPI_DATA(double) _PyLong_Frexp(PyLongObject *a, int64_t *e);
|
||||||
|
@ -105,10 +104,10 @@ PyAPI_DATA(PyObject*) _PyLong_DivmodNear(PyObject *, PyObject *);
|
||||||
PyAPI_DATA(PyObject*) _PyLong_Format(PyObject *obj, int base);
|
PyAPI_DATA(PyObject*) _PyLong_Format(PyObject *obj, int base);
|
||||||
|
|
||||||
// Export for 'math' shared extension
|
// Export for 'math' shared extension
|
||||||
PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, uint64_t);
|
PyAPI_DATA(PyObject*) _PyLong_Rshift(PyObject *, int64_t);
|
||||||
|
|
||||||
// Export for 'math' shared extension
|
// Export for 'math' shared extension
|
||||||
PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, uint64_t);
|
PyAPI_DATA(PyObject*) _PyLong_Lshift(PyObject *, int64_t);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject*) _PyLong_Add(PyLongObject *left, PyLongObject *right);
|
PyAPI_FUNC(PyObject*) _PyLong_Add(PyLongObject *left, PyLongObject *right);
|
||||||
PyAPI_FUNC(PyObject*) _PyLong_Multiply(PyLongObject *left, PyLongObject *right);
|
PyAPI_FUNC(PyObject*) _PyLong_Multiply(PyLongObject *left, PyLongObject *right);
|
||||||
|
|
|
@ -2146,7 +2146,7 @@ save_long(PicklerObject *self, PyObject *obj)
|
||||||
|
|
||||||
if (self->proto >= 2) {
|
if (self->proto >= 2) {
|
||||||
/* Linear-time pickling. */
|
/* Linear-time pickling. */
|
||||||
uint64_t nbits;
|
int64_t nbits;
|
||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
unsigned char *pdata;
|
unsigned char *pdata;
|
||||||
char header[5];
|
char header[5];
|
||||||
|
@ -2161,8 +2161,8 @@ save_long(PicklerObject *self, PyObject *obj)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
nbits = _PyLong_NumBits(obj);
|
nbits = _PyLong_NumBits(obj);
|
||||||
if (nbits == (uint64_t)-1 && PyErr_Occurred())
|
assert(nbits >= 0);
|
||||||
goto error;
|
assert(!PyErr_Occurred());
|
||||||
/* How many bytes do we need? There are nbits >> 3 full
|
/* How many bytes do we need? There are nbits >> 3 full
|
||||||
* bytes of data, and nbits & 7 leftover bits. If there
|
* bytes of data, and nbits & 7 leftover bits. If there
|
||||||
* are any leftover bits, then we clearly need another
|
* are any leftover bits, then we clearly need another
|
||||||
|
|
|
@ -295,7 +295,7 @@ random_seed(RandomObject *self, PyObject *arg)
|
||||||
int result = -1; /* guilty until proved innocent */
|
int result = -1; /* guilty until proved innocent */
|
||||||
PyObject *n = NULL;
|
PyObject *n = NULL;
|
||||||
uint32_t *key = NULL;
|
uint32_t *key = NULL;
|
||||||
uint64_t bits;
|
int64_t bits;
|
||||||
size_t keyused;
|
size_t keyused;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
@ -335,8 +335,8 @@ random_seed(RandomObject *self, PyObject *arg)
|
||||||
|
|
||||||
/* Now split n into 32-bit chunks, from the right. */
|
/* Now split n into 32-bit chunks, from the right. */
|
||||||
bits = _PyLong_NumBits(n);
|
bits = _PyLong_NumBits(n);
|
||||||
if (bits == (uint64_t)-1 && PyErr_Occurred())
|
assert(bits >= 0);
|
||||||
goto Done;
|
assert(!PyErr_Occurred());
|
||||||
|
|
||||||
/* Figure out how many 32-bit chunks this gives us. */
|
/* Figure out how many 32-bit chunks this gives us. */
|
||||||
keyused = bits == 0 ? 1 : (size_t)((bits - 1) / 32 + 1);
|
keyused = bits == 0 ? 1 : (size_t)((bits - 1) / 32 + 1);
|
||||||
|
|
|
@ -1657,7 +1657,7 @@ math_isqrt(PyObject *module, PyObject *n)
|
||||||
/*[clinic end generated code: output=35a6f7f980beab26 input=5b6e7ae4fa6c43d6]*/
|
/*[clinic end generated code: output=35a6f7f980beab26 input=5b6e7ae4fa6c43d6]*/
|
||||||
{
|
{
|
||||||
int a_too_large, c_bit_length;
|
int a_too_large, c_bit_length;
|
||||||
uint64_t c, d;
|
int64_t c, d;
|
||||||
uint64_t m;
|
uint64_t m;
|
||||||
uint32_t u;
|
uint32_t u;
|
||||||
PyObject *a = NULL, *b;
|
PyObject *a = NULL, *b;
|
||||||
|
@ -1680,14 +1680,13 @@ math_isqrt(PyObject *module, PyObject *n)
|
||||||
|
|
||||||
/* c = (n.bit_length() - 1) // 2 */
|
/* c = (n.bit_length() - 1) // 2 */
|
||||||
c = _PyLong_NumBits(n);
|
c = _PyLong_NumBits(n);
|
||||||
if (c == (uint64_t)(-1)) {
|
assert(c > 0);
|
||||||
goto error;
|
assert(!PyErr_Occurred());
|
||||||
}
|
c = (c - 1) / 2;
|
||||||
c = (c - 1U) / 2U;
|
|
||||||
|
|
||||||
/* Fast path: if c <= 31 then n < 2**64 and we can compute directly with a
|
/* Fast path: if c <= 31 then n < 2**64 and we can compute directly with a
|
||||||
fast, almost branch-free algorithm. */
|
fast, almost branch-free algorithm. */
|
||||||
if (c <= 31U) {
|
if (c <= 31) {
|
||||||
int shift = 31 - (int)c;
|
int shift = 31 - (int)c;
|
||||||
m = (uint64_t)PyLong_AsUnsignedLongLong(n);
|
m = (uint64_t)PyLong_AsUnsignedLongLong(n);
|
||||||
Py_DECREF(n);
|
Py_DECREF(n);
|
||||||
|
@ -1704,13 +1703,13 @@ math_isqrt(PyObject *module, PyObject *n)
|
||||||
|
|
||||||
/* From n >= 2**64 it follows that c.bit_length() >= 6. */
|
/* From n >= 2**64 it follows that c.bit_length() >= 6. */
|
||||||
c_bit_length = 6;
|
c_bit_length = 6;
|
||||||
while ((c >> c_bit_length) > 0U) {
|
while ((c >> c_bit_length) > 0) {
|
||||||
++c_bit_length;
|
++c_bit_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise d and a. */
|
/* Initialise d and a. */
|
||||||
d = c >> (c_bit_length - 5);
|
d = c >> (c_bit_length - 5);
|
||||||
b = _PyLong_Rshift(n, 2U*c - 62U);
|
b = _PyLong_Rshift(n, 2*c - 62);
|
||||||
if (b == NULL) {
|
if (b == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1727,12 +1726,12 @@ math_isqrt(PyObject *module, PyObject *n)
|
||||||
|
|
||||||
for (int s = c_bit_length - 6; s >= 0; --s) {
|
for (int s = c_bit_length - 6; s >= 0; --s) {
|
||||||
PyObject *q;
|
PyObject *q;
|
||||||
uint64_t e = d;
|
int64_t e = d;
|
||||||
|
|
||||||
d = c >> s;
|
d = c >> s;
|
||||||
|
|
||||||
/* q = (n >> 2*c - e - d + 1) // a */
|
/* q = (n >> 2*c - e - d + 1) // a */
|
||||||
q = _PyLong_Rshift(n, 2U*c - d - e + 1U);
|
q = _PyLong_Rshift(n, 2*c - d - e + 1);
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1742,7 +1741,7 @@ math_isqrt(PyObject *module, PyObject *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* a = (a << d - 1 - e) + q */
|
/* a = (a << d - 1 - e) + q */
|
||||||
Py_SETREF(a, _PyLong_Lshift(a, d - 1U - e));
|
Py_SETREF(a, _PyLong_Lshift(a, d - 1 - e));
|
||||||
if (a == NULL) {
|
if (a == NULL) {
|
||||||
Py_DECREF(q);
|
Py_DECREF(q);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -2202,8 +2201,8 @@ loghelper(PyObject* arg, double (*func)(double))
|
||||||
to compute the log anyway. Clear the exception and continue. */
|
to compute the log anyway. Clear the exception and continue. */
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
x = _PyLong_Frexp((PyLongObject *)arg, &e);
|
x = _PyLong_Frexp((PyLongObject *)arg, &e);
|
||||||
if (x == -1.0 && PyErr_Occurred())
|
assert(e >= 0);
|
||||||
return NULL;
|
assert(!PyErr_Occurred());
|
||||||
/* Value is ~= x * 2**e, so the log ~= log(x) + log(2) * e. */
|
/* Value is ~= x * 2**e, so the log ~= log(x) + log(2) * e. */
|
||||||
result = func(x) + func(2.0) * e;
|
result = func(x) + func(2.0) * e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -406,19 +406,16 @@ float_richcompare(PyObject *v, PyObject *w, int op)
|
||||||
}
|
}
|
||||||
/* The signs are the same. */
|
/* The signs are the same. */
|
||||||
/* Convert w to a double if it fits. In particular, 0 fits. */
|
/* Convert w to a double if it fits. In particular, 0 fits. */
|
||||||
uint64_t nbits64 = _PyLong_NumBits(w);
|
int64_t nbits64 = _PyLong_NumBits(w);
|
||||||
if (nbits64 > (unsigned int)DBL_MAX_EXP) {
|
assert(nbits64 >= 0);
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
if (nbits64 > DBL_MAX_EXP) {
|
||||||
/* This Python integer is larger than any finite C double.
|
/* This Python integer is larger than any finite C double.
|
||||||
* Replace with little doubles
|
* Replace with little doubles
|
||||||
* that give the same outcome -- w is so large that
|
* that give the same outcome -- w is so large that
|
||||||
* its magnitude must exceed the magnitude of any
|
* its magnitude must exceed the magnitude of any
|
||||||
* finite float.
|
* finite float.
|
||||||
*/
|
*/
|
||||||
if (nbits64 == (uint64_t)-1 && PyErr_Occurred()) {
|
|
||||||
/* This Python integer is so large that uint64_t isn't
|
|
||||||
* big enough to hold the # of bits. */
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
i = (double)vsign;
|
i = (double)vsign;
|
||||||
assert(wsign != 0);
|
assert(wsign != 0);
|
||||||
j = wsign * 2.0;
|
j = wsign * 2.0;
|
||||||
|
|
|
@ -133,8 +133,16 @@ long_normalize(PyLongObject *v)
|
||||||
/* Allocate a new int object with size digits.
|
/* Allocate a new int object with size digits.
|
||||||
Return NULL and set exception if we run out of memory. */
|
Return NULL and set exception if we run out of memory. */
|
||||||
|
|
||||||
#define MAX_LONG_DIGITS \
|
#if SIZEOF_SIZE_T < 8
|
||||||
|
# define MAX_LONG_DIGITS \
|
||||||
((PY_SSIZE_T_MAX - offsetof(PyLongObject, long_value.ob_digit))/sizeof(digit))
|
((PY_SSIZE_T_MAX - offsetof(PyLongObject, long_value.ob_digit))/sizeof(digit))
|
||||||
|
#else
|
||||||
|
/* Guarantee that the number of bits fits in int64_t.
|
||||||
|
This is more than an exbibyte, that is more than many of modern
|
||||||
|
architectures support in principle.
|
||||||
|
-1 is added to avoid overflow in _PyLong_Frexp(). */
|
||||||
|
# define MAX_LONG_DIGITS ((INT64_MAX-1) / PyLong_SHIFT)
|
||||||
|
#endif
|
||||||
|
|
||||||
PyLongObject *
|
PyLongObject *
|
||||||
_PyLong_New(Py_ssize_t size)
|
_PyLong_New(Py_ssize_t size)
|
||||||
|
@ -804,11 +812,11 @@ bit_length_digit(digit x)
|
||||||
return _Py_bit_length((unsigned long)x);
|
return _Py_bit_length((unsigned long)x);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
int64_t
|
||||||
_PyLong_NumBits(PyObject *vv)
|
_PyLong_NumBits(PyObject *vv)
|
||||||
{
|
{
|
||||||
PyLongObject *v = (PyLongObject *)vv;
|
PyLongObject *v = (PyLongObject *)vv;
|
||||||
uint64_t result = 0;
|
int64_t result = 0;
|
||||||
Py_ssize_t ndigits;
|
Py_ssize_t ndigits;
|
||||||
int msd_bits;
|
int msd_bits;
|
||||||
|
|
||||||
|
@ -818,21 +826,12 @@ _PyLong_NumBits(PyObject *vv)
|
||||||
assert(ndigits == 0 || v->long_value.ob_digit[ndigits - 1] != 0);
|
assert(ndigits == 0 || v->long_value.ob_digit[ndigits - 1] != 0);
|
||||||
if (ndigits > 0) {
|
if (ndigits > 0) {
|
||||||
digit msd = v->long_value.ob_digit[ndigits - 1];
|
digit msd = v->long_value.ob_digit[ndigits - 1];
|
||||||
if ((uint64_t)(ndigits - 1) > UINT64_MAX / (uint64_t)PyLong_SHIFT)
|
assert(ndigits <= INT64_MAX / PyLong_SHIFT);
|
||||||
goto Overflow;
|
result = (int64_t)(ndigits - 1) * PyLong_SHIFT;
|
||||||
result = (uint64_t)(ndigits - 1) * (uint64_t)PyLong_SHIFT;
|
|
||||||
msd_bits = bit_length_digit(msd);
|
msd_bits = bit_length_digit(msd);
|
||||||
if (UINT64_MAX - msd_bits < result)
|
|
||||||
goto Overflow;
|
|
||||||
result += msd_bits;
|
result += msd_bits;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
Overflow:
|
|
||||||
/* Very unlikely. Such integer would require more than 2 exbibytes of RAM. */
|
|
||||||
PyErr_SetString(PyExc_OverflowError, "int has too many bits "
|
|
||||||
"to express in a 64-bit integer");
|
|
||||||
return (uint64_t)-1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -1247,15 +1246,12 @@ PyLong_AsNativeBytes(PyObject* vv, void* buffer, Py_ssize_t n, int flags)
|
||||||
|
|
||||||
/* Calculates the number of bits required for the *absolute* value
|
/* Calculates the number of bits required for the *absolute* value
|
||||||
* of v. This does not take sign into account, only magnitude. */
|
* of v. This does not take sign into account, only magnitude. */
|
||||||
uint64_t nb = _PyLong_NumBits((PyObject *)v);
|
int64_t nb = _PyLong_NumBits((PyObject *)v);
|
||||||
if (nb == (uint64_t)-1) {
|
assert(nb >= 0);
|
||||||
res = -1;
|
/* Normally this would be ((nb - 1) / 8) + 1 to avoid rounding up
|
||||||
} else {
|
* multiples of 8 to the next byte, but we add an implied bit for
|
||||||
/* Normally this would be((nb - 1) / 8) + 1 to avoid rounding up
|
* the sign and it cancels out. */
|
||||||
* multiples of 8 to the next byte, but we add an implied bit for
|
res = (Py_ssize_t)(nb / 8) + 1;
|
||||||
* the sign and it cancels out. */
|
|
||||||
res = (Py_ssize_t)(nb / 8) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Two edge cases exist that are best handled after extracting the
|
/* Two edge cases exist that are best handled after extracting the
|
||||||
* bits. These may result in us reporting overflow when the value
|
* bits. These may result in us reporting overflow when the value
|
||||||
|
@ -3415,7 +3411,8 @@ x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem)
|
||||||
double
|
double
|
||||||
_PyLong_Frexp(PyLongObject *a, int64_t *e)
|
_PyLong_Frexp(PyLongObject *a, int64_t *e)
|
||||||
{
|
{
|
||||||
Py_ssize_t a_size, shift_digits, shift_bits, x_size;
|
Py_ssize_t a_size, shift_digits, x_size;
|
||||||
|
int shift_bits;
|
||||||
int64_t a_bits;
|
int64_t a_bits;
|
||||||
/* See below for why x_digits is always large enough. */
|
/* See below for why x_digits is always large enough. */
|
||||||
digit rem;
|
digit rem;
|
||||||
|
@ -3432,14 +3429,7 @@ _PyLong_Frexp(PyLongObject *a, int64_t *e)
|
||||||
*e = 0;
|
*e = 0;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
int msd_bits = bit_length_digit(a->long_value.ob_digit[a_size-1]);
|
a_bits = _PyLong_NumBits((PyObject *)a);
|
||||||
/* The following is an overflow-free version of the check
|
|
||||||
"if ((a_size - 1) * PyLong_SHIFT + msd_bits > PY_SSIZE_T_MAX) ..." */
|
|
||||||
if (a_size >= (INT64_MAX - 1) / PyLong_SHIFT + 1 &&
|
|
||||||
(a_size > (INT64_MAX - 1) / PyLong_SHIFT + 1 ||
|
|
||||||
msd_bits > (INT64_MAX - 1) % PyLong_SHIFT + 1))
|
|
||||||
goto overflow;
|
|
||||||
a_bits = (int64_t)(a_size - 1) * PyLong_SHIFT + msd_bits;
|
|
||||||
|
|
||||||
/* Shift the first DBL_MANT_DIG + 2 bits of a into x_digits[0:x_size]
|
/* Shift the first DBL_MANT_DIG + 2 bits of a into x_digits[0:x_size]
|
||||||
(shifting left if a_bits <= DBL_MANT_DIG + 2).
|
(shifting left if a_bits <= DBL_MANT_DIG + 2).
|
||||||
|
@ -3468,18 +3458,18 @@ _PyLong_Frexp(PyLongObject *a, int64_t *e)
|
||||||
*/
|
*/
|
||||||
if (a_bits <= DBL_MANT_DIG + 2) {
|
if (a_bits <= DBL_MANT_DIG + 2) {
|
||||||
shift_digits = (DBL_MANT_DIG + 2 - (Py_ssize_t)a_bits) / PyLong_SHIFT;
|
shift_digits = (DBL_MANT_DIG + 2 - (Py_ssize_t)a_bits) / PyLong_SHIFT;
|
||||||
shift_bits = (DBL_MANT_DIG + 2 - (Py_ssize_t)a_bits) % PyLong_SHIFT;
|
shift_bits = (DBL_MANT_DIG + 2 - (int)a_bits) % PyLong_SHIFT;
|
||||||
x_size = shift_digits;
|
x_size = shift_digits;
|
||||||
rem = v_lshift(x_digits + x_size, a->long_value.ob_digit, a_size,
|
rem = v_lshift(x_digits + x_size, a->long_value.ob_digit, a_size,
|
||||||
(int)shift_bits);
|
shift_bits);
|
||||||
x_size += a_size;
|
x_size += a_size;
|
||||||
x_digits[x_size++] = rem;
|
x_digits[x_size++] = rem;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
shift_digits = (Py_ssize_t)((a_bits - DBL_MANT_DIG - 2) / PyLong_SHIFT);
|
shift_digits = (Py_ssize_t)((a_bits - DBL_MANT_DIG - 2) / PyLong_SHIFT);
|
||||||
shift_bits = (Py_ssize_t)((a_bits - DBL_MANT_DIG - 2) % PyLong_SHIFT);
|
shift_bits = (int)((a_bits - DBL_MANT_DIG - 2) % PyLong_SHIFT);
|
||||||
rem = v_rshift(x_digits, a->long_value.ob_digit + shift_digits,
|
rem = v_rshift(x_digits, a->long_value.ob_digit + shift_digits,
|
||||||
a_size - shift_digits, (int)shift_bits);
|
a_size - shift_digits, shift_bits);
|
||||||
x_size = a_size - shift_digits;
|
x_size = a_size - shift_digits;
|
||||||
/* For correct rounding below, we need the least significant
|
/* For correct rounding below, we need the least significant
|
||||||
bit of x to be 'sticky' for this shift: if any of the bits
|
bit of x to be 'sticky' for this shift: if any of the bits
|
||||||
|
@ -3505,21 +3495,13 @@ _PyLong_Frexp(PyLongObject *a, int64_t *e)
|
||||||
/* Rescale; make correction if result is 1.0. */
|
/* Rescale; make correction if result is 1.0. */
|
||||||
dx /= 4.0 * EXP2_DBL_MANT_DIG;
|
dx /= 4.0 * EXP2_DBL_MANT_DIG;
|
||||||
if (dx == 1.0) {
|
if (dx == 1.0) {
|
||||||
if (a_bits == INT64_MAX)
|
assert(a_bits < INT64_MAX);
|
||||||
goto overflow;
|
|
||||||
dx = 0.5;
|
dx = 0.5;
|
||||||
a_bits += 1;
|
a_bits += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*e = a_bits;
|
*e = a_bits;
|
||||||
return _PyLong_IsNegative(a) ? -dx : dx;
|
return _PyLong_IsNegative(a) ? -dx : dx;
|
||||||
|
|
||||||
overflow:
|
|
||||||
/* exponent > PY_SSIZE_T_MAX */
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
|
||||||
"huge integer: number of bits overflows a Py_ssize_t");
|
|
||||||
*e = 0;
|
|
||||||
return -1.0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a C double from an int object. Rounds to the nearest double,
|
/* Get a C double from an int object. Rounds to the nearest double,
|
||||||
|
@ -3547,7 +3529,9 @@ PyLong_AsDouble(PyObject *v)
|
||||||
return (double)medium_value((PyLongObject *)v);
|
return (double)medium_value((PyLongObject *)v);
|
||||||
}
|
}
|
||||||
x = _PyLong_Frexp((PyLongObject *)v, &exponent);
|
x = _PyLong_Frexp((PyLongObject *)v, &exponent);
|
||||||
if ((x == -1.0 && PyErr_Occurred()) || exponent > DBL_MAX_EXP) {
|
assert(exponent >= 0);
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
if (exponent > DBL_MAX_EXP) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"int too large to convert to float");
|
"int too large to convert to float");
|
||||||
return -1.0;
|
return -1.0;
|
||||||
|
@ -5217,39 +5201,6 @@ long_bool(PyLongObject *v)
|
||||||
return !_PyLong_IsZero(v);
|
return !_PyLong_IsZero(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */
|
|
||||||
static int
|
|
||||||
divmod_shift(PyObject *shiftby, Py_ssize_t *wordshift, digit *remshift)
|
|
||||||
{
|
|
||||||
assert(PyLong_Check(shiftby));
|
|
||||||
assert(!_PyLong_IsNegative((PyLongObject *)shiftby));
|
|
||||||
Py_ssize_t lshiftby = PyLong_AsSsize_t((PyObject *)shiftby);
|
|
||||||
if (lshiftby >= 0) {
|
|
||||||
*wordshift = lshiftby / PyLong_SHIFT;
|
|
||||||
*remshift = lshiftby % PyLong_SHIFT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* PyLong_Check(shiftby) is true and shiftby is not negative, so it must
|
|
||||||
be that PyLong_AsSsize_t raised an OverflowError. */
|
|
||||||
assert(PyErr_ExceptionMatches(PyExc_OverflowError));
|
|
||||||
PyErr_Clear();
|
|
||||||
PyLongObject *wordshift_obj = divrem1((PyLongObject *)shiftby, PyLong_SHIFT, remshift);
|
|
||||||
if (wordshift_obj == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*wordshift = PyLong_AsSsize_t((PyObject *)wordshift_obj);
|
|
||||||
Py_DECREF(wordshift_obj);
|
|
||||||
if (*wordshift >= 0 && *wordshift < PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(digit)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
PyErr_Clear();
|
|
||||||
/* Clip the value. With such large wordshift the right shift
|
|
||||||
returns 0 and the left shift raises an error in _PyLong_New(). */
|
|
||||||
*wordshift = PY_SSIZE_T_MAX / sizeof(digit);
|
|
||||||
*remshift = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Inner function for both long_rshift and _PyLong_Rshift, shifting an
|
/* Inner function for both long_rshift and _PyLong_Rshift, shifting an
|
||||||
integer right by PyLong_SHIFT*wordshift + remshift bits.
|
integer right by PyLong_SHIFT*wordshift + remshift bits.
|
||||||
wordshift should be nonnegative. */
|
wordshift should be nonnegative. */
|
||||||
|
@ -5343,8 +5294,7 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
long_rshift(PyObject *a, PyObject *b)
|
long_rshift(PyObject *a, PyObject *b)
|
||||||
{
|
{
|
||||||
Py_ssize_t wordshift;
|
int64_t shiftby;
|
||||||
digit remshift;
|
|
||||||
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
|
|
||||||
|
@ -5355,24 +5305,35 @@ long_rshift(PyObject *a, PyObject *b)
|
||||||
if (_PyLong_IsZero((PyLongObject *)a)) {
|
if (_PyLong_IsZero((PyLongObject *)a)) {
|
||||||
return PyLong_FromLong(0);
|
return PyLong_FromLong(0);
|
||||||
}
|
}
|
||||||
if (divmod_shift(b, &wordshift, &remshift) < 0)
|
if (PyLong_AsInt64(b, &shiftby) < 0) {
|
||||||
return NULL;
|
if (!PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||||
return long_rshift1((PyLongObject *)a, wordshift, remshift);
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
if (_PyLong_IsNegative((PyLongObject *)a)) {
|
||||||
|
return PyLong_FromLong(-1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return PyLong_FromLong(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _PyLong_Rshift(a, shiftby);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a >> shiftby. */
|
/* Return a >> shiftby. */
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyLong_Rshift(PyObject *a, uint64_t shiftby)
|
_PyLong_Rshift(PyObject *a, int64_t shiftby)
|
||||||
{
|
{
|
||||||
Py_ssize_t wordshift;
|
Py_ssize_t wordshift;
|
||||||
digit remshift;
|
digit remshift;
|
||||||
|
|
||||||
assert(PyLong_Check(a));
|
assert(PyLong_Check(a));
|
||||||
|
assert(shiftby >= 0);
|
||||||
if (_PyLong_IsZero((PyLongObject *)a)) {
|
if (_PyLong_IsZero((PyLongObject *)a)) {
|
||||||
return PyLong_FromLong(0);
|
return PyLong_FromLong(0);
|
||||||
}
|
}
|
||||||
#if PY_SSIZE_T_MAX <= UINT64_MAX / PyLong_SHIFT
|
#if PY_SSIZE_T_MAX <= INT64_MAX / PyLong_SHIFT
|
||||||
if (shiftby > (uint64_t)PY_SSIZE_T_MAX * PyLong_SHIFT) {
|
if (shiftby > (int64_t)PY_SSIZE_T_MAX * PyLong_SHIFT) {
|
||||||
if (_PyLong_IsNegative((PyLongObject *)a)) {
|
if (_PyLong_IsNegative((PyLongObject *)a)) {
|
||||||
return PyLong_FromLong(-1);
|
return PyLong_FromLong(-1);
|
||||||
}
|
}
|
||||||
|
@ -5430,8 +5391,7 @@ long_lshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
long_lshift(PyObject *a, PyObject *b)
|
long_lshift(PyObject *a, PyObject *b)
|
||||||
{
|
{
|
||||||
Py_ssize_t wordshift;
|
int64_t shiftby;
|
||||||
digit remshift;
|
|
||||||
|
|
||||||
CHECK_BINOP(a, b);
|
CHECK_BINOP(a, b);
|
||||||
|
|
||||||
|
@ -5442,24 +5402,30 @@ long_lshift(PyObject *a, PyObject *b)
|
||||||
if (_PyLong_IsZero((PyLongObject *)a)) {
|
if (_PyLong_IsZero((PyLongObject *)a)) {
|
||||||
return PyLong_FromLong(0);
|
return PyLong_FromLong(0);
|
||||||
}
|
}
|
||||||
if (divmod_shift(b, &wordshift, &remshift) < 0)
|
if (PyLong_AsInt64(b, &shiftby) < 0) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"too many digits in integer");
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
return long_lshift1((PyLongObject *)a, wordshift, remshift);
|
}
|
||||||
|
return _PyLong_Lshift(a, shiftby);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a << shiftby. */
|
/* Return a << shiftby. */
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyLong_Lshift(PyObject *a, uint64_t shiftby)
|
_PyLong_Lshift(PyObject *a, int64_t shiftby)
|
||||||
{
|
{
|
||||||
Py_ssize_t wordshift;
|
Py_ssize_t wordshift;
|
||||||
digit remshift;
|
digit remshift;
|
||||||
|
|
||||||
assert(PyLong_Check(a));
|
assert(PyLong_Check(a));
|
||||||
|
assert(shiftby >= 0);
|
||||||
if (_PyLong_IsZero((PyLongObject *)a)) {
|
if (_PyLong_IsZero((PyLongObject *)a)) {
|
||||||
return PyLong_FromLong(0);
|
return PyLong_FromLong(0);
|
||||||
}
|
}
|
||||||
#if PY_SSIZE_T_MAX <= UINT64_MAX / PyLong_SHIFT
|
#if PY_SSIZE_T_MAX <= INT64_MAX / PyLong_SHIFT
|
||||||
if (shiftby > (uint64_t)PY_SSIZE_T_MAX * PyLong_SHIFT) {
|
if (shiftby > (int64_t)PY_SSIZE_T_MAX * PyLong_SHIFT) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"too many digits in integer");
|
"too many digits in integer");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -6213,11 +6179,10 @@ static PyObject *
|
||||||
int_bit_length_impl(PyObject *self)
|
int_bit_length_impl(PyObject *self)
|
||||||
/*[clinic end generated code: output=fc1977c9353d6a59 input=e4eb7a587e849a32]*/
|
/*[clinic end generated code: output=fc1977c9353d6a59 input=e4eb7a587e849a32]*/
|
||||||
{
|
{
|
||||||
uint64_t nbits = _PyLong_NumBits(self);
|
int64_t nbits = _PyLong_NumBits(self);
|
||||||
if (nbits == (uint64_t)-1) {
|
assert(nbits >= 0);
|
||||||
return NULL;
|
assert(!PyErr_Occurred());
|
||||||
}
|
return PyLong_FromInt64(nbits);
|
||||||
return PyLong_FromUnsignedLongLong(nbits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -6251,40 +6216,13 @@ int_bit_count_impl(PyObject *self)
|
||||||
|
|
||||||
PyLongObject *z = (PyLongObject *)self;
|
PyLongObject *z = (PyLongObject *)self;
|
||||||
Py_ssize_t ndigits = _PyLong_DigitCount(z);
|
Py_ssize_t ndigits = _PyLong_DigitCount(z);
|
||||||
Py_ssize_t bit_count = 0;
|
int64_t bit_count = 0;
|
||||||
|
|
||||||
/* Each digit has up to PyLong_SHIFT ones, so the accumulated bit count
|
for (Py_ssize_t i = 0; i < ndigits; i++) {
|
||||||
from the first PY_SSIZE_T_MAX/PyLong_SHIFT digits can't overflow a
|
|
||||||
Py_ssize_t. */
|
|
||||||
Py_ssize_t ndigits_fast = Py_MIN(ndigits, PY_SSIZE_T_MAX/PyLong_SHIFT);
|
|
||||||
for (Py_ssize_t i = 0; i < ndigits_fast; i++) {
|
|
||||||
bit_count += popcount_digit(z->long_value.ob_digit[i]);
|
bit_count += popcount_digit(z->long_value.ob_digit[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *result = PyLong_FromSsize_t(bit_count);
|
return PyLong_FromInt64(bit_count);
|
||||||
if (result == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use Python integers if bit_count would overflow. */
|
|
||||||
for (Py_ssize_t i = ndigits_fast; i < ndigits; i++) {
|
|
||||||
PyObject *x = PyLong_FromLong(popcount_digit(z->long_value.ob_digit[i]));
|
|
||||||
if (x == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
PyObject *y = long_add((PyLongObject *)result, (PyLongObject *)x);
|
|
||||||
Py_DECREF(x);
|
|
||||||
if (y == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
Py_SETREF(result, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
error:
|
|
||||||
Py_DECREF(result);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
|
|
@ -169,11 +169,10 @@ safe_multiply(PyObject *v, PyObject *w)
|
||||||
if (PyLong_Check(v) && PyLong_Check(w) &&
|
if (PyLong_Check(v) && PyLong_Check(w) &&
|
||||||
!_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)
|
!_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)
|
||||||
) {
|
) {
|
||||||
uint64_t vbits = _PyLong_NumBits(v);
|
int64_t vbits = _PyLong_NumBits(v);
|
||||||
uint64_t wbits = _PyLong_NumBits(w);
|
int64_t wbits = _PyLong_NumBits(w);
|
||||||
if (vbits == (uint64_t)-1 || wbits == (uint64_t)-1) {
|
assert(vbits >= 0);
|
||||||
return NULL;
|
assert(wbits >= 0);
|
||||||
}
|
|
||||||
if (vbits + wbits > MAX_INT_SIZE) {
|
if (vbits + wbits > MAX_INT_SIZE) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -215,12 +214,13 @@ safe_power(PyObject *v, PyObject *w)
|
||||||
if (PyLong_Check(v) && PyLong_Check(w) &&
|
if (PyLong_Check(v) && PyLong_Check(w) &&
|
||||||
!_PyLong_IsZero((PyLongObject *)v) && _PyLong_IsPositive((PyLongObject *)w)
|
!_PyLong_IsZero((PyLongObject *)v) && _PyLong_IsPositive((PyLongObject *)w)
|
||||||
) {
|
) {
|
||||||
uint64_t vbits = _PyLong_NumBits(v);
|
int64_t vbits = _PyLong_NumBits(v);
|
||||||
size_t wbits = PyLong_AsSize_t(w);
|
size_t wbits = PyLong_AsSize_t(w);
|
||||||
if (vbits == (uint64_t)-1 || wbits == (size_t)-1) {
|
assert(vbits >= 0);
|
||||||
|
if (wbits == (size_t)-1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (vbits > MAX_INT_SIZE / wbits) {
|
if ((uint64_t)vbits > MAX_INT_SIZE / wbits) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,12 +234,13 @@ safe_lshift(PyObject *v, PyObject *w)
|
||||||
if (PyLong_Check(v) && PyLong_Check(w) &&
|
if (PyLong_Check(v) && PyLong_Check(w) &&
|
||||||
!_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)
|
!_PyLong_IsZero((PyLongObject *)v) && !_PyLong_IsZero((PyLongObject *)w)
|
||||||
) {
|
) {
|
||||||
uint64_t vbits = _PyLong_NumBits(v);
|
int64_t vbits = _PyLong_NumBits(v);
|
||||||
size_t wbits = PyLong_AsSize_t(w);
|
size_t wbits = PyLong_AsSize_t(w);
|
||||||
if (vbits == (uint64_t)-1 || wbits == (size_t)-1) {
|
assert(vbits >= 0);
|
||||||
|
if (wbits == (size_t)-1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (wbits > MAX_INT_SIZE || vbits > MAX_INT_SIZE - wbits) {
|
if (wbits > MAX_INT_SIZE || (uint64_t)vbits > MAX_INT_SIZE - wbits) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue