From ed9be47970072d3c7f5815d27ef0d9aa64a1aff4 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 13:07:15 +0530 Subject: [PATCH 01/21] Add Missing fast path in PyLong_From*() functions for compact integers --- Objects/longobject.c | 120 ++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 59 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index d449a01cedf886..2e1faf3e0171f1 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -115,6 +115,65 @@ maybe_small_long(PyLongObject *v) if (PyErr_CheckSignals()) PyTryBlock \ } while(0) +#define PYLONG_FROM_SIGNED(INT_TYPE, ival) \ + do { \ + if (IS_SMALL_INT(ival)) { \ + return get_small_int((sdigit)(ival)); \ + } \ + if (-(INT_TYPE)PyLong_MASK <= (ival) && (ival) <= (INT_TYPE)PyLong_MASK) { \ + return _PyLong_FromMedium((sdigit)(ival)); \ + } \ + /* Count digits (at least two - smaller cases were handled above). */ \ + INT_TYPE abs_ival = (ival) < 0 ? 0U-(INT_TYPE)(ival) : (INT_TYPE)(ival); \ + /* Do shift in two steps to avoid possible undefined behavior. */ \ + INT_TYPE t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \ + Py_ssize_t ndigits = 2; \ + while (t) { \ + ++ndigits; \ + t >>= PyLong_SHIFT; \ + } \ + PyLongObject *v = _PyLong_New(ndigits); \ + if (v == NULL) { \ + return NULL; \ + } \ + digit *p = v->long_value.ob_digit; \ + _PyLong_SetSignAndDigitCount(v, (ival) < 0 ? -1 : 1, ndigits); \ + t = abs_ival; \ + while (t) { \ + *p++ = (digit)(t & PyLong_MASK); \ + t >>= PyLong_SHIFT; \ + } \ + return (PyObject *)v; \ + } while(0) + +#define PYLONG_FROM_UINT(INT_TYPE, ival) \ + do { \ + if (IS_SMALL_UINT(ival)) { \ + return get_small_int((sdigit)(ival)); \ + } \ + if ((ival) <= PyLong_MASK) { \ + return _PyLong_FromMedium((sdigit)(ival)); \ + } \ + /* Count the number of Python digits. */ \ + Py_ssize_t ndigits = 0; \ + INT_TYPE t = (ival); \ + while (t) { \ + ++ndigits; \ + t >>= PyLong_SHIFT; \ + } \ + PyLongObject *v = _PyLong_New(ndigits); \ + if (v == NULL) { \ + return NULL; \ + } \ + digit *p = v->long_value.ob_digit; \ + t = (ival); \ + while (t) { \ + *p++ = (digit)(t & PyLong_MASK); \ + t >>= PyLong_SHIFT; \ + } \ + return (PyObject *)v; \ + } while(0) + /* Normalize (remove leading zeros from) an int object. Doesn't attempt to free the storage--in most cases, due to the nature of the algorithms used, this could save at most be one word anyway. */ @@ -318,66 +377,9 @@ _PyLong_Negate(PyLongObject **x_p) PyObject * PyLong_FromLong(long ival) { - PyLongObject *v; - unsigned long abs_ival, t; - int ndigits; - - /* Handle small and medium cases. */ - if (IS_SMALL_INT(ival)) { - return get_small_int((sdigit)ival); - } - if (-(long)PyLong_MASK <= ival && ival <= (long)PyLong_MASK) { - return _PyLong_FromMedium((sdigit)ival); - } - - /* Count digits (at least two - smaller cases were handled above). */ - abs_ival = ival < 0 ? 0U-(unsigned long)ival : (unsigned long)ival; - /* Do shift in two steps to avoid possible undefined behavior. */ - t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; - ndigits = 2; - while (t) { - ++ndigits; - t >>= PyLong_SHIFT; - } - - /* Construct output value. */ - v = _PyLong_New(ndigits); - if (v != NULL) { - digit *p = v->long_value.ob_digit; - _PyLong_SetSignAndDigitCount(v, ival < 0 ? -1 : 1, ndigits); - t = abs_ival; - while (t) { - *p++ = (digit)(t & PyLong_MASK); - t >>= PyLong_SHIFT; - } - } - return (PyObject *)v; + PYLONG_FROM_SIGNED(long, ival); } -#define PYLONG_FROM_UINT(INT_TYPE, ival) \ - do { \ - if (IS_SMALL_UINT(ival)) { \ - return get_small_int((sdigit)(ival)); \ - } \ - /* Count the number of Python digits. */ \ - Py_ssize_t ndigits = 0; \ - INT_TYPE t = (ival); \ - while (t) { \ - ++ndigits; \ - t >>= PyLong_SHIFT; \ - } \ - PyLongObject *v = _PyLong_New(ndigits); \ - if (v == NULL) { \ - return NULL; \ - } \ - digit *p = v->long_value.ob_digit; \ - while ((ival)) { \ - *p++ = (digit)((ival) & PyLong_MASK); \ - (ival) >>= PyLong_SHIFT; \ - } \ - return (PyObject *)v; \ - } while(0) - /* Create a new int object from a C unsigned long int */ PyObject * @@ -399,7 +401,7 @@ PyLong_FromUnsignedLongLong(unsigned long long ival) PyObject * PyLong_FromSize_t(size_t ival) { - PYLONG_FROM_UINT(size_t, ival); + PYLONG_FROM_SIGNED(size_t, ival); } /* Create a new int object from a C double */ From ba70518630541d9f4bfebb46610c2908582b229f Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 13:32:57 +0530 Subject: [PATCH 02/21] Revert change --- Objects/longobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 2e1faf3e0171f1..4cf2327b78979a 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -401,7 +401,7 @@ PyLong_FromUnsignedLongLong(unsigned long long ival) PyObject * PyLong_FromSize_t(size_t ival) { - PYLONG_FROM_SIGNED(size_t, ival); + PYLONG_FROM_UINT(size_t, ival); } /* Create a new int object from a C double */ From 34315cb4fbf6be7c6719894899d236d4263c019d Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 14:03:18 +0530 Subject: [PATCH 03/21] Correct types --- Objects/longobject.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 4cf2327b78979a..63191fc48bcacc 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -117,6 +117,7 @@ maybe_small_long(PyLongObject *v) #define PYLONG_FROM_SIGNED(INT_TYPE, ival) \ do { \ + unsigned long abs_ival, t; \ if (IS_SMALL_INT(ival)) { \ return get_small_int((sdigit)(ival)); \ } \ @@ -124,9 +125,9 @@ maybe_small_long(PyLongObject *v) return _PyLong_FromMedium((sdigit)(ival)); \ } \ /* Count digits (at least two - smaller cases were handled above). */ \ - INT_TYPE abs_ival = (ival) < 0 ? 0U-(INT_TYPE)(ival) : (INT_TYPE)(ival); \ + abs_ival = (ival) < 0 ? 0U-(unsigned long)(ival) : (unsigned long)(ival); \ /* Do shift in two steps to avoid possible undefined behavior. */ \ - INT_TYPE t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \ + t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \ Py_ssize_t ndigits = 2; \ while (t) { \ ++ndigits; \ From 0ef383c250e7b45f15667fb5c147a9fff8012f26 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 14:30:14 +0530 Subject: [PATCH 04/21] Convert PyLong_FromLongLong() as well to leverage macro PYLONG_FROM_SIGNED. And also added a blurb about the changes --- ...-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 + Objects/longobject.c | 39 ++----------------- 2 files changed, 5 insertions(+), 36 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst new file mode 100644 index 00000000000000..1213319fe76da0 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -0,0 +1,2 @@ +Add Missing fast path in PyLong_FromLong(), PyLong_FromLongLong() functions +for compact integers diff --git a/Objects/longobject.c b/Objects/longobject.c index 63191fc48bcacc..7f36ef60cb8a6e 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -117,7 +117,7 @@ maybe_small_long(PyLongObject *v) #define PYLONG_FROM_SIGNED(INT_TYPE, ival) \ do { \ - unsigned long abs_ival, t; \ + unsigned INT_TYPE abs_ival, t; \ if (IS_SMALL_INT(ival)) { \ return get_small_int((sdigit)(ival)); \ } \ @@ -125,7 +125,7 @@ maybe_small_long(PyLongObject *v) return _PyLong_FromMedium((sdigit)(ival)); \ } \ /* Count digits (at least two - smaller cases were handled above). */ \ - abs_ival = (ival) < 0 ? 0U-(unsigned long)(ival) : (unsigned long)(ival); \ + abs_ival = (ival) < 0 ? 0U-(unsigned INT_TYPE)(ival) : (unsigned INT_TYPE)(ival); \ /* Do shift in two steps to avoid possible undefined behavior. */ \ t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \ Py_ssize_t ndigits = 2; \ @@ -1456,40 +1456,7 @@ PyLong_AsVoidPtr(PyObject *vv) PyObject * PyLong_FromLongLong(long long ival) { - PyLongObject *v; - unsigned long long abs_ival, t; - int ndigits; - - /* Handle small and medium cases. */ - if (IS_SMALL_INT(ival)) { - return get_small_int((sdigit)ival); - } - if (-(long long)PyLong_MASK <= ival && ival <= (long long)PyLong_MASK) { - return _PyLong_FromMedium((sdigit)ival); - } - - /* Count digits (at least two - smaller cases were handled above). */ - abs_ival = ival < 0 ? 0U-(unsigned long long)ival : (unsigned long long)ival; - /* Do shift in two steps to avoid possible undefined behavior. */ - t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; - ndigits = 2; - while (t) { - ++ndigits; - t >>= PyLong_SHIFT; - } - - /* Construct output value. */ - v = _PyLong_New(ndigits); - if (v != NULL) { - digit *p = v->long_value.ob_digit; - _PyLong_SetSignAndDigitCount(v, ival < 0 ? -1 : 1, ndigits); - t = abs_ival; - while (t) { - *p++ = (digit)(t & PyLong_MASK); - t >>= PyLong_SHIFT; - } - } - return (PyObject *)v; + PYLONG_FROM_SIGNED(long long, ival); } /* Create a new int object from a C Py_ssize_t. */ From c00ba8c6ca7fbf650b1180706da4ef06a06e80d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=A4=E0=B0=BE?= =?UTF-8?q?=E0=B0=9F=E0=B0=BF=E0=B0=AA=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF?= =?UTF-8?q?=20=E0=B0=B6=E0=B1=8D=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF?= =?UTF-8?q?=E0=B0=B5=E0=B0=BE=E0=B0=B8=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86?= =?UTF-8?q?=E0=B0=A1=E0=B1=8D=E0=B0=A1=E0=B0=BF=29?= Date: Wed, 22 Jan 2025 15:16:33 +0530 Subject: [PATCH 05/21] Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst Co-authored-by: Pieter Eendebak --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index 1213319fe76da0..546305c08bb3a3 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ -Add Missing fast path in PyLong_FromLong(), PyLong_FromLongLong() functions +Add missing fast path in :func:`PyLong_FromLong` and :func:`PyLong_FromLongLong` functions for compact integers From 2b5163f66cff5ef80a6296a10886c44cb8867a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=A4=E0=B0=BE?= =?UTF-8?q?=E0=B0=9F=E0=B0=BF=E0=B0=AA=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF?= =?UTF-8?q?=20=E0=B0=B6=E0=B1=8D=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF?= =?UTF-8?q?=E0=B0=B5=E0=B0=BE=E0=B0=B8=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86?= =?UTF-8?q?=E0=B0=A1=E0=B1=8D=E0=B0=A1=E0=B0=BF=29?= Date: Wed, 22 Jan 2025 15:16:42 +0530 Subject: [PATCH 06/21] Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst Co-authored-by: Pieter Eendebak --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index 546305c08bb3a3..5ed2f4018330d8 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ Add missing fast path in :func:`PyLong_FromLong` and :func:`PyLong_FromLongLong` functions -for compact integers +for compact integers. From 955bb376f848ce1103e640fa3cf984d64a4ba059 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 22 Jan 2025 14:25:25 +0300 Subject: [PATCH 07/21] Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index 5ed2f4018330d8..bf9f2e3d8aae80 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ -Add missing fast path in :func:`PyLong_FromLong` and :func:`PyLong_FromLongLong` functions +Add missing fast path in :c:func:`PyLong_FromLong` and :c:func:`PyLong_FromLongLong` functions for compact integers. From 237b8b980a1451771409b3f6012fc1e648206e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=A4=E0=B0=BE?= =?UTF-8?q?=E0=B0=9F=E0=B0=BF=E0=B0=AA=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF?= =?UTF-8?q?=20=E0=B0=B6=E0=B1=8D=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF?= =?UTF-8?q?=E0=B0=B5=E0=B0=BE=E0=B0=B8=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86?= =?UTF-8?q?=E0=B0=A1=E0=B1=8D=E0=B0=A1=E0=B0=BF=29?= Date: Wed, 22 Jan 2025 21:05:30 +0530 Subject: [PATCH 08/21] Update Objects/longobject.c Co-authored-by: Yan Yanchii --- Objects/longobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 7f36ef60cb8a6e..d95e6348d667d6 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -117,7 +117,6 @@ maybe_small_long(PyLongObject *v) #define PYLONG_FROM_SIGNED(INT_TYPE, ival) \ do { \ - unsigned INT_TYPE abs_ival, t; \ if (IS_SMALL_INT(ival)) { \ return get_small_int((sdigit)(ival)); \ } \ @@ -125,6 +124,7 @@ maybe_small_long(PyLongObject *v) return _PyLong_FromMedium((sdigit)(ival)); \ } \ /* Count digits (at least two - smaller cases were handled above). */ \ + unsigned INT_TYPE abs_ival, t; \ abs_ival = (ival) < 0 ? 0U-(unsigned INT_TYPE)(ival) : (unsigned INT_TYPE)(ival); \ /* Do shift in two steps to avoid possible undefined behavior. */ \ t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \ From 11ad06f853f90bb6c04e3195dc780eb035e5fc11 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 21:29:05 +0530 Subject: [PATCH 09/21] Move back PYLONG_FROM_UINT where it belongs earlier --- Objects/longobject.c | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index d95e6348d667d6..63ee6e1a9e4fa0 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -147,34 +147,6 @@ maybe_small_long(PyLongObject *v) return (PyObject *)v; \ } while(0) -#define PYLONG_FROM_UINT(INT_TYPE, ival) \ - do { \ - if (IS_SMALL_UINT(ival)) { \ - return get_small_int((sdigit)(ival)); \ - } \ - if ((ival) <= PyLong_MASK) { \ - return _PyLong_FromMedium((sdigit)(ival)); \ - } \ - /* Count the number of Python digits. */ \ - Py_ssize_t ndigits = 0; \ - INT_TYPE t = (ival); \ - while (t) { \ - ++ndigits; \ - t >>= PyLong_SHIFT; \ - } \ - PyLongObject *v = _PyLong_New(ndigits); \ - if (v == NULL) { \ - return NULL; \ - } \ - digit *p = v->long_value.ob_digit; \ - t = (ival); \ - while (t) { \ - *p++ = (digit)(t & PyLong_MASK); \ - t >>= PyLong_SHIFT; \ - } \ - return (PyObject *)v; \ - } while(0) - /* Normalize (remove leading zeros from) an int object. Doesn't attempt to free the storage--in most cases, due to the nature of the algorithms used, this could save at most be one word anyway. */ @@ -381,6 +353,34 @@ PyLong_FromLong(long ival) PYLONG_FROM_SIGNED(long, ival); } +#define PYLONG_FROM_UINT(INT_TYPE, ival) \ + do { \ + if (IS_SMALL_UINT(ival)) { \ + return get_small_int((sdigit)(ival)); \ + } \ + if ((ival) <= PyLong_MASK) { \ + return _PyLong_FromMedium((sdigit)(ival)); \ + } \ + /* Count the number of Python digits. */ \ + Py_ssize_t ndigits = 0; \ + INT_TYPE t = (ival); \ + while (t) { \ + ++ndigits; \ + t >>= PyLong_SHIFT; \ + } \ + PyLongObject *v = _PyLong_New(ndigits); \ + if (v == NULL) { \ + return NULL; \ + } \ + digit *p = v->long_value.ob_digit; \ + t = (ival); \ + while (t) { \ + *p++ = (digit)(t & PyLong_MASK); \ + t >>= PyLong_SHIFT; \ + } \ + return (PyObject *)v; \ + } while(0) + /* Create a new int object from a C unsigned long int */ PyObject * From c25b910d2dcd019be3121a3bec8120fc5b734cca Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 21:31:53 +0530 Subject: [PATCH 10/21] Undo the changes --- Objects/longobject.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index 63ee6e1a9e4fa0..a74db9907773d9 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -373,10 +373,9 @@ PyLong_FromLong(long ival) return NULL; \ } \ digit *p = v->long_value.ob_digit; \ - t = (ival); \ - while (t) { \ - *p++ = (digit)(t & PyLong_MASK); \ - t >>= PyLong_SHIFT; \ + while ((ival)) { \ + *p++ = (digit)((ival) & PyLong_MASK); \ + (ival) >>= PyLong_SHIFT; \ } \ return (PyObject *)v; \ } while(0) From 37a5c9aa3bb0bca09071170032244c7ba7faaa00 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 21:50:50 +0530 Subject: [PATCH 11/21] Updated blurb accordingly --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index bf9f2e3d8aae80..6f440f90b2a54d 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ -Add missing fast path in :c:func:`PyLong_FromLong` and :c:func:`PyLong_FromLongLong` functions -for compact integers. +Add missing fast path in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t` functions +for compact integers. And refactor :c:func:`PyLong_FromLong` and :c:func:`PyLong_FromLongLong` to use the macro :c:macro:`PYLONG_FROM_SIGNED`. From 2cb1aec3ad65f2276fcb2ba12e4e8b4f7c073033 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 22:03:18 +0530 Subject: [PATCH 12/21] Remove :c:macro since it is only internal macro --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index 6f440f90b2a54d..0d18bd044b6974 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ Add missing fast path in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t` functions -for compact integers. And refactor :c:func:`PyLong_FromLong` and :c:func:`PyLong_FromLongLong` to use the macro :c:macro:`PYLONG_FROM_SIGNED`. +for compact integers. And refactor :c:func:`PyLong_FromLong` and :c:func:`PyLong_FromLongLong` to use the macro ``PYLONG_FROM_SIGNED``. From 99c542093a2611324224f77e95bd739d791f76bc Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Wed, 22 Jan 2025 22:07:34 +0530 Subject: [PATCH 13/21] Address review comments --- Objects/longobject.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index a74db9907773d9..ca61ed3b383d25 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -361,9 +361,10 @@ PyLong_FromLong(long ival) if ((ival) <= PyLong_MASK) { \ return _PyLong_FromMedium((sdigit)(ival)); \ } \ + /* Do shift in two steps to avoid possible undefined behavior. */ \ + INT_TYPE t = (ival) >> PyLong_SHIFT >> PyLong_SHIFT; \ /* Count the number of Python digits. */ \ - Py_ssize_t ndigits = 0; \ - INT_TYPE t = (ival); \ + Py_ssize_t ndigits = 2; \ while (t) { \ ++ndigits; \ t >>= PyLong_SHIFT; \ From 2724758ea8b3820fb78b7e6a93b18fa9870d30db Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 23 Jan 2025 11:41:34 +0530 Subject: [PATCH 14/21] Revert the refactoring --- Objects/longobject.c | 101 +++++++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 33 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index ca61ed3b383d25..e908d35d3d6ef1 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -115,37 +115,6 @@ maybe_small_long(PyLongObject *v) if (PyErr_CheckSignals()) PyTryBlock \ } while(0) -#define PYLONG_FROM_SIGNED(INT_TYPE, ival) \ - do { \ - if (IS_SMALL_INT(ival)) { \ - return get_small_int((sdigit)(ival)); \ - } \ - if (-(INT_TYPE)PyLong_MASK <= (ival) && (ival) <= (INT_TYPE)PyLong_MASK) { \ - return _PyLong_FromMedium((sdigit)(ival)); \ - } \ - /* Count digits (at least two - smaller cases were handled above). */ \ - unsigned INT_TYPE abs_ival, t; \ - abs_ival = (ival) < 0 ? 0U-(unsigned INT_TYPE)(ival) : (unsigned INT_TYPE)(ival); \ - /* Do shift in two steps to avoid possible undefined behavior. */ \ - t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; \ - Py_ssize_t ndigits = 2; \ - while (t) { \ - ++ndigits; \ - t >>= PyLong_SHIFT; \ - } \ - PyLongObject *v = _PyLong_New(ndigits); \ - if (v == NULL) { \ - return NULL; \ - } \ - digit *p = v->long_value.ob_digit; \ - _PyLong_SetSignAndDigitCount(v, (ival) < 0 ? -1 : 1, ndigits); \ - t = abs_ival; \ - while (t) { \ - *p++ = (digit)(t & PyLong_MASK); \ - t >>= PyLong_SHIFT; \ - } \ - return (PyObject *)v; \ - } while(0) /* Normalize (remove leading zeros from) an int object. Doesn't attempt to free the storage--in most cases, due to the nature @@ -350,7 +319,40 @@ _PyLong_Negate(PyLongObject **x_p) PyObject * PyLong_FromLong(long ival) { - PYLONG_FROM_SIGNED(long, ival); + PyLongObject *v; + unsigned long abs_ival, t; + int ndigits; + + /* Handle small and medium cases. */ + if (IS_SMALL_INT(ival)) { + return get_small_int((sdigit)ival); + } + if (-(long)PyLong_MASK <= ival && ival <= (long)PyLong_MASK) { + return _PyLong_FromMedium((sdigit)ival); + } + + /* Count digits (at least two - smaller cases were handled above). */ + abs_ival = ival < 0 ? 0U-(unsigned long)ival : (unsigned long)ival; + /* Do shift in two steps to avoid possible undefined behavior. */ + t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; + ndigits = 2; + while (t) { + ++ndigits; + t >>= PyLong_SHIFT; + } + + /* Construct output value. */ + v = _PyLong_New(ndigits); + if (v != NULL) { + digit *p = v->long_value.ob_digit; + _PyLong_SetSignAndDigitCount(v, ival < 0 ? -1 : 1, ndigits); + t = abs_ival; + while (t) { + *p++ = (digit)(t & PyLong_MASK); + t >>= PyLong_SHIFT; + } + } + return (PyObject *)v; } #define PYLONG_FROM_UINT(INT_TYPE, ival) \ @@ -1456,7 +1458,40 @@ PyLong_AsVoidPtr(PyObject *vv) PyObject * PyLong_FromLongLong(long long ival) { - PYLONG_FROM_SIGNED(long long, ival); + PyLongObject *v; + unsigned long long abs_ival, t; + int ndigits; + + /* Handle small and medium cases. */ + if (IS_SMALL_INT(ival)) { + return get_small_int((sdigit)ival); + } + if (-(long long)PyLong_MASK <= ival && ival <= (long long)PyLong_MASK) { + return _PyLong_FromMedium((sdigit)ival); + } + + /* Count digits (at least two - smaller cases were handled above). */ + abs_ival = ival < 0 ? 0U-(unsigned long long)ival : (unsigned long long)ival; + /* Do shift in two steps to avoid possible undefined behavior. */ + t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT; + ndigits = 2; + while (t) { + ++ndigits; + t >>= PyLong_SHIFT; + } + + /* Construct output value. */ + v = _PyLong_New(ndigits); + if (v != NULL) { + digit *p = v->long_value.ob_digit; + _PyLong_SetSignAndDigitCount(v, ival < 0 ? -1 : 1, ndigits); + t = abs_ival; + while (t) { + *p++ = (digit)(t & PyLong_MASK); + t >>= PyLong_SHIFT; + } + } + return (PyObject *)v; } /* Create a new int object from a C Py_ssize_t. */ From 2a8692dd1a5a4e7c5bf796aec42440c5b88d39ec Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 23 Jan 2025 11:45:24 +0530 Subject: [PATCH 15/21] Revert changes --- Objects/longobject.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Objects/longobject.c b/Objects/longobject.c index e908d35d3d6ef1..861a732a5eb479 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -115,7 +115,6 @@ maybe_small_long(PyLongObject *v) if (PyErr_CheckSignals()) PyTryBlock \ } while(0) - /* Normalize (remove leading zeros from) an int object. Doesn't attempt to free the storage--in most cases, due to the nature of the algorithms used, this could save at most be one word anyway. */ From 70d85f16af51dcf06f64a4ca103fbdbd9c1b4aca Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 23 Jan 2025 11:47:54 +0530 Subject: [PATCH 16/21] update the blurb : Remove note about refactoring --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index 0d18bd044b6974..e9d9baa3cba4fa 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ Add missing fast path in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t` functions -for compact integers. And refactor :c:func:`PyLong_FromLong` and :c:func:`PyLong_FromLongLong` to use the macro ``PYLONG_FROM_SIGNED``. +for compact integers. From af410e0732d90e54cb2f5279555c5f04c42e3ea3 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 23 Jan 2025 12:27:13 +0530 Subject: [PATCH 17/21] Remove blurb --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst deleted file mode 100644 index e9d9baa3cba4fa..00000000000000 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add missing fast path in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t` functions -for compact integers. From 5a9e201806141312ddafdbc0e642c59a9e63062d Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 23 Jan 2025 12:41:58 +0530 Subject: [PATCH 18/21] Revert "Remove blurb" This reverts commit af410e0732d90e54cb2f5279555c5f04c42e3ea3. --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst new file mode 100644 index 00000000000000..e9d9baa3cba4fa --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -0,0 +1,2 @@ +Add missing fast path in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t` functions +for compact integers. From 5760c954fd39b9787a6616db4efe967a67d6ef39 Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Thatiparthy Date: Thu, 23 Jan 2025 13:11:31 +0530 Subject: [PATCH 19/21] Update news entry for better wording --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index e9d9baa3cba4fa..b28ce91021eada 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ -Add missing fast path in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t` functions -for compact integers. +Add missing fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, +:c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t`. From 1f81b87fc95f24e5b7e9db4ce865c9e3617b9fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=A4=E0=B0=BE?= =?UTF-8?q?=E0=B0=9F=E0=B0=BF=E0=B0=AA=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF?= =?UTF-8?q?=20=E0=B0=B6=E0=B1=8D=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF?= =?UTF-8?q?=E0=B0=B5=E0=B0=BE=E0=B0=B8=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86?= =?UTF-8?q?=E0=B0=A1=E0=B1=8D=E0=B0=A1=E0=B0=BF=29?= Date: Thu, 23 Jan 2025 17:52:24 +0530 Subject: [PATCH 20/21] Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index b28ce91021eada..22f3082943a897 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ -Add missing fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, +Add missing fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t`. From f4d74d229a26f517973d55fc3f9769f266384413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Srinivas=20Reddy=20Thatiparthy=20=28=E0=B0=A4=E0=B0=BE?= =?UTF-8?q?=E0=B0=9F=E0=B0=BF=E0=B0=AA=E0=B0=B0=E0=B1=8D=E0=B0=A4=E0=B0=BF?= =?UTF-8?q?=20=E0=B0=B6=E0=B1=8D=E0=B0=B0=E0=B1=80=E0=B0=A8=E0=B0=BF?= =?UTF-8?q?=E0=B0=B5=E0=B0=BE=E0=B0=B8=E0=B1=8D=20=20=E0=B0=B0=E0=B1=86?= =?UTF-8?q?=E0=B0=A1=E0=B1=8D=E0=B0=A1=E0=B0=BF=29?= Date: Thu, 23 Jan 2025 19:43:14 +0530 Subject: [PATCH 21/21] Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst Co-authored-by: Victor Stinner --- .../2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst index 22f3082943a897..d946f6a2fea185 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issue-129149.wAYu43.rst @@ -1,2 +1,2 @@ -Add missing fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, +Add fast path for medium-size integers in :c:func:`PyLong_FromUnsignedLong`, :c:func:`PyLong_FromUnsignedLongLong` and :c:func:`PyLong_FromSize_t`.