diff --git a/Objects/longobject.c b/Objects/longobject.c index 905c4695f60d4f..34362c63a25854 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -262,6 +262,24 @@ _PyLong_FromMedium(sdigit x) return (PyObject*)v; } +static twodigits THREE_DIGIT_CUTOFF = (twodigits)1 << PyLong_SHIFT << PyLong_SHIFT; // two shifts to avoud undefined behavior + +static inline Py_ssize_t _fast_digit_count_ssize_t(Py_ssize_t abs_ival) +{ + assert(abs_ival >> PyLong_SHIFT != 0); + Py_ssize_t ndigits = abs_ival <= THREE_DIGIT_CUTOFF ? 2 : 3; + return ndigits; +} + + + +static inline Py_ssize_t _fast_digit_count(twodigits abs_ival) +{ + assert(abs_ival >> PyLong_SHIFT != 0); + Py_ssize_t ndigits = abs_ival <= THREE_DIGIT_CUTOFF ? 2 : 3; + return ndigits; +} + static PyObject * _PyLong_FromLarge(stwodigits ival) { @@ -279,6 +297,11 @@ _PyLong_FromLarge(stwodigits ival) abs_ival = (twodigits)ival; sign = 1; } +#if PYLONG_BITS_IN_DIGIT == 31 + /* Must be at least two digits, at most 3 */ + twodigits t; + Py_ssize_t ndigits = _fast_digit_count(abs_ival); +#else /* Must be at least two digits */ assert(abs_ival >> PyLong_SHIFT != 0); twodigits t = abs_ival >> (PyLong_SHIFT * 2); @@ -287,6 +310,7 @@ _PyLong_FromLarge(stwodigits ival) ++ndigits; t >>= PyLong_SHIFT; } +#endif PyLongObject *v = long_alloc(ndigits); if (v != NULL) { digit *p = v->long_value.ob_digit; @@ -353,11 +377,7 @@ PyLong_FromLong(long ival) 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; - } + ndigits = _fast_digit_count_ssize_t(abs_ival); /* Construct output value. */ v = long_alloc(ndigits); @@ -384,11 +404,7 @@ PyLong_FromLong(long 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 = 2; \ - while (t) { \ - ++ndigits; \ - t >>= PyLong_SHIFT; \ - } \ + Py_ssize_t ndigits = _fast_digit_count_ssize_t(ival); \ PyLongObject *v = long_alloc(ndigits); \ if (v == NULL) { \ return NULL; \ @@ -1526,7 +1542,6 @@ 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)) { @@ -1543,11 +1558,7 @@ PyLong_FromSsize_t(Py_ssize_t ival) } /* Count the number of Python digits. */ - t = abs_ival; - while (t) { - ++ndigits; - t >>= PyLong_SHIFT; - } + Py_ssize_t ndigits = _fast_digit_count_ssize_t(abs_ival); v = long_alloc(ndigits); if (v != NULL) { digit *p = v->long_value.ob_digit;