Skip to content

Commit a67837c

Browse files
committed
WIP
1 parent 32d6758 commit a67837c

11 files changed

Lines changed: 993 additions & 1197 deletions

File tree

Include/internal/pycore_long.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -357,12 +357,8 @@ _PyLong_CheckExactAndCompact(PyObject *op)
357357
#define _PY_LONG_MAX_DIGITS_FOR_INT64 ((64 + PyLong_SHIFT - 1) / PyLong_SHIFT)
358358

359359
static inline int
360-
_PyLong_CheckExactAndMightFitInt64(PyObject *op)
360+
_PyLong_MightFitInt64(const PyLongObject *v)
361361
{
362-
if (!PyLong_CheckExact(op)) {
363-
return 0;
364-
}
365-
const PyLongObject *v = (const PyLongObject *)op;
366362
if (_PyLong_IsCompact(v)) {
367363
return 1;
368364
}
@@ -382,6 +378,13 @@ _PyLong_CheckExactAndMightFitInt64(PyObject *op)
382378
return 1;
383379
}
384380

381+
static inline int
382+
_PyLong_CheckExactAndMightFitInt64(PyObject *op)
383+
{
384+
return PyLong_CheckExact(op) &&
385+
_PyLong_MightFitInt64((const PyLongObject *)op);
386+
}
387+
385388
/* Extract an exact int to int64_t without raising.
386389
*
387390
* Returns true on success and writes to *out; returns false if the value is
@@ -396,21 +399,18 @@ _PyLong_TryAsInt64Exact(PyLongObject *v, int64_t *out)
396399
return true;
397400
}
398401
Py_ssize_t ndigits = _PyLong_DigitCount(v);
399-
if (ndigits == 0) {
400-
*out = 0;
401-
return true;
402-
}
403402
if (ndigits > _PY_LONG_MAX_DIGITS_FOR_INT64) {
404403
return false;
405404
}
406405
uint64_t abs_val = 0;
407406
unsigned int shift = 0;
408407
for (Py_ssize_t i = 0; i < ndigits; i++) {
409408
uint64_t d = (uint64_t)v->long_value.ob_digit[i];
410-
if (shift >= 64) {
411-
return false;
412-
}
413-
if (shift != 0 && (d >> (64 - shift)) != 0) {
409+
if (ndigits == _PY_LONG_MAX_DIGITS_FOR_INT64 &&
410+
i == ndigits - 1 &&
411+
shift != 0 &&
412+
(d >> (64 - shift)) != 0)
413+
{
414414
return false;
415415
}
416416
abs_val |= d << shift;

0 commit comments

Comments
 (0)