[pypy-svn] r14316 - pypy/dist/pypy/objspace/std

tismer at codespeak.net tismer at codespeak.net
Tue Jul 5 22:30:38 CEST 2005


Author: tismer
Date: Tue Jul  5 22:30:37 2005
New Revision: 14316

Modified:
   pypy/dist/pypy/objspace/std/longobject.py
Log:
formatting seems to work
(the cpython test takes hours, can't wait)

Modified: pypy/dist/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/longobject.py	(original)
+++ pypy/dist/pypy/objspace/std/longobject.py	Tue Jul  5 22:30:37 2005
@@ -63,7 +63,7 @@
 
     def _setshort(self, index, short):
         a = self.digits[index // 2]
-        ##!!assert isinstance(short, r_uint)
+        assert isinstance(short, r_uint)
         assert short & SHORT_MASK == short
         if index % 2 == 0:
             self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short
@@ -135,8 +135,8 @@
         raise OperationError(space.w_OverflowError,
                              space.wrap("long int too large to convert to float"))
 
-def long__Float(space, w_floatobj): #YYYYYY
-    return W_LongObject(space, *args_from_long(long(w_floatobj.floatval)))
+def long__Float(space, w_floatobj):
+    return _FromDouble(space, w_floatobj.floatval)
 
 def int_w__Long(space, w_value):
     if len(w_value.digits) == 1:
@@ -156,11 +156,11 @@
     raise OperationError(space.w_OverflowError,
                          space.wrap("long int too large to convert to unsigned int"))    
 
-def repr__Long(space, w_long): #YYYYYY
-    return space.wrap(repr(w_long.longval()))
+def repr__Long(space, w_long):
+    return space.wrap(_format(w_long, 10, True))
 
-def str__Long(space, w_long): #YYYYYY
-    return space.wrap(str(w_long.longval()))
+def str__Long(space, w_long):
+    return space.wrap(_format(w_long, 10, False))
 
 def eq__Long_Long(space, w_long1, w_long2):
     if (w_long1.sign != w_long2.sign or
@@ -617,14 +617,16 @@
     z._normalize()
     return z
 
-def _inplace_divrem1(pout, pin, n):
+def _inplace_divrem1(pout, pin, n, size=0):
     """
     Divide long pin by non-zero digit n, storing quotient
     in pout, and returning the remainder. It's OK for pin == pout on entry.
     """
     rem = r_uint(0)
     assert n > 0 and n <= SHORT_MASK
-    size = len(pin.digits) * 2 - 1
+    if not size:
+        size = len(pin.digits) * 2
+    size -= 1
     while size >= 0:
         rem = (rem << SHORT_BIT) + pin._getshort(size)
         hi = rem // n
@@ -774,7 +776,7 @@
             vj = r_uint(0)
         else:
             vj = v._getshort(j)
-        carry = r_suint(0) # note: this must hold two digits and sign!
+        carry = r_suint(0) # note: this must hold two digits and a sign!
 
         if vj == w._getshort(size_w-1):
             q = r_uint(SHORT_MASK)
@@ -792,7 +794,7 @@
                                 ) << SHORT_BIT)
                 + v._getshort(j-2)):
             q -= 1
-
+            print '***', q##!!
         i = 0
         while i < size_w and i+k < size_v:
             z = w._getshort(i) * q
@@ -809,10 +811,10 @@
             v._setshort(i+k, r_uint(0))
 
         if carry == 0:
-            a._setshort(k, q)
+            a._setshort(k, q & SHORT_MASK)
         else:
             assert carry == -1
-            a._setshort(k, q-1)
+            a._setshort(k, (q-1) & SHORT_MASK)
 
             carry = r_suint(0)
             i = 0
@@ -999,3 +1001,147 @@
         one = W_LongObject(space, [r_uint(1)], 1)
         div = sub__Long_Long(space, div, one)
     return div, mod
