From 056495d5cde239ab19920a11c07400bdcfe1ec85 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 23 Dec 2021 14:18:47 +0000 Subject: [PATCH 1/5] bpo-46055: Streamline inner loop for right shifts --- Objects/longobject.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 77434e67642f5e..bd2c5fc7e7f303 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4491,7 +4491,6 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) { PyLongObject *z = NULL; Py_ssize_t newsize, hishift, i, j; - digit lomask, himask; if (Py_SIZE(a) < 0) { /* Right shifting negative numbers is harder */ @@ -4511,16 +4510,17 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) if (newsize <= 0) return PyLong_FromLong(0); hishift = PyLong_SHIFT - remshift; - lomask = ((digit)1 << hishift) - 1; - himask = PyLong_MASK ^ lomask; z = _PyLong_New(newsize); if (z == NULL) return NULL; - for (i = 0, j = wordshift; i < newsize; i++, j++) { - z->ob_digit[i] = (a->ob_digit[j] >> remshift) & lomask; - if (i+1 < newsize) - z->ob_digit[i] |= (a->ob_digit[j+1] << hishift) & himask; + j = wordshift; + digit next = a->ob_digit[j++]; + for (i = 0; j < Py_SIZE(a); i++, j++) { + digit high = next >> remshift; + next = a->ob_digit[j]; + z->ob_digit[i] = (high | next << hishift) & PyLong_MASK; } + z->ob_digit[i] = next >> remshift; z = maybe_small_long(long_normalize(z)); } return (PyObject *)z; From d0f1958bee9acc5e37fb767718ca1d3a9b880053 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 23 Dec 2021 14:46:29 +0000 Subject: [PATCH 2/5] Move declarations to top of function; rename high to lobits --- Objects/longobject.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index bd2c5fc7e7f303..89d401bc8af55c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4491,6 +4491,7 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) { PyLongObject *z = NULL; Py_ssize_t newsize, hishift, i, j; + digit lobits, next; if (Py_SIZE(a) < 0) { /* Right shifting negative numbers is harder */ @@ -4514,13 +4515,13 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) if (z == NULL) return NULL; j = wordshift; - digit next = a->ob_digit[j++]; + lobits = a->ob_digit[j++] >> remshift; for (i = 0; j < Py_SIZE(a); i++, j++) { - digit high = next >> remshift; next = a->ob_digit[j]; - z->ob_digit[i] = (high | next << hishift) & PyLong_MASK; + z->ob_digit[i] = (lobits | next << hishift) & PyLong_MASK; + lobits = next >> remshift; } - z->ob_digit[i] = next >> remshift; + z->ob_digit[i] = lobits; z = maybe_small_long(long_normalize(z)); } return (PyObject *)z; From f92f3f80741df576012fa01c19d341e0e00a65c9 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 23 Dec 2021 15:08:07 +0000 Subject: [PATCH 3/5] Now even faster! --- Objects/longobject.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 89d401bc8af55c..a91a535f04337c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4491,7 +4491,6 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) { PyLongObject *z = NULL; Py_ssize_t newsize, hishift, i, j; - digit lobits, next; if (Py_SIZE(a) < 0) { /* Right shifting negative numbers is harder */ @@ -4515,13 +4514,13 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) if (z == NULL) return NULL; j = wordshift; - lobits = a->ob_digit[j++] >> remshift; + twodigits acc = a->ob_digit[j++] >> remshift; for (i = 0; j < Py_SIZE(a); i++, j++) { - next = a->ob_digit[j]; - z->ob_digit[i] = (lobits | next << hishift) & PyLong_MASK; - lobits = next >> remshift; + acc |= ((twodigits)(a->ob_digit[j]) << hishift); + z->ob_digit[i] = acc & PyLong_MASK; + acc >>= PyLong_SHIFT; } - z->ob_digit[i] = lobits; + z->ob_digit[i] = acc; z = maybe_small_long(long_normalize(z)); } return (PyObject *)z; From 76e9a487c7be6525d927de99f2045259ee1e7509 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 23 Dec 2021 15:26:16 +0000 Subject: [PATCH 4/5] Remove unnecessary parentheses --- Objects/longobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index a91a535f04337c..e315ac77857f68 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4516,7 +4516,7 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) j = wordshift; twodigits acc = a->ob_digit[j++] >> remshift; for (i = 0; j < Py_SIZE(a); i++, j++) { - acc |= ((twodigits)(a->ob_digit[j]) << hishift); + acc |= (twodigits)(a->ob_digit[j]) << hishift; z->ob_digit[i] = acc & PyLong_MASK; acc >>= PyLong_SHIFT; } From 76dc4761d0d4cb12102ffa93b019c41f25b76029 Mon Sep 17 00:00:00 2001 From: Mark Dickinson Date: Thu, 23 Dec 2021 15:37:51 +0000 Subject: [PATCH 5/5] Cosmetic changes to align the inner loop with that of long_lshift1 --- Objects/longobject.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index e315ac77857f68..ddb3def402cdd5 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4491,6 +4491,7 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) { PyLongObject *z = NULL; Py_ssize_t newsize, hishift, i, j; + twodigits accum; if (Py_SIZE(a) < 0) { /* Right shifting negative numbers is harder */ @@ -4514,13 +4515,13 @@ long_rshift1(PyLongObject *a, Py_ssize_t wordshift, digit remshift) if (z == NULL) return NULL; j = wordshift; - twodigits acc = a->ob_digit[j++] >> remshift; + accum = a->ob_digit[j++] >> remshift; for (i = 0; j < Py_SIZE(a); i++, j++) { - acc |= (twodigits)(a->ob_digit[j]) << hishift; - z->ob_digit[i] = acc & PyLong_MASK; - acc >>= PyLong_SHIFT; + accum |= (twodigits)a->ob_digit[j] << hishift; + z->ob_digit[i] = (digit)(accum & PyLong_MASK); + accum >>= PyLong_SHIFT; } - z->ob_digit[i] = acc; + z->ob_digit[i] = (digit)accum; z = maybe_small_long(long_normalize(z)); } return (PyObject *)z;