@@ -40,6 +40,8 @@ medium_value(PyLongObject *x)
4040#define IS_SMALL_INT (ival ) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
4141#define IS_SMALL_UINT (ival ) ((ival) < NSMALLPOSINTS)
4242
43+ /* To be valid the type of x must cover -PyLong_BASE to +PyLong_BASE.
44+ int, long, Py_ssize_t are all ok */
4345#define IS_MEDIUM_INT (x ) (((twodigits)x)+PyLong_MASK <= 2*PyLong_MASK)
4446
4547static PyObject *
@@ -195,9 +197,10 @@ _PyLong_FromLarge(stwodigits ival)
195197 abs_ival = (twodigits )ival ;
196198 sign = 1 ;
197199 }
198- /* Loop to determine number of digits */
199- twodigits t = abs_ival ;
200- Py_ssize_t ndigits = 0 ;
200+ /* Must be at least two digits */
201+ assert (abs_ival >> PyLong_SHIFT != 0 );
202+ twodigits t = abs_ival >> (PyLong_SHIFT * 2 );
203+ Py_ssize_t ndigits = 2 ;
201204 while (t ) {
202205 ++ ndigits ;
203206 t >>= PyLong_SHIFT ;
@@ -251,8 +254,44 @@ _PyLong_Negate(PyLongObject **x_p)
251254PyObject *
252255PyLong_FromLong (long ival )
253256{
254- Py_BUILD_ASSERT (sizeof (stwodigits ) >= sizeof (long ));
255- return _PyLong_FromSTwoDigits (ival );
257+ if (IS_SMALL_INT (ival )) {
258+ return get_small_int ((sdigit )ival );
259+ }
260+ unsigned long abs_ival ;
261+ int sign ;
262+ if (ival < 0 ) {
263+ /* negate: can't write this as abs_ival = -ival since that
264+ invokes undefined behaviour when ival is LONG_MIN */
265+ abs_ival = 0U - (twodigits )ival ;
266+ sign = -1 ;
267+ }
268+ else {
269+ abs_ival = (unsigned long )ival ;
270+ sign = 1 ;
271+ }
272+ /* Fast path for single-digit ints */
273+ if (!(abs_ival >> PyLong_SHIFT )) {
274+ return _PyLong_FromMedium ((sdigit )ival );
275+ }
276+ /* Must be at least two digits */
277+ unsigned long t = abs_ival >> (PyLong_SHIFT * 2 );
278+ Py_ssize_t ndigits = 2 ;
279+ while (t ) {
280+ ++ ndigits ;
281+ t >>= PyLong_SHIFT ;
282+ }
283+ PyLongObject * v = _PyLong_New (ndigits );
284+ if (v != NULL ) {
285+ digit * p = v -> ob_digit ;
286+ Py_SET_SIZE (v , ndigits * sign );
287+ t = abs_ival ;
288+ while (t ) {
289+ * p ++ = Py_SAFE_DOWNCAST (
290+ t & PyLong_MASK , unsigned long , digit );
291+ t >>= PyLong_SHIFT ;
292+ }
293+ }
294+ return (PyObject * )v ;
256295}
257296
258297#define PYLONG_FROM_UINT (INT_TYPE , ival ) \
@@ -3554,7 +3593,7 @@ long_mul(PyLongObject *a, PyLongObject *b)
35543593 /* fast path for single-digit multiplication */
35553594 if (IS_MEDIUM_VALUE (a ) && IS_MEDIUM_VALUE (b )) {
35563595 stwodigits v = medium_value (a ) * medium_value (b );
3557- return PyLong_FromLongLong (( long long ) v );
3596+ return _PyLong_FromSTwoDigits ( v );
35583597 }
35593598
35603599 z = k_mul (a , b );
0 commit comments