diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-01-24 15:02:35 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-01-24 15:02:35 (GMT) |
commit | d4624c3331a54506b9c678ad096e56366b66f51d (patch) | |
tree | b503cc038d47e1f1fbb565f0987d74a970bcf42b /Objects/longobject.c | |
parent | 59e4779abc25626cb0ab9fa24ccb3223a00db143 (diff) | |
download | cpython-d4624c3331a54506b9c678ad096e56366b66f51d.zip cpython-d4624c3331a54506b9c678ad096e56366b66f51d.tar.gz cpython-d4624c3331a54506b9c678ad096e56366b66f51d.tar.bz2 |
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
Diffstat (limited to 'Objects/longobject.c')
-rw-r--r-- | Objects/longobject.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c index 46efe5f..a932df7 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -175,7 +175,7 @@ PyObject * PyLong_FromLong(long ival) { PyLongObject *v; - unsigned long abs_ival; + unsigned long abs_ival; unsigned long t; /* unsigned so >> doesn't propagate sign bit */ int ndigits = 0; int sign = 1; @@ -183,33 +183,35 @@ PyLong_FromLong(long ival) CHECK_SMALL_INT(ival); if (ival < 0) { - /* if LONG_MIN == -LONG_MAX-1 (true on most platforms) then - ANSI C says that the result of -ival is undefined when ival - == LONG_MIN. Hence the following workaround. */ - abs_ival = (unsigned long)(-1-ival) + 1; + /* negate: can't write this as abs_ival = -ival since that + invokes undefined behaviour when ival is LONG_MIN */ + abs_ival = 0U-(unsigned long)ival; sign = -1; } else { abs_ival = (unsigned long)ival; } - /* Fast path for single-digits ints */ - if (!(ival>>PyLong_SHIFT)) { + /* Fast path for single-digit ints */ + if (!(abs_ival >> PyLong_SHIFT)) { v = _PyLong_New(1); if (v) { 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; } /* 2 digits */ - if (!(ival >> 2*PyLong_SHIFT)) { + if (!(abs_ival >> 2*PyLong_SHIFT)) { v = _PyLong_New(2); if (v) { Py_SIZE(v) = 2*sign; - v->ob_digit[0] = (digit)ival & PyLong_MASK; - v->ob_digit[1] = (digit)(ival >> PyLong_SHIFT); + v->ob_digit[0] = Py_SAFE_DOWNCAST( + abs_ival & PyLong_MASK, unsigned long, digit); + v->ob_digit[1] = Py_SAFE_DOWNCAST( + abs_ival >> PyLong_SHIFT, unsigned long, digit); } return (PyObject*)v; } @@ -226,7 +228,8 @@ PyLong_FromLong(long ival) Py_SIZE(v) = ndigits*sign; t = abs_ival; while (t) { - *p++ = (digit)(t & PyLong_MASK); + *p++ = Py_SAFE_DOWNCAST( + t & PyLong_MASK, unsigned long, digit); t >>= PyLong_SHIFT; } } |