Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r64281:f12e27274ff3
Date: 2013-05-18 12:19 +0200
http://bitbucket.org/pypy/pypy/changeset/f12e27274ff3/

Log:    Fix: I suspect the previous version to create a code of size N^2,
        with N==31 or 63

diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -5,7 +5,6 @@
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.debug import make_sure_not_resized, check_regular_int
 from rpython.rlib.objectmodel import we_are_translated, specialize
-from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib import jit
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper import extregistry
@@ -2109,25 +2108,22 @@
 
 # an RPython trick: this creates a nested sequence of calls that are
 # all inlined into each other, making an unrolled loop.  Moreover the
-# calls are done in the "wrong" order to write it as a regular loop:
+# calls are done in the "wrong" order to be written as a regular loop:
 # the first digit that is append-ed to the builder is the most
 # significant one (corresponding to the innermost call).
[email protected]()
-def _minus_1(x):
-    return x - 1
[email protected](2)
-def _add_decimal_digits(builder, value, ndigits):
+_succ = specialize.memo()(lambda n: n + 1)
[email protected](3)
+def _add_decimal_digits(builder, value, ndigits, digit_index=1):
     assert value >= 0
-    if ndigits > 1:
-        _add_decimal_digits(builder, value // 10, _minus_1(ndigits))
+    if digit_index < ndigits:
+        assert digit_index < DECIMAL_SHIFT
+        _add_decimal_digits(builder, value // 10, ndigits, _succ(digit_index))
         builder.append(chr(ord('0') + value % 10))
     else:
         assert value < 10
         builder.append(chr(ord('0') + value))
 _add_decimal_digits._always_inline_ = True
 
-count_decimal_shift_from_1 = unrolling_iterable(range(1, DECIMAL_SHIFT))
-
 
 def _format_decimal(a, addL=False):
     """ Optimized version of _format(a, BASE10, '', 'L' if addL else ''). """
@@ -2171,15 +2167,12 @@
     assert sizem1 >= 0
 
     # calculate exact length of output string, and allocate
+    decimal_digits_in_last_part = 1
     rem = pout[sizem1]
     tenpow = 10
-    for i in count_decimal_shift_from_1:
-        if rem < tenpow:
-            decimal_digits_in_last_part = i
-            break
+    while rem >= tenpow:
         tenpow *= 10
-    else:
-        decimal_digits_in_last_part = DECIMAL_SHIFT
+        decimal_digits_in_last_part += 1
     strlen = (addL + negative +
               decimal_digits_in_last_part + (sizem1) * DECIMAL_SHIFT)
 
@@ -2189,18 +2182,13 @@
     if negative:
         builder.append('-')
 
-    # pout[size-1]: always produce at least one decimal digit
-    for i in count_decimal_shift_from_1:
-        if i == decimal_digits_in_last_part:
-            _add_decimal_digits(builder, pout[sizem1], i)
-            break
-    else:
-        _add_decimal_digits(builder, pout[sizem1], DECIMAL_SHIFT)
-
-    # pout[0] through pout[size-2] contribute exactly
-    # DECIMAL_SHIFT digits each
-    for i in range(sizem1-1, -1, -1):
-        _add_decimal_digits(builder, pout[i], DECIMAL_SHIFT)
+    # pout[size-1] produces 'decimal_digits_in_last_part' digits.
+    # Then the remaining pout[size-2] through pout[0] contribute exactly
+    # DECIMAL_SHIFT digits each.
+    decimal_digits = decimal_digits_in_last_part
+    for i in range(sizem1, -1, -1):
+        _add_decimal_digits(builder, pout[i], decimal_digits)
+        decimal_digits = DECIMAL_SHIFT
 
     # done
     if addL:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to