Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-129149: Add Missing fast path in PYLONG_FROM_UINT macro for compact integers #129168

Merged
merged 21 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ed9be47
Add Missing fast path in PyLong_From*() functions for compact integers
srinivasreddy Jan 22, 2025
ba70518
Revert change
srinivasreddy Jan 22, 2025
34315cb
Correct types
srinivasreddy Jan 22, 2025
0ef383c
Convert PyLong_FromLongLong() as well to leverage macro PYLONG_FROM_S…
srinivasreddy Jan 22, 2025
c00ba8c
Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issu…
srinivasreddy Jan 22, 2025
2b5163f
Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issu…
srinivasreddy Jan 22, 2025
955bb37
Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issu…
skirpichev Jan 22, 2025
237b8b9
Update Objects/longobject.c
srinivasreddy Jan 22, 2025
11ad06f
Move back PYLONG_FROM_UINT where it belongs earlier
srinivasreddy Jan 22, 2025
c25b910
Undo the changes
srinivasreddy Jan 22, 2025
37a5c9a
Updated blurb accordingly
srinivasreddy Jan 22, 2025
2cb1aec
Remove :c:macro since it is only internal macro
srinivasreddy Jan 22, 2025
99c5420
Address review comments
srinivasreddy Jan 22, 2025
2724758
Revert the refactoring
srinivasreddy Jan 23, 2025
2a8692d
Revert changes
srinivasreddy Jan 23, 2025
70d85f1
update the blurb : Remove note about refactoring
srinivasreddy Jan 23, 2025
af410e0
Remove blurb
srinivasreddy Jan 23, 2025
5a9e201
Revert "Remove blurb"
srinivasreddy Jan 23, 2025
5760c95
Update news entry for better wording
srinivasreddy Jan 23, 2025
1f81b87
Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issu…
srinivasreddy Jan 23, 2025
f4d74d2
Update Misc/NEWS.d/next/Core_and_Builtins/2025-01-22-14-24-44.gh-issu…
srinivasreddy Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add Missing fast path in PyLong_FromLong(), PyLong_FromLongLong() functions
srinivasreddy marked this conversation as resolved.
Show resolved Hide resolved
for compact integers
srinivasreddy marked this conversation as resolved.
Show resolved Hide resolved
154 changes: 62 additions & 92 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,66 @@ maybe_small_long(PyLongObject *v)
if (PyErr_CheckSignals()) PyTryBlock \
} while(0)

#define PYLONG_FROM_SIGNED(INT_TYPE, ival) \
skirpichev marked this conversation as resolved.
Show resolved Hide resolved
do { \
unsigned INT_TYPE abs_ival, t; \
srinivasreddy marked this conversation as resolved.
Show resolved Hide resolved
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). */ \
srinivasreddy marked this conversation as resolved.
Show resolved Hide resolved
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)

#define PYLONG_FROM_UINT(INT_TYPE, ival) \
srinivasreddy marked this conversation as resolved.
Show resolved Hide resolved
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. */
Expand Down Expand Up @@ -318,66 +378,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 *
Expand Down Expand Up @@ -1453,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. */
Expand Down
Loading