|
|
|
@ -4277,15 +4277,54 @@ long_bool(PyLongObject *v) |
|
|
|
return Py_SIZE(v) != 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */ |
|
|
|
static int |
|
|
|
divmod_shift(PyLongObject *shiftby, Py_ssize_t *wordshift, digit *remshift) |
|
|
|
{ |
|
|
|
assert(PyLong_Check((PyObject *)shiftby)); |
|
|
|
assert(Py_SIZE(shiftby) >= 0); |
|
|
|
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 Py_SIZE(shiftby) >= 0, so it must |
|
|
|
be that PyLong_AsSsize_t raised an OverflowError. */ |
|
|
|
assert(PyErr_ExceptionMatches(PyExc_OverflowError)); |
|
|
|
PyErr_Clear(); |
|
|
|
PyLongObject *wordshift_obj = divrem1(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; |
|
|
|
} |
|
|
|
|
|
|
|
static PyObject * |
|
|
|
long_rshift(PyLongObject *a, PyLongObject *b) |
|
|
|
{ |
|
|
|
PyLongObject *z = NULL; |
|
|
|
Py_ssize_t shiftby, newsize, wordshift, loshift, hishift, i, j; |
|
|
|
digit lomask, himask; |
|
|
|
Py_ssize_t newsize, wordshift, hishift, i, j; |
|
|
|
digit loshift, lomask, himask; |
|
|
|
|
|
|
|
CHECK_BINOP(a, b); |
|
|
|
|
|
|
|
if (Py_SIZE(b) < 0) { |
|
|
|
PyErr_SetString(PyExc_ValueError, |
|
|
|
"negative shift count"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (Py_SIZE(a) < 0) { |
|
|
|
/* Right shifting negative numbers is harder */ |
|
|
|
PyLongObject *a1, *a2; |
|
|
|
@ -4300,19 +4339,11 @@ long_rshift(PyLongObject *a, PyLongObject *b) |
|
|
|
Py_DECREF(a2); |
|
|
|
} |
|
|
|
else { |
|
|
|
shiftby = PyLong_AsSsize_t((PyObject *)b); |
|
|
|
if (shiftby == -1L && PyErr_Occurred()) |
|
|
|
return NULL; |
|
|
|
if (shiftby < 0) { |
|
|
|
PyErr_SetString(PyExc_ValueError, |
|
|
|
"negative shift count"); |
|
|
|
if (divmod_shift(b, &wordshift, &loshift) < 0) |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
wordshift = shiftby / PyLong_SHIFT; |
|
|
|
newsize = Py_ABS(Py_SIZE(a)) - wordshift; |
|
|
|
newsize = Py_SIZE(a) - wordshift; |
|
|
|
if (newsize <= 0) |
|
|
|
return PyLong_FromLong(0); |
|
|
|
loshift = shiftby % PyLong_SHIFT; |
|
|
|
hishift = PyLong_SHIFT - loshift; |
|
|
|
lomask = ((digit)1 << hishift) - 1; |
|
|
|
himask = PyLong_MASK ^ lomask; |
|
|
|
@ -4336,27 +4367,22 @@ long_lshift(PyObject *v, PyObject *w) |
|
|
|
PyLongObject *a = (PyLongObject*)v; |
|
|
|
PyLongObject *b = (PyLongObject*)w; |
|
|
|
PyLongObject *z = NULL; |
|
|
|
Py_ssize_t shiftby, oldsize, newsize, wordshift, remshift, i, j; |
|
|
|
Py_ssize_t oldsize, newsize, wordshift, i, j; |
|
|
|
digit remshift; |
|
|
|
twodigits accum; |
|
|
|
|
|
|
|
CHECK_BINOP(a, b); |
|
|
|
|
|
|
|
shiftby = PyLong_AsSsize_t((PyObject *)b); |
|
|
|
if (shiftby == -1L && PyErr_Occurred()) |
|
|
|
return NULL; |
|
|
|
if (shiftby < 0) { |
|
|
|
if (Py_SIZE(b) < 0) { |
|
|
|
PyErr_SetString(PyExc_ValueError, "negative shift count"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (Py_SIZE(a) == 0) { |
|
|
|
return PyLong_FromLong(0); |
|
|
|
} |
|
|
|
|
|
|
|
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */ |
|
|
|
wordshift = shiftby / PyLong_SHIFT; |
|
|
|
remshift = shiftby - wordshift * PyLong_SHIFT; |
|
|
|
|
|
|
|
if (divmod_shift(b, &wordshift, &remshift) < 0) |
|
|
|
return NULL; |
|
|
|
oldsize = Py_ABS(Py_SIZE(a)); |
|
|
|
newsize = oldsize + wordshift; |
|
|
|
if (remshift) |
|
|
|
|