diff options
author | Tim Peters <tim.peters@gmail.com> | 2001-06-12 01:22:22 (GMT) |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2001-06-12 01:22:22 (GMT) |
commit | 7a3bfc3a472dafc42d20845389eb79db8af0b046 (patch) | |
tree | 5b59ec1db42d4559a21af550c3b068b053ac79d2 /Objects | |
parent | ac4797a12eed2fb5bcc68ae6e768e5ab4ec5b422 (diff) | |
download | cpython-7a3bfc3a472dafc42d20845389eb79db8af0b046.zip cpython-7a3bfc3a472dafc42d20845389eb79db8af0b046.tar.gz cpython-7a3bfc3a472dafc42d20845389eb79db8af0b046.tar.bz2 |
Added q/Q standard (x-platform 8-byte ints) mode in struct module.
This completes the q/Q project.
longobject.c _PyLong_AsByteArray: The original code had a gross bug:
the most-significant Python digit doesn't necessarily have SHIFT
significant bits, and you really need to count how many copies of the sign
bit it has else spurious overflow errors result.
test_struct.py: This now does exhaustive std q/Q testing at, and on both
sides of, all relevant power-of-2 boundaries, both positive and negative.
NEWS: Added brief dict news while I was at it.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/longobject.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c index 92f8b04..fac8bb6 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -364,20 +364,33 @@ _PyLong_AsByteArray(PyLongObject* v, accumbits = 0; carry = do_twos_comp ? 1 : 0; for (i = 0; i < ndigits; ++i) { + unsigned int oldaccumbits = accumbits; twodigits thisdigit = v->ob_digit[i]; if (do_twos_comp) { thisdigit = (thisdigit ^ MASK) + carry; carry = thisdigit >> SHIFT; thisdigit &= MASK; } + if (i < ndigits - 1) + accumbits += SHIFT; + else { + /* The most-significant digit may be partly empty. */ + twodigits bitmask = 1 << (SHIFT - 1); + twodigits signbit = do_twos_comp << (SHIFT - 1); + unsigned int nsignbits = 0; + while ((thisdigit & bitmask) == signbit && bitmask) { + ++nsignbits; + bitmask >>= 1; + signbit >>= 1; + } + accumbits += SHIFT - nsignbits; + } /* Because we're going LSB to MSB, thisdigit is more significant than what's already in accum, so needs to be prepended to accum. */ - accum |= thisdigit << accumbits; - accumbits += SHIFT; + accum |= thisdigit << oldaccumbits; /* Store as many bytes as possible. */ - assert(accumbits >= 8); - do { + while (accumbits >= 8) { if (j >= n) goto Overflow; ++j; @@ -385,13 +398,13 @@ _PyLong_AsByteArray(PyLongObject* v, p += pincr; accumbits -= 8; accum >>= 8; - } while (accumbits >= 8); + } } /* Store the straggler (if any). */ assert(accumbits < 8); assert(carry == 0); /* else do_twos_comp and *every* digit was 0 */ - if (accum) { + if (accumbits > 0) { if (j >= n) goto Overflow; ++j; |