@@ -262,6 +262,24 @@ _PyLong_FromMedium(sdigit x)
262
262
return (PyObject * )v ;
263
263
}
264
264
265
+ static twodigits THREE_DIGIT_CUTOFF = (twodigits )1 << PyLong_SHIFT << PyLong_SHIFT ; // two shifts to avoud undefined behavior
266
+
267
+ static inline Py_ssize_t _fast_digit_count_ssize_t (Py_ssize_t abs_ival )
268
+ {
269
+ assert (abs_ival >> PyLong_SHIFT != 0 );
270
+ Py_ssize_t ndigits = abs_ival <= THREE_DIGIT_CUTOFF ? 2 : 3 ;
271
+ return ndigits ;
272
+ }
273
+
274
+
275
+
276
+ static inline Py_ssize_t _fast_digit_count (twodigits abs_ival )
277
+ {
278
+ assert (abs_ival >> PyLong_SHIFT != 0 );
279
+ Py_ssize_t ndigits = abs_ival <= THREE_DIGIT_CUTOFF ? 2 : 3 ;
280
+ return ndigits ;
281
+ }
282
+
265
283
static PyObject *
266
284
_PyLong_FromLarge (stwodigits ival )
267
285
{
@@ -279,6 +297,11 @@ _PyLong_FromLarge(stwodigits ival)
279
297
abs_ival = (twodigits )ival ;
280
298
sign = 1 ;
281
299
}
300
+ #if PYLONG_BITS_IN_DIGIT == 31
301
+ /* Must be at least two digits, at most 3 */
302
+ twodigits t ;
303
+ Py_ssize_t ndigits = _fast_digit_count (abs_ival );
304
+ #else
282
305
/* Must be at least two digits */
283
306
assert (abs_ival >> PyLong_SHIFT != 0 );
284
307
twodigits t = abs_ival >> (PyLong_SHIFT * 2 );
@@ -287,6 +310,7 @@ _PyLong_FromLarge(stwodigits ival)
287
310
++ ndigits ;
288
311
t >>= PyLong_SHIFT ;
289
312
}
313
+ #endif
290
314
PyLongObject * v = long_alloc (ndigits );
291
315
if (v != NULL ) {
292
316
digit * p = v -> long_value .ob_digit ;
@@ -353,11 +377,7 @@ PyLong_FromLong(long ival)
353
377
abs_ival = ival < 0 ? 0U - (unsigned long )ival : (unsigned long )ival ;
354
378
/* Do shift in two steps to avoid possible undefined behavior. */
355
379
t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT ;
356
- ndigits = 2 ;
357
- while (t ) {
358
- ++ ndigits ;
359
- t >>= PyLong_SHIFT ;
360
- }
380
+ ndigits = _fast_digit_count_ssize_t (abs_ival );
361
381
362
382
/* Construct output value. */
363
383
v = long_alloc (ndigits );
@@ -384,11 +404,7 @@ PyLong_FromLong(long ival)
384
404
/* Do shift in two steps to avoid possible undefined behavior. */ \
385
405
INT_TYPE t = (ival ) >> PyLong_SHIFT >> PyLong_SHIFT ; \
386
406
/* Count the number of Python digits. */ \
387
- Py_ssize_t ndigits = 2 ; \
388
- while (t ) { \
389
- ++ ndigits ; \
390
- t >>= PyLong_SHIFT ; \
391
- } \
407
+ Py_ssize_t ndigits = _fast_digit_count_ssize_t (ival ); \
392
408
PyLongObject * v = long_alloc (ndigits ); \
393
409
if (v == NULL ) { \
394
410
return NULL ; \
@@ -1526,7 +1542,6 @@ PyLong_FromSsize_t(Py_ssize_t ival)
1526
1542
PyLongObject * v ;
1527
1543
size_t abs_ival ;
1528
1544
size_t t ; /* unsigned so >> doesn't propagate sign bit */
1529
- int ndigits = 0 ;
1530
1545
int negative = 0 ;
1531
1546
1532
1547
if (IS_SMALL_INT (ival )) {
@@ -1543,11 +1558,7 @@ PyLong_FromSsize_t(Py_ssize_t ival)
1543
1558
}
1544
1559
1545
1560
/* Count the number of Python digits. */
1546
- t = abs_ival ;
1547
- while (t ) {
1548
- ++ ndigits ;
1549
- t >>= PyLong_SHIFT ;
1550
- }
1561
+ Py_ssize_t ndigits = _fast_digit_count_ssize_t (abs_ival );
1551
1562
v = long_alloc (ndigits );
1552
1563
if (v != NULL ) {
1553
1564
digit * p = v -> long_value .ob_digit ;
0 commit comments