Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a5119e7

Browse filesBrowse files
bpo-36957: Add _PyLong_Rshift() and _PyLong_Lshift(). (GH-13416)
1 parent 1d5bdef commit a5119e7
Copy full SHA for a5119e7

File tree

Expand file treeCollapse file tree

4 files changed

+87
-53
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+87
-53
lines changed

‎Include/longobject.h

Copy file name to clipboardExpand all lines: Include/longobject.h
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ PyAPI_FUNC(PyObject *) _PyLong_GCD(PyObject *, PyObject *);
230230
#ifndef Py_LIMITED_API
231231
PyAPI_DATA(PyObject *) _PyLong_Zero;
232232
PyAPI_DATA(PyObject *) _PyLong_One;
233+
234+
PyAPI_FUNC(PyObject *) _PyLong_Rshift(PyObject *, size_t);
235+
PyAPI_FUNC(PyObject *) _PyLong_Lshift(PyObject *, size_t);
233236
#endif
234237

235238
#ifdef __cplusplus

‎Modules/mathmodule.c

Copy file name to clipboardExpand all lines: Modules/mathmodule.c
+7-23Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,18 +1671,13 @@ math_isqrt(PyObject *module, PyObject *n)
16711671
}
16721672
d = 0;
16731673
while (--s >= 0) {
1674-
PyObject *q, *shift;
1674+
PyObject *q;
16751675
size_t e = d;
16761676

16771677
d = c >> s;
16781678

16791679
/* q = (n >> 2*c - e - d + 1) // a */
1680-
shift = PyLong_FromSize_t(2U*c - d - e + 1U);
1681-
if (shift == NULL) {
1682-
goto error;
1683-
}
1684-
q = PyNumber_Rshift(n, shift);
1685-
Py_DECREF(shift);
1680+
q = _PyLong_Rshift(n, 2U*c - d - e + 1U);
16861681
if (q == NULL) {
16871682
goto error;
16881683
}
@@ -1692,13 +1687,7 @@ math_isqrt(PyObject *module, PyObject *n)
16921687
}
16931688

