[issue14339] Optimizing bin, oct and hex

Serhiy Storchaka report at bugs.python.org
Mon Apr 16 11:02:37 CEST 2012


Serhiy Storchaka <storchaka at gmail.com> added the comment:

> I think 'x' would be more appropriate. :-)

Oops. You are right, of cause.

----------
Added file: http://bugs.python.org/file25234/long_to_binary_base_3.patch

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue14339>
_______________________________________
-------------- next part --------------
diff -r 13307eb5bf47 Objects/longobject.c
--- a/Objects/longobject.c	Sat Apr 14 14:20:29 2012 -0500
+++ b/Objects/longobject.c	Mon Apr 16 12:01:24 2012 +0300
@@ -1672,11 +1672,10 @@
 {
     register PyLongObject *a = (PyLongObject *)aa;
     PyObject *v;
-    Py_ssize_t i, sz;
+    Py_ssize_t sz;
     Py_ssize_t size_a;
-    char *p;
-    char sign = '\0';
-    char *buffer;
+    Py_UCS1 *p;
+    int negative;
     int bits;
 
     assert(base == 2 || base == 8 || base == 10 || base == 16);
@@ -1688,6 +1687,7 @@
         return NULL;
     }
     size_a = ABS(Py_SIZE(a));
+    negative = Py_SIZE(a) < 0;
 
     /* Compute a rough upper bound for the length of the string */
     switch (base) {
@@ -1706,31 +1706,37 @@
     }
     /* compute length of output string: allow 2 characters for prefix and
        1 for possible '-' sign. */
-    if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT / sizeof(Py_UCS4)) {
+    if (size_a > (PY_SSIZE_T_MAX - 3) / PyLong_SHIFT) {
         PyErr_SetString(PyExc_OverflowError,
                         "int is too large to format");
         return NULL;
     }
     /* now size_a * PyLong_SHIFT + 3 <= PY_SSIZE_T_MAX, so the RHS below
        is safe from overflow */
-    sz = 3 + (size_a * PyLong_SHIFT + (bits - 1)) / bits;
-    assert(sz >= 0);
-    buffer = PyMem_Malloc(sz);
-    if (buffer == NULL) {
+    if (size_a == 0) {
+        sz = 3;
+    }
+    else {
+        sz = 2 + negative + ((size_a - 1) * PyLong_SHIFT +
+                             bits_in_digit(a->ob_digit[size_a - 1]) +
+                             (bits - 1)) / bits;
+    }
+    v = PyUnicode_New(sz, 'x');
+    if (v == NULL) {
         PyErr_NoMemory();
         return NULL;
     }
-    p = &buffer[sz];
-    if (Py_SIZE(a) < 0)
-        sign = '-';
-
-    if (Py_SIZE(a) == 0) {
+    assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND);
+    p = PyUnicode_1BYTE_DATA(v) + sz;
+
+    if (size_a == 0) {
         *--p = '0';
     }
     else {
         /* JRH: special case for power-of-2 bases */
         twodigits accum = 0;
         int accumbits = 0;              /* # of bits in accum */
+        Py_ssize_t i;
         for (i = 0; i < size_a; ++i) {
             accum |= (twodigits)a->ob_digit[i] << accumbits;
             accumbits += PyLong_SHIFT;
@@ -1739,7 +1745,7 @@
                 char cdigit;
                 cdigit = (char)(accum & (base - 1));
                 cdigit += (cdigit < 10) ? '0' : 'a'-10;
-                assert(p > buffer);
+                assert(p > PyUnicode_1BYTE_DATA(v));
                 *--p = cdigit;
                 accumbits -= bits;
                 accum >>= bits;
@@ -1747,6 +1753,7 @@
         }
     }
 
+    assert(p == PyUnicode_1BYTE_DATA(v) + 2 + negative);
     if (base == 16)
         *--p = 'x';
     else if (base == 8)
@@ -1754,10 +1761,8 @@
     else /* (base == 2) */
         *--p = 'b';
     *--p = '0';
-    if (sign)
-        *--p = sign;
-    v = PyUnicode_DecodeASCII(p, &buffer[sz] - p, NULL);
-    PyMem_Free(buffer);
+    if (negative)
+        *--p = '-';
     return v;
 }
 


More information about the Python-bugs-list mailing list