]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
long_format(): Easy speedup for output bases that aren't a power of 2 (in
authorTim Peters <tim.peters@gmail.com>
Fri, 13 Jul 2001 02:59:26 +0000 (02:59 +0000)
committerTim Peters <tim.peters@gmail.com>
Fri, 13 Jul 2001 02:59:26 +0000 (02:59 +0000)
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.

Objects/longobject.c

index 85b26a3fe31b11e3dbb6c2a4b7fa6a772f561672..53ae5ed6bd237ffa39e995c96d083c22f37d7c36 100644 (file)
@@ -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);
        }