16941689
/* a = (a << d - 1 - e) + q */
1695-
shift = PyLong_FromSize_t(d - 1U - e);
1696-
if (shift == NULL) {
1697-
Py_DECREF(q);
1698-
goto error;
1699-
}
1700-
Py_SETREF(a, PyNumber_Lshift(a, shift));
1701-
Py_DECREF(shift);
1690+
Py_SETREF(a, _PyLong_Lshift(a, d - 1U - e));
17021691
if (a == NULL) {
17031692
Py_DECREF(q);
17041693
goto error;
@@ -1939,9 +1928,9 @@ static PyObject *
19391928
math_factorial(PyObject *module, PyObject *arg)
19401929
/*[clinic end generated code: output=6686f26fae00e9ca input=6d1c8105c0d91fb4]*/
19411930
{
1942-
long x;
1931+
long x, two_valuation;
19431932
int overflow;
1944-
PyObject *result, *odd_part, *two_valuation, *pyint_form;
1933+
PyObject *result, *odd_part, *pyint_form;
19451934

19461935
if (PyFloat_Check(arg)) {
19471936
PyObject *lx;
@@ -1990,13 +1979,8 @@ math_factorial(PyObject *module, PyObject *arg)
19901979
odd_part = factorial_odd_part(x);
19911980
if (odd_part == NULL)
19921981
return NULL;
1993-
two_valuation = PyLong_FromLong(x - count_set_bits(x));
1994-
if (two_valuation == NULL) {
1995-
Py_DECREF(odd_part);
1996-
return NULL;
1997-
}
1998-
result = PyNumber_Lshift(odd_part, two_valuation);
1999-
Py_DECREF(two_valuation);
1982+
two_valuation = x - count_set_bits(x);
1983+
result = _PyLong_Lshift(odd_part, two_valuation);
20001984
Py_DECREF(odd_part);
20011985
return result;
20021986
}

‎Objects/floatobject.c

Copy file name to clipboardExpand all lines: Objects/floatobject.c
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,13 +463,13 @@ float_richcompare(PyObject *v, PyObject *w, int op)
463463
*/
464464
PyObject *temp;
465465

466-
temp = PyNumber_Lshift(ww, _PyLong_One);
466+
temp = _PyLong_Lshift(ww, 1);
467467
if (temp == NULL)
468468
goto Error;
469469
Py_DECREF(ww);
470470
ww = temp;
471471

472-
temp = PyNumber_Lshift(vv, _PyLong_One);
472+
temp = _PyLong_Lshift(vv, 1);
473473
if (temp == NULL)
474474
goto Error;
475475
Py_DECREF(vv);

‎Objects/longobject.c

Copy file name to clipboardExpand all lines: Objects/longobject.c
+75-28Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4416,9 +4416,9 @@ long_bool(PyLongObject *v)
44164416

44174417
/* wordshift, remshift = divmod(shiftby, PyLong_SHIFT) */
44184418
static int
4419-
divmod_shift(PyLongObject *shiftby, Py_ssize_t *wordshift, digit *remshift)
4419+
divmod_shift(PyObject *shiftby, Py_ssize_t *wordshift, digit *remshift)
44204420
{
4421-
assert(PyLong_Check((PyObject *)shiftby));
4421+
assert(PyLong_Check(shiftby));
44224422
assert(Py_SIZE(shiftby) >= 0);
44234423
Py_ssize_t lshiftby = PyLong_AsSsize_t((PyObject *)shiftby);
44244424
if (lshiftby >= 0) {
@@ -4430,7 +4430,7 @@ divmod_shift(PyLongObject *shiftby, Py_ssize_t *wordshift, digit *remshift)
44304430
be that PyLong_AsSsize_t raised an OverflowError. */
44314431
assert(PyErr_ExceptionMatches(PyExc_OverflowError));
44324432
PyErr_Clear();
4433-
PyLongObject *wordshift_obj = divrem1(shiftby, PyLong_SHIFT, remshift);
4433+
PyLongObject *wordshift_obj = divrem1((PyLongObject *)shiftby, PyLong_SHIFT, remshift);
44344434
if (wordshift_obj == NULL) {
44354435
return -1;
44364436
}
@@ -4448,47 +4448,37 @@ divmod_shift(PyLongObject *shiftby, Py_ssize_t *wordshift, digit *remshift)
44484448
}
44494449

44504450
static PyObject *
4451-
long_rshift(PyLongObject *a, PyLongObject *b)
4451+
long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift)
44524452
{
44534453
PyLongObject *z = NULL;
4454-
Py_ssize_t newsize, wordshift, hishift, i, j;
4455-
digit loshift, lomask, himask;
4456-
4457-
CHECK_BINOP(a, b);
4458-
4459-
if (Py_SIZE(b) < 0) {
4460-
PyErr_SetString(PyExc_ValueError,
4461-
"negative shift count");
4462-
return NULL;
4463-
}
4454+
Py_ssize_t newsize, hishift, i, j;
4455+
digit lomask, himask;
44644456

44654457
if (Py_SIZE(a) < 0) {
44664458
/* Right shifting negative numbers is harder */
44674459
PyLongObject *a1, *a2;
44684460
a1 = (PyLongObject *) long_invert(a);
44694461
if (a1 == NULL)
44704462
return NULL;
4471-
a2 = (PyLongObject *) long_rshift(a1, b);
4463+
a2 = (PyLongObject *) long_rshift1(a1, wordshift, remshift);
44724464
Py_DECREF(a1);
44734465
if (a2 == NULL)
44744466
return NULL;
44754467
z = (PyLongObject *) long_invert(a2);
44764468
Py_DECREF(a2);
44774469
}
44784470
else {
4479-
if (divmod_shift(b, &wordshift, &loshift) < 0)
4480-
return NULL;
44814471
newsize = Py_SIZE(a) - wordshift;
44824472
if (newsize <= 0)
44834473
return PyLong_FromLong(0);
4484-
hishift = PyLong_SHIFT - loshift;
4474+
hishift = PyLong_SHIFT - remshift;
44854475
lomask = ((digit)1 << hishift) - 1;
44864476
himask = PyLong_MASK ^ lomask;
44874477
z = _PyLong_New(newsize);
44884478
if (z == NULL)
44894479
return NULL;
44904480
for (i = 0, j = wordshift; i < newsize; i++, j++) {
4491-
z->ob_digit[i] = (a->ob_digit[j] >> loshift) & lomask;
4481+
z->ob_digit[i] = (a->ob_digit[j] >> remshift) & lomask;
44924482
if (i+1 < newsize)
44934483
z->ob_digit[i] |= (a->ob_digit[j+1] << hishift) & himask;
44944484
}
@@ -4498,15 +4488,10 @@ long_rshift(PyLongObject *a, PyLongObject *b)
44984488
}
44994489

45004490
static PyObject *
4501-
long_lshift(PyObject *v, PyObject *w)
4491+
long_rshift(PyObject *a, PyObject *b)
45024492
{
4503-
/* This version due to Tim Peters */
4504-
PyLongObject *a = (PyLongObject*)v;
4505-
PyLongObject *b = (PyLongObject*)w;
4506-
PyLongObject *z = NULL;
4507-
Py_ssize_t oldsize, newsize, wordshift, i, j;
4493+
Py_ssize_t wordshift;
45084494
digit remshift;
4509-
twodigits accum;
45104495

45114496
CHECK_BINOP(a, b);
45124497

@@ -4517,9 +4502,35 @@ long_lshift(PyObject *v, PyObject *w)
45174502
if (Py_SIZE(a) == 0) {
45184503
return PyLong_FromLong(0);
45194504
}
4520-
45214505
if (divmod_shift(b, &wordshift, &remshift) < 0)
45224506
return NULL;
4507+
return long_rshift1((PyLongObject *)a, wordshift, remshift);
4508+
}
4509+
4510+
/* Return a >> shiftby. */
4511+
PyObject *
4512+
_PyLong_Rshift(PyObject *a, size_t shiftby)
4513+
{
4514+
Py_ssize_t wordshift;
4515+
digit remshift;
4516+
4517+
assert(PyLong_Check(a));
4518+
if (Py_SIZE(a) == 0) {
4519+
return PyLong_FromLong(0);
4520+
}
4521+
wordshift = shiftby / PyLong_SHIFT;
4522+
remshift = shiftby % PyLong_SHIFT;
4523+
return long_rshift1((PyLongObject *)a, wordshift, remshift);
4524+
}
4525+
4526+
static PyObject *
4527+
long_lshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift)
4528+
{
4529+
/* This version due to Tim Peters */
4530+
PyLongObject *z = NULL;
4531+
Py_ssize_t oldsize, newsize, i, j;
4532+
twodigits accum;
4533+
45234534
oldsize = Py_ABS(Py_SIZE(a));
45244535
newsize = oldsize + wordshift;
45254536
if (remshift)
@@ -4547,6 +4558,42 @@ long_lshift(PyObject *v, PyObject *w)
45474558
return (PyObject *) maybe_small_long(z);
45484559
}
45494560

4561+
static PyObject *
4562+
long_lshift(PyObject *a, PyObject *b)
4563+
{
4564+
Py_ssize_t wordshift;
4565+
digit remshift;
4566+
4567+
CHECK_BINOP(a, b);
4568+
4569+
if (Py_SIZE(b) < 0) {
4570+
PyErr_SetString(PyExc_ValueError, "negative shift count");
4571+
return NULL;
4572+
}
4573+
if (Py_SIZE(a) == 0) {
4574+
return PyLong_FromLong(0);
4575+
}
4576+
if (divmod_shift(b, &wordshift, &remshift) < 0)
4577+
return NULL;
4578+
return long_lshift1((PyLongObject *)a, wordshift, remshift);
4579+
}
4580+
4581+
/* Return a << shiftby. */
4582+
PyObject *
4583+
_PyLong_Lshift(PyObject *a, size_t shiftby)
4584+
{
4585+
Py_ssize_t wordshift;
4586+
digit remshift;
4587+
4588+
assert(PyLong_Check(a));
4589+
if (Py_SIZE(a) == 0) {
4590+
return PyLong_FromLong(0);
4591+
}
4592+
wordshift = shiftby / PyLong_SHIFT;
4593+
remshift = shiftby % PyLong_SHIFT;
4594+
return long_lshift1((PyLongObject *)a, wordshift, remshift);
4595+
}
4596+
45504597
/* Compute two's complement of digit vector a[0:m], writing result to
45514598
z[0:m]. The digit vector a need not be normalized, but should not
45524599
be entirely zero. a and z may point to the same digit vector. */
@@ -5552,7 +5599,7 @@ static PyNumberMethods long_as_number = {
55525599
(inquiry)long_bool, /*tp_bool*/
55535600
(unaryfunc)long_invert, /*nb_invert*/
55545601
long_lshift, /*nb_lshift*/
5555-
(binaryfunc)long_rshift, /*nb_rshift*/
5602+
long_rshift, /*nb_rshift*/
55565603
long_and, /*nb_and*/
55575604
long_xor, /*nb_xor*/
55585605
long_or, /*nb_or*/

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.