diff options
author | Mark Dickinson <dickinsm@gmail.com> | 2009-09-17 19:37:28 (GMT) |
---|---|---|
committer | Mark Dickinson <dickinsm@gmail.com> | 2009-09-17 19:37:28 (GMT) |
commit | 2e72b0d603b81a38ecbcb9c257aa3ba202ae7b76 (patch) | |
tree | ed1ea7256baf3abef15dd050073032908419a24e /Objects/longobject.c | |
parent | 2c54e693b62fe78a5fb30c54dd7222990ad29650 (diff) | |
download | cpython-2e72b0d603b81a38ecbcb9c257aa3ba202ae7b76.zip cpython-2e72b0d603b81a38ecbcb9c257aa3ba202ae7b76.tar.gz cpython-2e72b0d603b81a38ecbcb9c257aa3ba202ae7b76.tar.bz2 |
Add some more module maintainers.
Diffstat (limited to 'Objects/longobject.c')
-rw-r--r-- | Objects/longobject.c | 148 |
1 files changed, 44 insertions, 104 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c index 9f414ca..814ef64 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1775,9 +1775,9 @@ _PyLong_Format(PyObject *aa, int base) Py_ssize_t i, sz; Py_ssize_t size_a; Py_UNICODE *p; - int bits; - char sign = '\0'; + int bits, negative; + assert(base == 2 || base == 8 || base == 10 || base == 16); if (base == 10) return long_to_decimal_string((PyObject *)a); @@ -1785,23 +1785,34 @@ _PyLong_Format(PyObject *aa, int base) PyErr_BadInternalCall(); return NULL; } - assert(base >= 2 && base <= 36); size_a = ABS(Py_SIZE(a)); + negative = Py_SIZE(a) < 0; /* Compute a rough upper bound for the length of the string */ - i = base; - bits = 0; - while (i > 1) { - ++bits; - i >>= 1; + switch (base) { + case 2: + bits = 1; + break; + case 8: + bits = 3; + break; + case 16: + bits = 4; + break; + default: + assert(0); /* never get here */ } + + /* length of string required: +1 for negative sign, +2 for prefix */ i = 5; /* ensure we don't get signed overflow in sz calculation */ - if (size_a > (PY_SSIZE_T_MAX - i) / PyLong_SHIFT) { + if (size_a > (PY_SSIZE_T_MAX - 4) / PyLong_SHIFT) { PyErr_SetString(PyExc_OverflowError, "int is too large to format"); return NULL; } + sz = 3 + negative + (size_a * PyLong_SHIFT - 1) / bits; + sz = i + 1 + (size_a * PyLong_SHIFT - 1) / bits; assert(sz >= 0); str = PyUnicode_FromUnicode(NULL, sz); @@ -1809,112 +1820,41 @@ _PyLong_Format(PyObject *aa, int base) return NULL; p = PyUnicode_AS_UNICODE(str) + sz; *p = '\0'; - if (Py_SIZE(a) < 0) - sign = '-'; if (Py_SIZE(a) == 0) { *--p = '0'; } - else if ((base & (base - 1)) == 0) { - /* JRH: special case for power-of-2 bases */ - twodigits accum = 0; - int accumbits = 0; /* # of bits in accum */ - int basebits = 1; /* # of bits in base-1 */ - i = base; - while ((i >>= 1) > 1) - ++basebits; - - for (i = 0; i < size_a; ++i) { - accum |= (twodigits)a->ob_digit[i] << accumbits; - accumbits += PyLong_SHIFT; - assert(accumbits >= basebits); - do { - char cdigit = (char)(accum & (base - 1)); - cdigit += (cdigit < 10) ? '0' : 'a'-10; - assert(p > PyUnicode_AS_UNICODE(str)); - *--p = cdigit; - accumbits -= basebits; - accum >>= basebits; - } while (i < size_a-1 ? accumbits >= basebits : - accum > 0); - } - } - else { - /* Not 0, and base not a power of 2. Divide repeatedly by - base, but for speed use the highest power of base that - fits in a digit. */ - Py_ssize_t size = size_a; - digit *pin = a->ob_digit; - PyLongObject *scratch; - /* powbasw <- largest power of base that fits in a digit. */ - digit powbase = base; /* powbase == base ** power */ - int power = 1; - for (;;) { - twodigits newpow = powbase * (twodigits)base; - if (newpow >> PyLong_SHIFT) - /* doesn't fit in a digit */ - break; - powbase = (digit)newpow; - ++power; - } - - /* Get a scratch area for repeated division. */ - scratch = _PyLong_New(size); - if (scratch == NULL) { - Py_DECREF(str); - return NULL; - } + assert((base & (base-1)) = 0); + /* JRH: special case for power-of-2 bases */ + twodigits accum = 0; + int accumbits = 0; /* # of bits in accum */ + int basebits = 1; /* # of bits in base-1 */ + i = base; + while ((i >>= 1) > 1) + ++basebits; - /* Repeatedly divide by powbase. */ + for (i = 0; i < size_a; ++i) { + accum |= (twodigits)a->ob_digit[i] << accumbits; + accumbits += PyLong_SHIFT; + assert(accumbits >= basebits); do { - int ntostore = power; - digit rem = inplace_divrem1(scratch->ob_digit, - pin, size, powbase); - pin = scratch->ob_digit; /* no need to use a again */ - if (pin[size - 1] == 0) - --size; - SIGCHECK({ - Py_DECREF(scratch); - Py_DECREF(str); - return NULL; - }) - - /* Break rem into digits. */ - assert(ntostore > 0); - do { - digit nextrem = (digit)(rem / base); - char c = (char)(rem - nextrem * base); - assert(p > PyUnicode_AS_UNICODE(str)); - c += (c < 10) ? '0' : 'a'-10; - *--p = c; - rem = nextrem; - --ntostore; - /* Termination is a bit delicate: must not - store leading zeroes, so must get out if - remaining quotient and rem are both 0. */ - } while (ntostore && (size || rem)); - } while (size != 0); - Py_DECREF(scratch); + char cdigit = (char)(accum & (base - 1)); + cdigit += (cdigit < 10) ? '0' : 'a'-10; + assert(p > PyUnicode_AS_UNICODE(str)); + *--p = cdigit; + accumbits -= basebits; + accum >>= basebits; + } while (i < size_a-1 ? accumbits >= basebits : + accum > 0); } - if (base == 16) { + if (base == 16) *--p = 'x'; - *--p = '0'; - } - else if (base == 8) { + else if (base == 8) *--p = 'o'; - *--p = '0'; - } - else if (base == 2) { + else /* base == 2 */ *--p = 'b'; - *--p = '0'; - } - else if (base != 10) { - *--p = '#'; - *--p = '0' + base%10; - if (base > 10) - *--p = '0' + base/10; - } + *--p = '0'; if (sign) *--p = sign; if (p != PyUnicode_AS_UNICODE(str)) { |