Commit d4624c33 authored by Mark Dickinson's avatar Mark Dickinson

Some minor cleanups in PyLong_FromLong:

 - fast path wasn't being properly taken for negative ints;
   thanks Victor Stinner for pointing this out.
 - use Py_SAFE_DOWNCAST instead of direct casting to digit
   (it's safer, especially if we ever consider moving to 30-bit
   digits)
 - cleaner way to write negation
parent 59e4779a
...@@ -175,7 +175,7 @@ PyObject * ...@@ -175,7 +175,7 @@ PyObject *
PyLong_FromLong(long ival) PyLong_FromLong(long ival)
{ {
PyLongObject *v; PyLongObject *v;
unsigned long abs_ival; unsigned long abs_ival;
unsigned long t; /* unsigned so >> doesn't propagate sign bit */ unsigned long t; /* unsigned so >> doesn't propagate sign bit */
int ndigits = 0; int ndigits = 0;
int sign = 1; int sign = 1;
...@@ -183,33 +183,35 @@ PyLong_FromLong(long ival) ...@@ -183,33 +183,35 @@ PyLong_FromLong(long ival)
CHECK_SMALL_INT(ival); CHECK_SMALL_INT(ival);
if (ival < 0) { if (ival < 0) {
/* if LONG_MIN == -LONG_MAX-1 (true on most platforms) then /* negate: can't write this as abs_ival = -ival since that
ANSI C says that the result of -ival is undefined when ival invokes undefined behaviour when ival is LONG_MIN */
== LONG_MIN. Hence the following workaround. */ abs_ival = 0U-(unsigned long)ival;
abs_ival = (unsigned long)(-1-ival) + 1;
sign = -1; sign = -1;
} }
else { else {
abs_ival = (unsigned long)ival; abs_ival = (unsigned long)ival;
} }
/* Fast path for single-digits ints */ /* Fast path for single-digit ints */
if (!(ival>>PyLong_SHIFT)) { if (!(abs_ival >> PyLong_SHIFT)) {
v = _PyLong_New(1); v = _PyLong_New(1);
if (v) { if (v) {
Py_SIZE(v) = sign; Py_SIZE(v) = sign;
v->ob_digit[0] = (digit)ival; v->ob_digit[0] = Py_SAFE_DOWNCAST(
abs_ival, unsigned long, digit);
} }
return (PyObject*)v; return (PyObject*)v;
} }
/* 2 digits */ /* 2 digits */
if (!(ival >> 2*PyLong_SHIFT)) { if (!(abs_ival >> 2*PyLong_SHIFT)) {
v = _PyLong_New(2); v = _PyLong_New(2);
if (v) { if (v) {
Py_SIZE(v) = 2*sign; Py_SIZE(v) = 2*sign;
v->ob_digit[0] = (digit)ival & PyLong_MASK; v->ob_digit[0] = Py_SAFE_DOWNCAST(
v->ob_digit[1] = (digit)(ival >> PyLong_SHIFT); abs_ival & PyLong_MASK, unsigned long, digit);
v->ob_digit[1] = Py_SAFE_DOWNCAST(
abs_ival >> PyLong_SHIFT, unsigned long, digit);
} }
return (PyObject*)v; return (PyObject*)v;
} }
...@@ -226,7 +228,8 @@ PyLong_FromLong(long ival) ...@@ -226,7 +228,8 @@ PyLong_FromLong(long ival)
Py_SIZE(v) = ndigits*sign; Py_SIZE(v) = ndigits*sign;
t = abs_ival; t = abs_ival;
while (t) { while (t) {
*p++ = (digit)(t & PyLong_MASK); *p++ = Py_SAFE_DOWNCAST(
t & PyLong_MASK, unsigned long, digit);
t >>= PyLong_SHIFT; t >>= PyLong_SHIFT;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment