[pypy-svn] r69505 - in pypy/branch/float-comparison/pypy/rlib: . test

arigo at codespeak.net arigo at codespeak.net
Sun Nov 22 17:44:30 CET 2009


Author: arigo
Date: Sun Nov 22 17:44:29 2009
New Revision: 69505

Modified:
   pypy/branch/float-comparison/pypy/rlib/rbigint.py
   pypy/branch/float-comparison/pypy/rlib/test/test_rbigint.py
Log:
Add the argument 'rounding_towards' to rbigint.fromfloat().
Add tests.  Also make constants ZERO and ONE global constants.


Modified: pypy/branch/float-comparison/pypy/rlib/rbigint.py
==============================================================================
--- pypy/branch/float-comparison/pypy/rlib/rbigint.py	(original)
+++ pypy/branch/float-comparison/pypy/rlib/rbigint.py	Sun Nov 22 17:44:29 2009
@@ -75,7 +75,7 @@
             sign = 1
             ival = r_uint(intval)
         else:
-            return rbigint()
+            return ZERO
         # Count the number of Python digits.
         # We used to pick 5 ("big enough for anything"), but that's a
         # waste of time and space given that 5*15 = 75 bits are rarely
@@ -97,35 +97,43 @@
 
     def frombool(b):
         if b:
-            return rbigint([1], 1)
-        return rbigint()
+            return ONE
+        return ZERO
     frombool = staticmethod(frombool)
 
     def fromlong(l):
         return rbigint(*args_from_long(l))
     fromlong = staticmethod(fromlong)
 
-    def fromfloat(dval):
+    def fromfloat(dval, rounding_towards=0):
         """ Create a new bigint object from a float """
-        neg = 0
+        neg = False
         if isinf(dval):
             raise OverflowError
         if dval < 0.0:
-            neg = 1
+            neg = True
             dval = -dval
         frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0
         if expo <= 0:
-            return rbigint()
-        ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result
-        v = rbigint([0] * ndig, 1)
-        frac = math.ldexp(frac, (expo-1) % SHIFT + 1)
-        for i in range(ndig-1, -1, -1):
-            bits = mask_digit(int(frac))
-            v._setdigit(i, bits)
-            frac -= float(bits)
-            frac = math.ldexp(frac, SHIFT)
-        if neg:
-            v.sign = -1
+            v = ZERO
+        else:
+            ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result
+            v = rbigint([0] * ndig, 1)
+            frac = math.ldexp(frac, (expo-1) % SHIFT + 1)
+            for i in range(ndig-1, -1, -1):
+                bits = mask_digit(int(frac))
+                v._setdigit(i, bits)
+                frac -= float(bits)
+                frac = math.ldexp(frac, SHIFT)
+            if neg:
+                v.sign = -1
+        if rounding_towards != 0 and frac != 0.0:
+            if not neg:
+                if rounding_towards > 0:
+                    v = v.add(ONE)
+            else:
+                if rounding_towards < 0:
+                    v = v.sub(ONE)
         return v
     fromfloat = staticmethod(fromfloat)
 
@@ -352,7 +360,7 @@
         div, mod = _divrem(v, w)
         if mod.sign * w.sign == -1:
             mod = mod.add(w)
-            div = div.sub(rbigint([1], 1))
+            div = div.sub(ONE)
         return div, mod
 
     def pow(a, b, c=None):
@@ -384,7 +392,7 @@
             # if modulus == 1:
             #     return 0
             if c._numdigits() == 1 and c.digits[0] == 1:
-                return rbigint()
+                return ZERO
 
             # if base < 0:
             #     base = base % modulus
@@ -396,7 +404,7 @@
         # At this point a, b, and c are guaranteed non-negative UNLESS
         # c is NULL, in which case a may be negative. */
 
-        z = rbigint([1], 1)
+        z = ONE
 
         # python adaptation: moved macros REDUCE(X) and MULT(X, Y, result)
         # into helper function result = _help_mult(x, y, c)
@@ -416,8 +424,8 @@
         else:
             # Left-to-right 5-ary exponentiation (HAC Algorithm 14.82)
             # z still holds 1L
-            table = [z] * 32
-            table[0] = z;
+            table = [None] * 32
+            table[0] = z
             for i in range(1, 32):
                 table[i] = _help_mult(table[i-1], a, c)
             i = b._numdigits() - 1
@@ -444,7 +452,7 @@
         return rbigint(self.digits, abs(self.sign))
 
     def invert(self): #Implement ~x as -(x + 1)
-        return self.add(rbigint([1], 1)).neg()
+        return self.add(ONE).neg()
 
     def lshift(self, int_other):
         if int_other < 0:
@@ -490,7 +498,7 @@
         wordshift = int_other // SHIFT
         newsize = self._numdigits() - wordshift
         if newsize <= 0:
-            return rbigint()
+            return ZERO
 
         loshift = int_other % SHIFT
         hishift = SHIFT - loshift
@@ -565,6 +573,9 @@
 
 # Helper Functions
 
+ZERO = rbigint()
+ONE = rbigint([1], 1)
+
 
 def _help_mult(x, y, c):
     """

Modified: pypy/branch/float-comparison/pypy/rlib/test/test_rbigint.py
==============================================================================
--- pypy/branch/float-comparison/pypy/rlib/test/test_rbigint.py	(original)
+++ pypy/branch/float-comparison/pypy/rlib/test/test_rbigint.py	Sun Nov 22 17:44:29 2009
@@ -172,6 +172,32 @@
         x = 12345.6789e200
         x *= x
         assert raises(OverflowError, rbigint.fromfloat, x)
+        #
+        f1 = rbigint.fromfloat(12345.0, rounding_towards=-1)
+        assert f1.toint() == 12345
+        f1 = rbigint.fromfloat(12345.0, rounding_towards=0)
+        assert f1.toint() == 12345
+        f1 = rbigint.fromfloat(12345.0, rounding_towards=+1)
+        assert f1.toint() == 12345
+        f1 = rbigint.fromfloat(-12345.0, rounding_towards=-1)
+        assert f1.toint() == -12345
+        f1 = rbigint.fromfloat(-12345.0, rounding_towards=0)
+        assert f1.toint() == -12345
+        f1 = rbigint.fromfloat(-12345.0, rounding_towards=+1)
+        assert f1.toint() == -12345
+        #
+        f1 = rbigint.fromfloat(12345.6, rounding_towards=-1)
+        assert f1.toint() == 12345
+        f1 = rbigint.fromfloat(12345.6, rounding_towards=0)
+        assert f1.toint() == 12345
+        f1 = rbigint.fromfloat(12345.6, rounding_towards=+1)
+        assert f1.toint() == 12346   # here!
+        f1 = rbigint.fromfloat(-12345.6, rounding_towards=-1)
+        assert f1.toint() == -12346  # here!
+        f1 = rbigint.fromfloat(-12345.6, rounding_towards=0)
+        assert f1.toint() == -12345
+        f1 = rbigint.fromfloat(-12345.6, rounding_towards=+1)
+        assert f1.toint() == -12345
 
     def test_eq(self):
         x = 5858393919192332223L



More information about the Pypy-commit mailing list