summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-07-13 02:59:26 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-07-13 02:59:26 (GMT)
commitfad225f1ba5df5f22328ea5648d1e3d2aa919479 (patch)
treef986a328a9bcbbae5294caeac37e43f7586458c2 /Objects
parenta3253d70bc4a1446f2b088ed9cdc821e75faaf96 (diff)
downloadcpython-fad225f1ba5df5f22328ea5648d1e3d2aa919479.zip
cpython-fad225f1ba5df5f22328ea5648d1e3d2aa919479.tar.gz
cpython-fad225f1ba5df5f22328ea5648d1e3d2aa919479.tar.bz2
long_format(): Easy speedup for output bases that aren't a power of 2 (in
particular, str(long) and repr(long) use base 10, and that gets a factor of 4 speedup). Another factor of 2 can be gotten by refactoring divrem1 to support in-place division, but that started getting messy so I'm leaving that out.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/longobject.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 85b26a3..53ae5ed 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -811,28 +811,45 @@ long_format(PyObject *aa, int base, int addL)
}
}
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. */
+ digit powbase = base; /* powbase == base ** power */
+ int power = 1;
+ for (;;) {
+ unsigned long newpow = powbase * (unsigned long)base;
+ if (newpow >> SHIFT) /* doesn't fit in a digit */
+ break;
+ powbase = (digit)newpow;
+ ++power;
+ }
+
Py_INCREF(a);
do {
+ int ntostore = power;
digit rem;
- PyLongObject *temp = divrem1(a, (digit)base, &rem);
+ PyLongObject *temp = divrem1(a, powbase, &rem);
+ Py_DECREF(a);
if (temp == NULL) {
- Py_DECREF(a);
Py_DECREF(str);
return NULL;
}
- if (rem < 10)
- rem += '0';
- else
- rem += 'A'-10;
- assert(p > PyString_AS_STRING(str));
- *--p = (char) rem;
- Py_DECREF(a);
a = temp;
SIGCHECK({
Py_DECREF(a);
Py_DECREF(str);
return NULL;
})
+ while (--ntostore >= 0) {
+ digit nextrem = (digit)(rem / base);
+ char c = (char)(rem - nextrem * base);
+ assert(p > PyString_AS_STRING(str));
+ c += (c < 10) ? '0' : 'A'-10;
+ *--p = c;
+ rem = nextrem;
+ if (a->ob_size == 0 && rem == 0)
+ break; /* skip leading zeroes */
+ }
} while (ABS(a->ob_size) != 0);
Py_DECREF(a);
}