[pypy-commit] pypy bigint-with-int-ops: Support Long Int compare ops

stian noreply at buildbot.pypy.org
Fri Aug 9 00:11:46 CEST 2013


Author: stian
Branch: bigint-with-int-ops
Changeset: r66025:7500e0cc59b1
Date: 2013-08-09 00:10 +0200
http://bitbucket.org/pypy/pypy/changeset/7500e0cc59b1/

Log:	Support Long Int compare ops

diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -155,17 +155,17 @@
     return space.newbool(w_long1.num.ge(w_long2.num))
 
 def lt__Long_Int(space, w_long1, w_int2):
-    return space.newbool(w_long1.num.lt(rbigint.fromint(w_int2.intval)))
+    return space.newbool(w_long1.num.int_lt(w_int2.intval))
 def le__Long_Int(space, w_long1, w_int2):
-    return space.newbool(w_long1.num.le(rbigint.fromint(w_int2.intval)))
+    return space.newbool(w_long1.num.int_le(w_int2.intval))
 def eq__Long_Int(space, w_long1, w_int2):
-    return space.newbool(w_long1.num.eq(rbigint.fromint(w_int2.intval)))
+    return space.newbool(w_long1.num.int_eq(w_int2.intval))
 def ne__Long_Int(space, w_long1, w_int2):
-    return space.newbool(w_long1.num.ne(rbigint.fromint(w_int2.intval)))
+    return space.newbool(w_long1.num.int_ne(w_int2.intval))
 def gt__Long_Int(space, w_long1, w_int2):
-    return space.newbool(w_long1.num.gt(rbigint.fromint(w_int2.intval)))
+    return space.newbool(w_long1.num.int_gt(w_int2.intval))
 def ge__Long_Int(space, w_long1, w_int2):
-    return space.newbool(w_long1.num.ge(rbigint.fromint(w_int2.intval)))
+    return space.newbool(w_long1.num.int_ge(w_int2.intval))
 
 def lt__Int_Long(space, w_int1, w_long2):
     return space.newbool(rbigint.fromint(w_int1.intval).lt(w_long2.num))
diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -499,10 +499,27 @@
             i += 1
         return True
 
+    @jit.elidable
+    def int_eq(self, other):
+        """ eq with int """
+        
+        if not int_in_valid_range(other):
+            # Fallback to Long. 
+            return self.eq(rbigint.fromint(other))
+
+        if self.numdigits() > 1:
+            return False
+
+        return (self.sign * self.digit(0)) == other
+
     @jit.look_inside
     def ne(self, other):
         return not self.eq(other)
 
+    @jit.look_inside
+    def int_ne(self, other):
+        return not self.int_eq(other)
+
     @jit.elidable
     def lt(self, other):
         if self.sign > other.sign:
@@ -538,18 +555,67 @@
             i -= 1
         return False
 
+    @jit.elidable
+    def int_lt(self, other):
+        """ lt where other is an int """
+
+        if not int_in_valid_range(other):
+            # Fallback to Long.
+            return self.lt(rbigint.fromint(other))
+
+        osign = 1
+        if other == 0:
+            osign = 0
+        elif other < 0:
+            osign = -1
+ 
+        if self.sign > osign:
+            return False
+        elif self.sign < osign:
+            return True
+
+        digits = self.numdigits()
+        
+        if digits > 1:
+            if osign == 1:
+                return False
+            else:
+                return True
+
+        d1 = self.sign * self.digit(0)
+        if d1 < other:
+            return True
+        return False
+
     @jit.look_inside
     def le(self, other):
         return not other.lt(self)
 
     @jit.look_inside
+    def int_le(self, other):
+        # Alternative that might be faster, reimplant this. as a check with other + 1. But we got to check for overflow
+        # or reduce valid range.
+
+        if self.int_eq(other):
+            return True
+        return self.int_lt(other)
+
+    @jit.look_inside
     def gt(self, other):
         return other.lt(self)
 
     @jit.look_inside
+    def int_gt(self, other):
+        return not self.int_le(other)
+
+    @jit.look_inside
     def ge(self, other):
         return not self.lt(other)
 
+    @jit.look_inside
+    def int_ge(self, other):
+        return not self.int_lt(other)
+
     @jit.elidable
     def hash(self):
         return _hash(self)
diff --git a/rpython/rlib/test/test_rbigint.py b/rpython/rlib/test/test_rbigint.py
--- a/rpython/rlib/test/test_rbigint.py
+++ b/rpython/rlib/test/test_rbigint.py
@@ -375,6 +375,13 @@
                 f2 = rbigint.fromlong(y)
                 assert (x < y) ==  f1.lt(f2)
 
+    def test_int_lt(self):
+        val = [0, 0x11111111, 0x11111112]
+        for x in gen_signs(val):
+            for y in gen_signs(val):
+                f1 = rbigint.fromlong(x)
+                assert (x < y) ==  f1.int_lt(y)
+
     def test_order(self):
         f6 = rbigint.fromint(6)
         f7 = rbigint.fromint(7)
@@ -383,6 +390,14 @@
         assert (f6.gt(f6), f6.gt(f7), f7.gt(f6)) == (0,0,1)
         assert (f6.ge(f6), f6.ge(f7), f7.ge(f6)) == (1,0,1)
 
+    def test_int_order(self):
+        f6 = rbigint.fromint(6)
+        f7 = rbigint.fromint(7)
+        assert (f6.int_lt(6), f6.int_lt(7), f7.int_lt(6)) == (0,1,0)
+        assert (f6.int_le(6), f6.int_le(7), f7.int_le(6)) == (1,1,0)
+        assert (f6.int_gt(6), f6.int_gt(7), f7.int_gt(6)) == (0,0,1)
+        assert (f6.int_ge(6), f6.int_ge(7), f7.int_ge(6)) == (1,0,1)
+
     def test_int_conversion(self):
         f1 = rbigint.fromlong(12332)
         f2 = rbigint.fromint(12332)


More information about the pypy-commit mailing list