+
+
+def _format(a, base, addL):
+    """
+    Convert a long int object to a string, using a given conversion base.
+    Return a string object.
+    If base is 8 or 16, add the proper prefix '0' or '0x'.
+    """
+    size_a = len(a.digits) * 2
+    if a._getshort(size_a-1) == 0:
+        size_a -= 1
+
+    assert base >= 2 and base <= 36
+
+    sign = chr(0)
+
+    # Compute a rough upper bound for the length of the string
+    i = base
+    bits = 0
+    while i > 1:
+        bits += 1
+        i >>= 1
+    i = 5 + int(bool(addL)) + (size_a*LONG_BIT + bits-1) // bits
+    s = [chr(0)] * i
+    p = i
+    if addL:
+        p -= 1
+        s[p] = 'L'
+    if a.sign < 0:
+        sign = '-'
+
+    if a.sign == 0:
+        p -= 1
+        s[p] = '0'
+    elif (base & (base - 1)) == 0:
+        # JRH: special case for power-of-2 bases
+        accum = r_uint(0)
+        accumbits = 0  # # of bits in accum 
+        basebits = 1   # # of bits in base-1
+        i = base
+        while 1:
+            i >>= 1
+            if i <= 1:
+                break
+            basebits += 1
+
+        for i in range(size_a):
+            accum |= a._getshort(i) << accumbits
+            accumbits += SHORT_BIT
+            assert accumbits >= basebits
+            while 1:
+                cdigit = accum & (base - 1)
+                if cdigit < 10:
+                    cdigit += ord('0')
+                else:
+                    cdigit += ord('A') - 10
+                assert p > 0
+                p -= 1
+                s[p] = chr(cdigit)
+                accumbits -= basebits
+                accum >>= basebits
+                if i < size_a - 1:
+                    if accumbits < basebits:
+                        break
+                else:
+                    if accum <= 0:
+                        break
+    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.
+        size = size_a
+        pin = a # just for similarity to C source which uses the array
+        # powbasw <- largest power of base that fits in a digit.
+        powbase = base  # powbase == base ** power
+        power = 1
+        while 1:
+            newpow = powbase * r_uint(base)
+            if newpow >> SHORT_BIT:  # doesn't fit in a digit
+                break
+            powbase = newpow
+            power += 1
+
+        # Get a scratch area for repeated division.
+        digitpairs = (size + 1) // 2
+        scratch = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1)
+
+        # Repeatedly divide by powbase.
+        while 1:
+            ntostore = power
+            rem = _inplace_divrem1(scratch, pin, powbase, size)
+            pin = scratch  # no need to use a again
+            if pin._getshort(size - 1) == 0:
+                size -= 1
+
+            # Break rem into digits.
+            assert ntostore > 0
+            while 1:
+                nextrem = rem // base
+                c = rem - nextrem * base
+                assert p > 0
+                if c < 10:
+                    c += ord('0')
+                else:
+                    c += ord('A') - 10
+                p -= 1
+                s[p] = chr(c)
+                rem = nextrem
+                ntostore -= 1
+                # Termination is a bit delicate:  must not
+                # store leading zeroes, so must get out if
+                # remaining quotient and rem are both 0.
+                if not (ntostore and (size or rem)):
+                    break
+            if size == 0:
+                break
+
+    if base == 8:
+        if size_a != 0:
+            p -= 1
+            s[p] = '0'
+    elif base == 16:
+        p -= 1
+        s[p] ='x'
+        p -= 1
+        s[p] = '0'
+    elif base != 10:
+        p -= 1
+        s[p] = '#'
+        p -= 1
+        s[p] = chr(ord('0') + base % 10)
+        if base > 10:
+            p -= 1
+            s[p] = chr(ord('0') + base // 10)
+    if sign:
+        p -= 1
+        s[p] = sign
+
+    if p == 0:
+        return ''.join(s)
+    else:
+        return ''.join(s[p:])
+
+



More information about the Pypy-commit mailing list