[pypy-commit] pypy default: Use int with rbigint operations. This provide a upto 25% speedup on such operations, and a minor 5% speedup on pidigits.

stian noreply at buildbot.pypy.org
Sat May 2 02:38:15 CEST 2015


Author: stian
Branch: 
Changeset: r76972:f01fd6fb3a45
Date: 2015-05-02 02:37 +0200
http://bitbucket.org/pypy/pypy/changeset/f01fd6fb3a45/

Log:	Use int with rbigint operations. This provide a upto 25% speedup on
	such operations, and a minor 5% speedup on pidigits.

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
@@ -350,8 +350,13 @@
 
     def _make_descr_cmp(opname):
         op = getattr(rbigint, opname)
-        @delegate_other
+        intop = getattr(rbigint, "int_" + opname)
+
         def descr_impl(self, space, w_other):
+            if isinstance(w_other, W_AbstractIntObject):
+                return space.newbool(intop(self.num, w_other.int_w(space)))
+            elif not isinstance(w_other, W_AbstractLongObject):
+                return space.w_NotImplemented
             return space.newbool(op(self.num, w_other.asbigint()))
         return func_with_new_name(descr_impl, "descr_" + opname)
 
@@ -362,7 +367,7 @@
     descr_gt = _make_descr_cmp('gt')
     descr_ge = _make_descr_cmp('ge')
 
-    def _make_generic_descr_binop(opname):
+    def _make_generic_descr_binop_noncommutative(opname):
         methname = opname + '_' if opname in ('and', 'or') else opname
         descr_rname = 'descr_r' + opname
         op = getattr(rbigint, methname)
@@ -372,33 +377,65 @@
         def descr_binop(self, space, w_other):
             return W_LongObject(op(self.num, w_other.asbigint()))
 
-        if opname in COMMUTATIVE_OPS:
-            @func_renamer(descr_rname)
-            def descr_rbinop(self, space, w_other):
-                return descr_binop(self, space, w_other)
-        else:
-            @func_renamer(descr_rname)
-            @delegate_other
-            def descr_rbinop(self, space, w_other):
-                return W_LongObject(op(w_other.asbigint(), self.num))
+        @func_renamer(descr_rname)
+        @delegate_other
+        def descr_rbinop(self, space, w_other):
+            return W_LongObject(op(w_other.asbigint(), self.num))
 
         return descr_binop, descr_rbinop
 
+    def _make_generic_descr_binop(opname):
+        if opname not in COMMUTATIVE_OPS:
+            raise Exception("Not supported")
+            
+        methname = opname + '_' if opname in ('and', 'or') else opname
+        descr_rname = 'descr_r' + opname
+        op = getattr(rbigint, methname)
+        intop = getattr(rbigint, "int_" + methname)
+        
+        @func_renamer('descr_' + opname)
+        def descr_binop(self, space, w_other):
+            if isinstance(w_other, W_AbstractIntObject):
+                return W_LongObject(intop(self.num, w_other.int_w(space)))
+            elif not isinstance(w_other, W_AbstractLongObject):
+                return space.w_NotImplemented
+
+            return W_LongObject(op(self.num, w_other.asbigint()))
+
+        @func_renamer(descr_rname)
+        def descr_rbinop(self, space, w_other):
+            if isinstance(w_other, W_AbstractIntObject):
+                return W_LongObject(intop(self.num, w_other.int_w(space)))
+            elif not isinstance(w_other, W_AbstractLongObject):
+                return space.w_NotImplemented
+
+            return W_LongObject(op(w_other.asbigint(), self.num))
+
+        return descr_binop, descr_rbinop
+        
     descr_add, descr_radd = _make_generic_descr_binop('add')
-    descr_sub, descr_rsub = _make_generic_descr_binop('sub')
+    descr_sub, descr_rsub = _make_generic_descr_binop_noncommutative('sub')
     descr_mul, descr_rmul = _make_generic_descr_binop('mul')
     descr_and, descr_rand = _make_generic_descr_binop('and')
     descr_or, descr_ror = _make_generic_descr_binop('or')
     descr_xor, descr_rxor = _make_generic_descr_binop('xor')
 
-    def _make_descr_binop(func):
+    def _make_descr_binop(func, int_func=None):
         opname = func.__name__[1:]
 
-        @delegate_other
-        @func_renamer('descr_' + opname)
-        def descr_binop(self, space, w_other):
-            return func(self, space, w_other)
-
+        if int_func:
+            @func_renamer('descr_' + opname)
+            def descr_binop(self, space, w_other):
+                if isinstance(w_other, W_AbstractIntObject):
+                    return int_func(self, space, w_other.int_w(space))
+                elif not isinstance(w_other, W_AbstractLongObject):
+                    return space.w_NotImplemented
+                return func(self, space, w_other)
+        else:
+            @delegate_other
+            @func_renamer('descr_' + opname)
+            def descr_binop(self, space, w_other):
+                return func(self, space, w_other)
         @delegate_other
         @func_renamer('descr_r' + opname)
         def descr_rbinop(self, space, w_other):
@@ -417,7 +454,13 @@
         except OverflowError:   # b too big
             raise oefmt(space.w_OverflowError, "shift count too large")
         return W_LongObject(self.num.lshift(shift))
-    descr_lshift, descr_rlshift = _make_descr_binop(_lshift)
+        
+    def _int_lshift(self, space, w_other):
+        if w_other < 0:
+            raise oefmt(space.w_ValueError, "negative shift count")
+        return W_LongObject(self.num.lshift(w_other))
+        
+    descr_lshift, descr_rlshift = _make_descr_binop(_lshift, _int_lshift)
 
     def _rshift(self, space, w_other):
         if w_other.asbigint().sign < 0:
@@ -427,8 +470,22 @@
         except OverflowError:   # b too big # XXX maybe just return 0L instead?
             raise oefmt(space.w_OverflowError, "shift count too large")
         return newlong(space, self.num.rshift(shift))
-    descr_rshift, descr_rrshift = _make_descr_binop(_rshift)
+        
+    def _int_rshift(self, space, w_other):
+        if w_other < 0:
+            raise oefmt(space.w_ValueError, "negative shift count")
 
+        return newlong(space, self.num.rshift(w_other))
+    descr_rshift, descr_rrshift = _make_descr_binop(_rshift, _int_rshift)
+
+    def _floordiv(self, space, w_other):
+        try:
+            z = self.num.floordiv(w_other.asbigint())
+        except ZeroDivisionError:
+            raise oefmt(space.w_ZeroDivisionError,
+                        "long division or modulo by zero")
+        return newlong(space, z)
+        
     def _floordiv(self, space, w_other):
         try:
             z = self.num.floordiv(w_other.asbigint())
@@ -448,7 +505,15 @@
             raise oefmt(space.w_ZeroDivisionError,
                         "long division or modulo by zero")
         return newlong(space, z)
-    descr_mod, descr_rmod = _make_descr_binop(_mod)
+        
+    def _int_mod(self, space, w_other):
+        try:
+            z = self.num.int_mod(w_other)
+        except ZeroDivisionError:
+            raise oefmt(space.w_ZeroDivisionError,
+                        "long division or modulo by zero")
+        return newlong(space, z)
+    descr_mod, descr_rmod = _make_descr_binop(_mod, _int_mod)
 
     def _divmod(self, space, w_other):
         try:


More information about the pypy-commit mailing list