[pypy-svn] r45706 - in pypy/branch/pypy-more-rtti-inprogress/rlib: . test

arigo at codespeak.net arigo at codespeak.net
Thu Aug 16 13:01:40 CEST 2007


Author: arigo
Date: Thu Aug 16 13:01:40 2007
New Revision: 45706

Modified:
   pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py
   pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py
Log:
Added rbigint.tolonglong().


Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rlib/rbigint.py	Thu Aug 16 13:01:40 2007
@@ -1,4 +1,5 @@
-from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong, ovfcheck
+from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong
+from pypy.rlib.rarithmetic import ovfcheck, r_longlong
 
 import math, sys
 
@@ -174,6 +175,9 @@
     def toint(self):
         return _AsLong(self)
 
+    def tolonglong(self):
+        return _AsLongLong(self)
+
     def tobool(self):
         return self.sign != 0
 
@@ -194,16 +198,7 @@
     def toulonglong(self):
         if self.sign == -1:
             raise ValueError("cannot convert negative integer to unsigned int")
-        x = r_ulonglong(0)
-        i = len(self.digits) - 1
-        while i >= 0:
-            prev = x
-            x = (x << SHIFT) + self.digits[i]
-            if (x >> SHIFT) != prev:
-                    raise OverflowError(
-                        "long int too large to convert to unsigned long long int")
-            i -= 1
-        return x
+        return _AsULonglong_ignore_sign(self)
 
     def tofloat(self):
         return _AsDouble(self)
@@ -1557,6 +1552,39 @@
         raise OverflowError
     return intmask(x * sign)
 
+ULONGLONG_BOUND = r_ulonglong(1L << (r_longlong.BITS-1))
+LONGLONG_MIN = r_longlong(-(1L << (r_longlong.BITS-1)))
+
+def _AsLongLong(v):
+    """
+    Get a r_longlong integer from a bigint object.
+    Raises OverflowError if overflow occurs.
+    """
+    x = _AsULonglong_ignore_sign(v)
+    # grr grr grr
+    if x >= ULONGLONG_BOUND:
+        if x == ULONGLONG_BOUND and v.sign < 0:
+            x = LONGLONG_MIN
+        else:
+            raise OverflowError
+    else:
+        x = r_longlong(x)
+        if v.sign < 0:
+            x = -x
+    return x
+
+def _AsULonglong_ignore_sign(v):
+    x = r_ulonglong(0)
+    i = len(v.digits) - 1
+    while i >= 0:
+        prev = x
+        x = (x << SHIFT) + v.digits[i]
+        if (x >> SHIFT) != prev:
+                raise OverflowError(
+                    "long int too large to convert to unsigned long long int")
+        i -= 1
+    return x
+
 def _hash(v):
     # This is designed so that Python ints and longs with the
     # same value hash to the same value, otherwise comparisons

Modified: pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py
==============================================================================
--- pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py	(original)
+++ pypy/branch/pypy-more-rtti-inprogress/rlib/test/test_rbigint.py	Thu Aug 16 13:01:40 2007
@@ -3,7 +3,7 @@
 from random import random, randint
 from pypy.rlib.rbigint import rbigint, SHIFT, MASK
 from pypy.rlib import rbigint as lobj
-from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib.rarithmetic import r_uint, r_longlong
 import operator, sys
 
 class TestRLong(object):
@@ -408,7 +408,16 @@
         ret = lobj._k_lopsided_mul(f1, f2)
         assert ret.tolong() == f1.tolong() * f2.tolong()
 
-
+    def test_longlong(self):
+        max = 1L << (r_longlong.BITS-1)
+        f1 = rbigint.fromlong(max-1)    # fits in r_longlong
+        f2 = rbigint.fromlong(-max)     # fits in r_longlong
+        f3 = rbigint.fromlong(max)      # overflows
+        f4 = rbigint.fromlong(-max-1)   # overflows
+        assert f1.tolonglong() == max-1
+        assert f2.tolonglong() == -max
+        py.test.raises(OverflowError, f3.tolonglong)
+        py.test.raises(OverflowError, f4.tolonglong)
 
 
 class TestTranslatable(object):



More information about the Pypy-commit mailing list