Skip to content

Commit

Permalink
Create a macro PYLONG_FROM_SIGNED, and leverage it in functions PyLon…
Browse files Browse the repository at this point in the history
…g_FromLong, PyLong_FromLongLong and PyLong_FromSsize_t so the repetitive code is removed.
  • Loading branch information
srinivasreddy committed Jan 23, 2025
1 parent d7d066c commit d63235b
Showing 1 changed file with 40 additions and 104 deletions.
144 changes: 40 additions & 104 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,43 @@ 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). */ \
size_t abs_ival, t; /* Use size_t for unsigned operations */ \
if ((ival) < 0) { \
/* avoid signed overflow when ival = minimum value */ \
abs_ival = (size_t)(-1-(ival))+1; \
} else { \
abs_ival = (size_t)(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
of the algorithms used, this could save at most be one word anyway. */
Expand Down Expand Up @@ -318,40 +355,7 @@ _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) \
Expand Down Expand Up @@ -1459,83 +1463,15 @@ 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. */

PyObject *
PyLong_FromSsize_t(Py_ssize_t ival)
{
PyLongObject *v;
size_t abs_ival;
size_t t; /* unsigned so >> doesn't propagate sign bit */
int ndigits = 0;
int negative = 0;

if (IS_SMALL_INT(ival)) {
return get_small_int((sdigit)ival);
}

if (ival < 0) {
/* avoid signed overflow when ival = SIZE_T_MIN */
abs_ival = (size_t)(-1-ival)+1;
negative = 1;
}
else {
abs_ival = (size_t)ival;
}

/* Count the number of Python digits. */
t = abs_ival;
while (t) {
++ndigits;
t >>= PyLong_SHIFT;
}
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->long_value.ob_digit;
_PyLong_SetSignAndDigitCount(v, negative ? -1 : 1, ndigits);
t = abs_ival;
while (t) {
*p++ = (digit)(t & PyLong_MASK);
t >>= PyLong_SHIFT;
}
}
return (PyObject *)v;
PYLONG_FROM_SIGNED(Py_ssize_t, ival);
}

/* Get a C long long int from an int object or any object that has an
Expand Down

0 comments on commit d63235b

Please sign in to comment.