Author: stian
Branch: improve-rbigint
Changeset: r56347:cd82209a05cb
Date: 2012-07-05 20:23 +0200
http://bitbucket.org/pypy/pypy/changeset/cd82209a05cb/

Log:    Improve the general speed of pow, special case 0 ** something and
        something ** 0, along with negative numbers.

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -558,6 +558,11 @@
             # XXX failed to implement
             raise ValueError("bigint pow() too negative")
         
+        if b.sign == 0:
+            return ONERBIGINT
+        elif a.sign == 0:
+            return NULLRBIGINT
+        
         size_b = b.numdigits()
         
         if c is not None:
@@ -574,7 +579,7 @@
             # if modulus == 1:
             #     return 0
             if c.numdigits() == 1 and c.digit(0) == 1:
-                return rbigint()
+                return NULLRBIGINT
 
             # if base < 0:
             #     base = base % modulus
@@ -583,18 +588,23 @@
                 a = a.mod(c)
                 
             
-        elif size_b == 1 and a.sign == 1:
+        elif size_b == 1:
             digit = b.digit(0)
             if digit == 0:
-                return ONERBIGINT
+                return ONERBIGINT if a.sign == 1 else ONENEGATIVERBIGINT
             elif digit == 1:
                 return a
             elif a.numdigits() == 1:
                 adigit = a.digit(0)
                 if adigit == 1:
+                    if a.sign == -1 and digit % 2:
+                        return ONENEGATIVERBIGINT
                     return ONERBIGINT
                 elif adigit & (adigit - 1) == 0:
-                    return a.lshift(((digit-1)*(ptwotable[adigit]-1)) + 
digit-1)
+                    ret = a.lshift(((digit-1)*(ptwotable[adigit]-1)) + digit-1)
+                    if a.sign == -1 and not digit % 2:
+                        ret.sign = 1
+                    return ret
                 
         # At this point a, b, and c are guaranteed non-negative UNLESS
         # c is NULL, in which case a may be negative. */
@@ -848,6 +858,7 @@
                                                      self.sign, self.str())
 
 ONERBIGINT = rbigint([ONEDIGIT], 1)
+ONENEGATIVERBIGINT = rbigint([ONEDIGIT], -1)
 NULLRBIGINT = rbigint()
 
 #_________________________________________________________________
diff --git a/pypy/translator/goal/targetbigintbenchmark.py 
b/pypy/translator/goal/targetbigintbenchmark.py
--- a/pypy/translator/goal/targetbigintbenchmark.py
+++ b/pypy/translator/goal/targetbigintbenchmark.py
@@ -29,21 +29,21 @@
         Sum: 901.7231250000001
         
         Pypy with improvements:
-        2.884540
-        2.499774
-        3.796117
-        1.681326
-        4.060521
-        9.696996
-        1.643792
-        4.045248
-        4.714733
-        6.589811
-        0.039319
-        3.503355
-        8.266362
-        5.044856
-        Sum:  58.466750
+        2.867820
+        2.523047
+        3.848003
+        1.682992
+        4.099669
+        9.233212
+        1.622695
+        4.026895
+        4.708891
+        6.542558
+        0.039864
+        3.508814
+        8.225711
+        5.009382
+        Sum:  57.939553
 
         A pure python form of those tests where also run
         Improved pypy           | Pypy                  | CPython 2.7.3
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to