summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-06-12 01:22:22 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-06-12 01:22:22 (GMT)
commit7a3bfc3a472dafc42d20845389eb79db8af0b046 (patch)
tree5b59ec1db42d4559a21af550c3b068b053ac79d2 /Objects
parentac4797a12eed2fb5bcc68ae6e768e5ab4ec5b422 (diff)
downloadcpython-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.c25
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;