]> granicus.if.org Git - python/commitdiff
Issue #28621: Sped up converting int to float by reusing faster bits counting
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 8 Nov 2016 18:34:22 +0000 (20:34 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Tue, 8 Nov 2016 18:34:22 +0000 (20:34 +0200)
implementation.  Patch by Adrian Wielgosik.

Misc/NEWS
Objects/longobject.c

index 94500c240e7a0dd39468456a2f9b2c5be353c9bf..91b97eb6e78f57a87ecf62e4cdf81778930db108 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1
 Core and Builtins
 -----------------
 
+- Issue #28621: Sped up converting int to float by reusing faster bits counting
+  implementation.  Patch by Adrian Wielgosik.
+
 - Issue #28580: Optimize iterating split table values.
   Patch by Xiang Zhang.
 
index 6e569b218dc891c4ea903a4f7db017f1a47f7dc9..10dde726a2951ed9b3e1cd96cc629e12bc5bdb05 100644 (file)
@@ -708,12 +708,33 @@ _PyLong_Sign(PyObject *vv)
     return Py_SIZE(v) == 0 ? 0 : (Py_SIZE(v) < 0 ? -1 : 1);
 }
 
+/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
+   2**k if d is nonzero, else 0. */
+
+static const unsigned char BitLengthTable[32] = {
+    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+};
+
+static int
+bits_in_digit(digit d)
+{
+    int d_bits = 0;
+    while (d >= 32) {
+        d_bits += 6;
+        d >>= 6;
+    }
+    d_bits += (int)BitLengthTable[d];
+    return d_bits;
+}
+
 size_t
 _PyLong_NumBits(PyObject *vv)
 {
     PyLongObject *v = (PyLongObject *)vv;
     size_t result = 0;
     Py_ssize_t ndigits;
+    int msd_bits;
 
     assert(v != NULL);
     assert(PyLong_Check(v));
@@ -724,12 +745,10 @@ _PyLong_NumBits(PyObject *vv)
         if ((size_t)(ndigits - 1) > SIZE_MAX / (size_t)PyLong_SHIFT)
             goto Overflow;
         result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
-        do {
-            ++result;
-            if (result == 0)
-                goto Overflow;
-            msd >>= 1;
-        } while (msd);
+        msd_bits = bits_in_digit(msd);
+        if (SIZE_MAX - msd_bits < result)
+            goto Overflow;
+        result += msd_bits;
     }
     return result;
 
@@ -1414,26 +1433,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
             Py_RETURN_NOTIMPLEMENTED;                   \
     } while(0)
 
-/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
-   2**k if d is nonzero, else 0. */
-
-static const unsigned char BitLengthTable[32] = {
-    0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
-    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
-};
-
-static int
-bits_in_digit(digit d)
-{
-    int d_bits = 0;
-    while (d >= 32) {
-        d_bits += 6;
-        d >>= 6;
-    }
-    d_bits += (int)BitLengthTable[d];
-    return d_bits;
-}
-
 /* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required.  x[0:n]
  * is modified in place, by adding y to it.  Carries are propagated as far as
  * x[m-1], and the remaining carry (0 or 1) is returned.
@@ -5079,7 +5078,8 @@ static PyObject *
 long_bit_length(PyLongObject *v)
 {
     PyLongObject *result, *x, *y;
-    Py_ssize_t ndigits, msd_bits = 0;
+    Py_ssize_t ndigits;
+    int msd_bits;
     digit msd;
 
     assert(v != NULL);
@@ -5090,11 +5090,7 @@ long_bit_length(PyLongObject *v)
         return PyLong_FromLong(0);
 
     msd = v->ob_digit[ndigits-1];
-    while (msd >= 32) {
-        msd_bits += 6;
-        msd >>= 6;
-    }
-    msd_bits += (long)(BitLengthTable[msd]);
+    msd_bits = bits_in_digit(msd);
 
     if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT)
         return PyLong_FromSsize_t((ndigits-1)*PyLong_SHIFT + msd_bits);