[pypy-commit] pypy bigint-with-int: Use the int_ops some other places, implant a int_truediv placeholder and add ZeroDivisionError

stian noreply at buildbot.pypy.org
Sat Aug 3 22:37:14 CEST 2013


Author: stian
Branch: bigint-with-int
Changeset: r65942:54da7171d2a4
Date: 2013-08-03 22:36 +0200
http://bitbucket.org/pypy/pypy/changeset/54da7171d2a4/

Log:	Use the int_ops some other places, implant a int_truediv placeholder
	and add ZeroDivisionError

	TODO:
	- Fix: 5 .__rsub__(2L) to give NotImplanted
	- Fallback to Long transformation if abs(INT) > MASK (currently causes
	a few tests to fail with rpython assert errors because we don't do
	this)

diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -42,7 +42,7 @@
         imag = space.float_w(space.getattr(self, space.wrap("imag")))
         real_b = rbigint.fromrarith_int(float2longlong(real))
         imag_b = rbigint.fromrarith_int(r_ulonglong(float2longlong(imag)))
-        val = real_b.lshift(64).or_(imag_b).lshift(3).or_(rbigint.fromint(tag))
+        val = real_b.lshift(64).or_(imag_b).lshift(3).int_or_(tag)
         return space.newlong_from_rbigint(val)
 
 
diff --git a/pypy/objspace/std/floattype.py b/pypy/objspace/std/floattype.py
--- a/pypy/objspace/std/floattype.py
+++ b/pypy/objspace/std/floattype.py
@@ -291,7 +291,7 @@
         from pypy.objspace.std.model import IDTAG_FLOAT as tag
         val = float2longlong(space.float_w(self))
         b = rbigint.fromrarith_int(val)
-        b = b.lshift(3).or_(rbigint.fromint(tag))
+        b = b.lshift(3).int_or_(tag)
         return space.newlong_from_rbigint(b)
 
     def int(self, space):
diff --git a/pypy/objspace/std/inttype.py b/pypy/objspace/std/inttype.py
--- a/pypy/objspace/std/inttype.py
+++ b/pypy/objspace/std/inttype.py
@@ -195,7 +195,7 @@
             return None
         from pypy.objspace.std.model import IDTAG_INT as tag
         b = space.bigint_w(self)
-        b = b.lshift(3).or_(rbigint.fromint(tag))
+        b = b.lshift(3).int_or_(tag)
         return space.newlong_from_rbigint(b)
 
     def int(self, space):
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
@@ -218,6 +218,17 @@
                              space.wrap("long/long too large for a float"))
     return space.newfloat(f)
 
+def truediv__Long_Int(space, w_long1, w_int2):
+    try:
+        f = w_long1.num.int_truediv(w_int2.intval)
+    except ZeroDivisionError:
+        raise OperationError(space.w_ZeroDivisionError,
+                             space.wrap("long division or modulo by zero"))
+    except OverflowError:
+        raise OperationError(space.w_OverflowError,
+                             space.wrap("long/long too large for a float"))
+    return space.newfloat(f)
+
 def floordiv__Long_Long(space, w_long1, w_long2):
     try:
         z = w_long1.num.floordiv(w_long2.num)
diff --git a/pypy/objspace/std/longtype.py b/pypy/objspace/std/longtype.py
--- a/pypy/objspace/std/longtype.py
+++ b/pypy/objspace/std/longtype.py
@@ -130,7 +130,7 @@
             return None
         from pypy.objspace.std.model import IDTAG_LONG as tag
         b = space.bigint_w(self)
-        b = b.lshift(3).or_(rbigint.fromint(tag))
+        b = b.lshift(3).int_or_(tag)
         return space.newlong_from_rbigint(b)
 
     def unwrap(w_self, space): #YYYYYY
diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -711,7 +711,7 @@
             elif self._digits[0] == ONEDIGIT:
                 return rbigint.fromint(self.sign * b)
 
-            res = self.widedigit(0) * b
+            res = self.widedigit(0) * abs(b)
             carry = res >> SHIFT
             if carry:
                 return rbigint([_store_digit(res & MASK), _store_digit(carry)], self.sign * (-1 if b < 0 else 1), 2)
@@ -730,6 +730,12 @@
         return div
 
     @jit.elidable
+    def int_truediv(self, other):
+        # XXX: Not specialized. Just use regular truediv for now.
+        div = _bigint_true_divide(self, rbigint.fromint(other))
+        return div
+
+    @jit.elidable
     def floordiv(self, other):
         if self.sign == 1 and other.numdigits() == 1 and other.sign == 1:
             digit = other.digit(0)
@@ -748,6 +754,10 @@
 
     @jit.elidable
     def int_floordiv(self, other):
+
+        if other == 0:
+            raise ZeroDivisionError("long division or modulo by zero")
+
         digit = abs(other)
         if self.sign == 1 and other > 0:
             if digit == 1:
@@ -878,22 +888,22 @@
     @jit.elidable
     def int_divmod(v, w):
         """ Divmod with int """
-        if v.sign != (-1 if w < 0 else 1):
-            # TODO, fix.
+
+        if w == 0:
+            raise ZeroDivisionError("long division or modulo by zero")
+
+        wsign = (-1 if w < 0 else 1)
+        if v.sign != wsign:
+            # Divrem1 doesn't deal with the sign difference. Instead of having yet another copy,
+            # Just fallback.
             return v.divmod(rbigint.fromint(w))
+
         div, mod = _divrem1(v, abs(w))
-        if v.sign != (-1 if w < 0 else 1):
-            mod = rbigint.fromint(mod)
-            mod.sign = -1 if w < 0 else 1
-            mod = mod.int_add(w)
-
-            if div.sign == 0:
-                return ONENEGATIVERBIGINT, mod
-            div = div.int_add(1)
-        else:
-            mod = rbigint.fromint(mod)
-            mod.sign = -1 if w < 0 else 1
-        div.sign = v.sign * (-1 if w < 0 else 1)
+        mod = rbigint.fromint(mod)
+        
+        mod.sign = wsign
+        div.sign = v.sign * wsign
+
         return div, mod
 
     @jit.elidable
@@ -1045,7 +1055,7 @@
         if self.sign == 0:
             return ONENEGATIVERBIGINT
 
-        ret = self.add(ONERBIGINT)
+        ret = self.int_add(1)
         ret.sign = -ret.sign
         return ret
 


More information about the pypy-commit mailing list