@@ -40,6 +40,8 @@ medium_value(PyLongObject *x)
40
40
#define IS_SMALL_INT (ival ) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)
41
41
#define IS_SMALL_UINT (ival ) ((ival) < NSMALLPOSINTS)
42
42
43
+ /* To be valid the type of x must cover -PyLong_BASE to +PyLong_BASE.
44
+ int, long, Py_ssize_t are all ok */
43
45
#define IS_MEDIUM_INT (x ) (((twodigits)x)+PyLong_MASK <= 2*PyLong_MASK)
44
46
45
47
static PyObject *
@@ -195,9 +197,10 @@ _PyLong_FromLarge(stwodigits ival)
195
197
abs_ival = (twodigits )ival ;
196
198
sign = 1 ;
197
199
}
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 ;
201
204
while (t ) {
202
205
++ ndigits ;
203
206
t >>= PyLong_SHIFT ;
@@ -251,8 +254,44 @@ _PyLong_Negate(PyLongObject **x_p)
251
254
PyObject *
252
255
PyLong_FromLong (long ival )
253
256
{
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 ;
256
295
}
257
296
258
297
#define PYLONG_FROM_UINT (INT_TYPE , ival ) \
@@ -3554,7 +3593,7 @@ long_mul(PyLongObject *a, PyLongObject *b)
3554
3593
/* fast path for single-digit multiplication */
3555
3594
if (IS_MEDIUM_VALUE (a ) && IS_MEDIUM_VALUE (b )) {
3556
3595
stwodigits v = medium_value (a ) * medium_value (b );
3557
- return PyLong_FromLongLong (( long long ) v );
3596
+ return _PyLong_FromSTwoDigits ( v );
3558
3597
}
3559
3598
3560
3599
z = k_mul (a , b );
0 commit comments