diff --git a/Objects/longobject.c b/Objects/longobject.c index 370931e64d3627..62e296f0328e7c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -115,6 +115,48 @@ 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; /* Use size_t for unsigned operations */ \ + size_t t; \ + if ((ival) < 0) { \ + /* Handle minimum value case separately to avoid overflow */ \ + if ((size_t)(ival) == ((size_t)1 << (sizeof(INT_TYPE) * 8 - 1))) { \ + abs_ival = ((size_t)1 << (sizeof(INT_TYPE) * 8 - 1)); \ + } else { \ + abs_ival = (size_t)(-(ival)); \ + } \ + } 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. */ @@ -318,40 +360,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) \ @@ -1459,40 +1468,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. */ @@ -1500,42 +1476,7 @@ PyLong_FromLongLong(long long ival) 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