[pypy-svn] r78662 - in pypy/branch/smalllong/pypy: config module/marshal/test objspace/std objspace/std/test rlib translator/c/src
arigo at codespeak.net
arigo at codespeak.net
Wed Nov 3 12:40:49 CET 2010
Author: arigo
Date: Wed Nov 3 12:40:46 2010
New Revision: 78662
Modified:
pypy/branch/smalllong/pypy/config/pypyoption.py
pypy/branch/smalllong/pypy/module/marshal/test/test_marshalimpl.py
pypy/branch/smalllong/pypy/objspace/std/longobject.py
pypy/branch/smalllong/pypy/objspace/std/longtype.py
pypy/branch/smalllong/pypy/objspace/std/marshal_impl.py
pypy/branch/smalllong/pypy/objspace/std/model.py
pypy/branch/smalllong/pypy/objspace/std/objspace.py
pypy/branch/smalllong/pypy/objspace/std/smalllongobject.py
pypy/branch/smalllong/pypy/objspace/std/strutil.py
pypy/branch/smalllong/pypy/objspace/std/test/test_smalllongobject.py
pypy/branch/smalllong/pypy/rlib/rarithmetic.py
pypy/branch/smalllong/pypy/rlib/rbigint.py
pypy/branch/smalllong/pypy/translator/c/src/int.h
Log:
Mostly finish smalllongobject.py. Add support for translating
operations like 'llong_add_ovf'.
Modified: pypy/branch/smalllong/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/smalllong/pypy/config/pypyoption.py (original)
+++ pypy/branch/smalllong/pypy/config/pypyoption.py Wed Nov 3 12:40:46 2010
@@ -195,7 +195,9 @@
default=100, cmdline="--prebuiltintto"),
BoolOption("withsmalllong", "use a version of 'long' in a C long long",
- default=False),
+ default=False,
+ requires=[("objspace.std.withsmallint", False),]),
+ # because of missing delegate_xx2yy
BoolOption("withstrjoin", "use strings optimized for addition",
default=False),
Modified: pypy/branch/smalllong/pypy/module/marshal/test/test_marshalimpl.py
==============================================================================
--- pypy/branch/smalllong/pypy/module/marshal/test/test_marshalimpl.py (original)
+++ pypy/branch/smalllong/pypy/module/marshal/test/test_marshalimpl.py Wed Nov 3 12:40:46 2010
@@ -24,6 +24,10 @@
assert z == 10000000000
z = marshal.loads('I\x00\x1c\xf4\xab\xfd\xff\xff\xff')
assert z == -10000000000
+ z = marshal.loads('I\x88\x87\x86\x85\x84\x83\x82\x01')
+ assert z == 108793946209421192
+ z = marshal.loads('I\xd8\xd8\xd9\xda\xdb\xdc\xcd\xfe')
+ assert z == -0x0132232425262728
def test_buffer(self):
import marshal
Modified: pypy/branch/smalllong/pypy/objspace/std/longobject.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/longobject.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/longobject.py Wed Nov 3 12:40:46 2010
@@ -58,6 +58,9 @@
def get_sign(self):
return self.num.sign
+ def __repr__(self):
+ return '<W_LongObject(%d)>' % self.num.tolong()
+
registerimplementation(W_LongObject)
def newbigint(space, w_longtype, bigint):
@@ -65,6 +68,21 @@
W_LongObject.__init__(w_obj, bigint)
return w_obj
+def newlong(space, bigint):
+ """Turn the bigint into a W_LongObject. If withsmalllong is enabled,
+ check if the bigint would fit in a smalllong, and return a
+ W_SmallLongObject instead if it does.
+ """
+ if space.config.objspace.std.withsmalllong:
+ try:
+ z = bigint.tolonglong()
+ except OverflowError:
+ pass
+ else:
+ from pypy.objspace.std.smalllongobject import W_SmallLongObject
+ return W_SmallLongObject(z)
+ return W_LongObject(bigint)
+
# bool-to-long
def delegate_Bool2Long(space, w_bool):
@@ -72,7 +90,7 @@
# int-to-long delegation
def delegate_Int2Long(space, w_intobj):
- return long__Int(space, w_intobj)
+ return W_LongObject.fromint(space, w_intobj.intval)
# long__Long is supposed to do nothing, unless it has
@@ -85,7 +103,7 @@
return W_LongObject(l)
def long__Int(space, w_intobj):
- return W_LongObject.fromint(space, w_intobj.intval)
+ return space.newlong(w_intobj.intval)
def int__Long(space, w_value):
try:
@@ -190,38 +208,41 @@
def truediv__Long_Long(space, w_long1, w_long2):
try:
- return space.newfloat(w_long1.num.truediv(w_long2.num))
+ f = w_long1.num.truediv(w_long2.num)
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:
- return W_LongObject(w_long1.num.floordiv(w_long2.num))
+ z = w_long1.num.floordiv(w_long2.num)
except ZeroDivisionError:
raise OperationError(space.w_ZeroDivisionError,
space.wrap("long division or modulo by zero"))
+ return newlong(space, z)
def div__Long_Long(space, w_long1, w_long2):
return floordiv__Long_Long(space, w_long1, w_long2)
def mod__Long_Long(space, w_long1, w_long2):
try:
- return W_LongObject(w_long1.num.mod(w_long2.num))
+ z = w_long1.num.mod(w_long2.num)
except ZeroDivisionError:
raise OperationError(space.w_ZeroDivisionError,
space.wrap("long division or modulo by zero"))
+ return newlong(space, z)
def divmod__Long_Long(space, w_long1, w_long2):
try:
div, mod = w_long1.num.divmod(w_long2.num)
- return space.newtuple([W_LongObject(div), W_LongObject(mod)])
except ZeroDivisionError:
raise OperationError(space.w_ZeroDivisionError,
space.wrap("long division or modulo by zero"))
+ return space.newtuple([newlong(space, div), newlong(space, mod)])
def pow__Long_Long_Long(space, w_long1, w_long2, w_long3):
# XXX need to replicate some of the logic, to get the errors right
@@ -282,10 +303,10 @@
except OverflowError: # b too big # XXX maybe just return 0L instead?
raise OperationError(space.w_OverflowError,
space.wrap("shift count too large"))
- return W_LongObject(w_long1.num.rshift(shift))
+ return newlong(space, w_long1.num.rshift(shift))
def and__Long_Long(space, w_long1, w_long2):
- return W_LongObject(w_long1.num.and_(w_long2.num))
+ return newlong(space, w_long1.num.and_(w_long2.num))
def xor__Long_Long(space, w_long1, w_long2):
return W_LongObject(w_long1.num.xor(w_long2.num))
@@ -305,11 +326,18 @@
register_all(vars())
# register implementations of ops that recover int op overflows
+def recover_with_smalllong(space):
+ # True if there is a chance that a SmallLong would fit when an Int does not
+ return (space.config.objspace.std.withsmalllong and
+ sys.maxint == 2147483647)
# binary ops
for opname in ['add', 'sub', 'mul', 'div', 'floordiv', 'truediv', 'mod', 'divmod', 'lshift']:
exec compile("""
def %(opname)s_ovr__Int_Int(space, w_int1, w_int2):
+ if recover_with_smalllong(space) and %(opname)r != 'truediv':
+ from pypy.objspace.std.smalllongobject import %(opname)s_ovr
+ return %(opname)s_ovr(space, w_int1, w_int2)
w_long1 = delegate_Int2Long(space, w_int1)
w_long2 = delegate_Int2Long(space, w_int2)
return %(opname)s__Long_Long(space, w_long1, w_long2)
@@ -322,6 +350,9 @@
for opname in ['neg', 'abs']:
exec """
def %(opname)s_ovr__Int(space, w_int1):
+ if recover_with_smalllong(space):
+ from pypy.objspace.std.smalllongobject import %(opname)s_ovr
+ return %(opname)s_ovr(space, w_int1)
w_long1 = delegate_Int2Long(space, w_int1)
return %(opname)s__Long(space, w_long1)
""" % {'opname': opname}
@@ -331,6 +362,9 @@
# pow
def pow_ovr__Int_Int_None(space, w_int1, w_int2, w_none3):
+ if recover_with_smalllong(space):
+ from pypy.objspace.std.smalllongobject import pow_ovr
+ return pow_ovr(space, w_int1, w_int2)
w_long1 = delegate_Int2Long(space, w_int1)
w_long2 = delegate_Int2Long(space, w_int2)
return pow__Long_Long_None(space, w_long1, w_long2, w_none3)
Modified: pypy/branch/smalllong/pypy/objspace/std/longtype.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/longtype.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/longtype.py Wed Nov 3 12:40:46 2010
@@ -35,7 +35,7 @@
return w_obj
# the following is all for the 'subclass_of_long(x)' case
if W_SmallLongObject and isinstance(w_obj, W_SmallLongObject):
- bigint = w_obj.as_bigint()
+ bigint = w_obj.asbigint()
elif isinstance(w_obj, W_LongObject):
bigint = w_obj.num
elif space.is_true(space.isinstance(w_obj, space.w_int)):
@@ -70,14 +70,14 @@
space.wrap(e.msg))
if (space.config.objspace.std.withsmalllong
and space.is_w(w_longtype, space.w_long)):
+ from pypy.objspace.std.smalllongobject import W_SmallLongObject
try:
- longlong = bigint.tolonglong()
+ return W_SmallLongObject.frombigint(bigint)
except OverflowError:
pass
- else:
- from pypy.objspace.std.smalllongobject import W_SmallLongObject
- return W_SmallLongObject(longlong)
+ from pypy.objspace.std.longobject import newbigint
return newbigint(space, w_longtype, bigint)
+string_to_w_long._dont_inline_ = True
# ____________________________________________________________
Modified: pypy/branch/smalllong/pypy/objspace/std/marshal_impl.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/marshal_impl.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/marshal_impl.py Wed Nov 3 12:40:46 2010
@@ -10,8 +10,8 @@
from pypy.interpreter.error import OperationError
from pypy.objspace.std.register_all import register_all
-from pypy.rlib.rarithmetic import LONG_BIT
-from pypy.objspace.std import longobject, model
+from pypy.rlib.rarithmetic import LONG_BIT, r_longlong, r_uint
+from pypy.objspace.std import model
from pypy.objspace.std.longobject import SHIFT as long_bits
from pypy.interpreter.special import Ellipsis
from pypy.interpreter.pycode import PyCode
@@ -144,27 +144,13 @@
register(TYPE_INT, unmarshal_Int)
def unmarshal_Int64(space, u, tc):
+ lo = u.get_int()
+ hi = u.get_int()
if LONG_BIT >= 64:
- lo = u.get_int() & (2**32-1)
- hi = u.get_int()
- return space.newint((hi << 32) | lo)
- else:
- # fall back to a long
- # XXX at some point, we need to extend longobject
- # by _PyLong_FromByteArray and _PyLong_AsByteArray.
- # I will do that when implementing cPickle.
- # for now, this rare case is solved the simple way.
- lshift = longobject.lshift__Long_Long
- longor = longobject.or__Long_Long
- lo1 = space.newlong(u.get_short() & 0xffff)
- lo2 = space.newlong(u.get_short() & 0xffff)
- res = space.newlong(u.get_int())
- nbits = space.newlong(16)
- res = lshift(space, res, nbits)
- res = longor(space, res, lo2)
- res = lshift(space, res, nbits)
- res = longor(space, res, lo1)
- return res
+ x = (hi << 32) | (lo & (2**32-1)) # result fits in an int
+ else:
+ x = (r_longlong(hi) << 32) | r_longlong(r_uint(lo)) # get a r_longlong
+ return space.wrap(x)
register(TYPE_INT64, unmarshal_Int64)
def pack_float(f):
Modified: pypy/branch/smalllong/pypy/objspace/std/model.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/model.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/model.py Wed Nov 3 12:40:46 2010
@@ -16,6 +16,7 @@
option_to_typename = {
"withsmallint" : ["smallintobject.W_SmallIntObject"],
+ "withsmalllong" : ["smalllongobject.W_SmallLongObject"],
"withstrslice" : ["strsliceobject.W_StringSliceObject"],
"withstrjoin" : ["strjoinobject.W_StringJoinObject"],
"withstrbuf" : ["strbufobject.W_StringBufferObject"],
@@ -68,6 +69,7 @@
from pypy.objspace.std import complexobject
from pypy.objspace.std import setobject
from pypy.objspace.std import smallintobject
+ from pypy.objspace.std import smalllongobject
from pypy.objspace.std import tupleobject
from pypy.objspace.std import listobject
from pypy.objspace.std import dictmultiobject
@@ -180,6 +182,18 @@
(longobject.W_LongObject, longobject.delegate_Int2Long),
(complexobject.W_ComplexObject, complexobject.delegate_Int2Complex),
]
+ if config.objspace.std.withsmalllong:
+ self.typeorder[boolobject.W_BoolObject] += [
+ (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Bool2SmallLong),
+ ]
+ self.typeorder[intobject.W_IntObject] += [
+ (smalllongobject.W_SmallLongObject, smalllongobject.delegate_Int2SmallLong),
+ ]
+ self.typeorder[smalllongobject.W_SmallLongObject] += [
+ (floatobject.W_FloatObject, smalllongobject.delegate_SmallLong2Float),
+ (longobject.W_LongObject, smalllongobject.delegate_SmallLong2Long),
+ (complexobject.W_ComplexObject, smalllongobject.delegate_SmallLong2Complex),
+ ]
self.typeorder[longobject.W_LongObject] += [
(floatobject.W_FloatObject, floatobject.delegate_Long2Float),
(complexobject.W_ComplexObject,
Modified: pypy/branch/smalllong/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/objspace.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/objspace.py Wed Nov 3 12:40:46 2010
@@ -176,7 +176,13 @@
#print 'wrapping', x, '->', w_result
return w_result
if isinstance(x, base_int):
- xxxxxxxxx
+ if self.config.objspace.std.withsmalllong:
+ from pypy.objspace.std.smalllongobject import W_SmallLongObject
+ from pypy.rlib.rarithmetic import r_longlong, r_ulonglong
+ from pypy.rlib.rarithmetic import longlongmax
+ if (not isinstance(x, r_ulonglong)
+ or x <= r_ulonglong(longlongmax)):
+ return W_SmallLongObject(r_longlong(x))
return W_LongObject.fromrarith_int(x)
# _____ below here is where the annotator should not get _____
@@ -274,7 +280,7 @@
def newlong(self, val): # val is an int
if self.config.objspace.std.withsmalllong:
from pypy.objspace.std.smalllongobject import W_SmallLongObject
- return W_SmallLongObject.fromint(self, val)
+ return W_SmallLongObject.fromint(val)
return W_LongObject.fromint(self, val)
def newtuple(self, list_w):
Modified: pypy/branch/smalllong/pypy/objspace/std/smalllongobject.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/smalllongobject.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/smalllongobject.py Wed Nov 3 12:40:46 2010
@@ -1,19 +1,428 @@
"""
-Implementation of 'small' longs, stored as a C 'long long' value.
-Useful for 32-bit applications manipulating 64-bit values.
+Implementation of 'small' longs, stored as a r_longlong.
+Useful for 32-bit applications manipulating values a bit larger than
+fits in an 'int'.
"""
from pypy.objspace.std.model import registerimplementation, W_Object
-from pypy.rlib.rarithmetic import r_longlong
+from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.multimethod import FailedToImplementArgs
+from pypy.rlib.rarithmetic import r_longlong, r_int, r_uint
+from pypy.rlib.rarithmetic import intmask, ovfcheck, LONGLONG_BIT
+from pypy.rlib.rbigint import rbigint
+from pypy.objspace.std.longobject import W_LongObject
+from pypy.objspace.std.intobject import W_IntObject
+from pypy.objspace.std.noneobject import W_NoneObject
+from pypy.interpreter.error import OperationError
class W_SmallLongObject(W_Object):
from pypy.objspace.std.longtype import long_typedef as typedef
+ _immutable_ = True
def __init__(w_self, value):
assert isinstance(value, r_longlong)
- w_self._longlong = value
+ w_self.longlong = value
- def as_bigint(w_self):
- xxx
+ @staticmethod
+ def fromint(value):
+ return W_SmallLongObject(r_longlong(value))
+
+ @staticmethod
+ def frombigint(bigint):
+ return W_SmallLongObject(bigint.tolonglong())
+
+ def asbigint(w_self):
+ return rbigint.fromrarith_int(w_self.longlong)
+
+ def __repr__(w_self):
+ return '<W_SmallLongObject(%d)>' % w_self.longlong
registerimplementation(W_SmallLongObject)
+
+
+def delegate_Bool2SmallLong(space, w_bool):
+ return W_SmallLongObject(r_longlong(space.is_true(w_bool)))
+
+def delegate_Int2SmallLong(space, w_int):
+ return W_SmallLongObject(r_longlong(w_int.intval))
+
+def delegate_SmallLong2Long(space, w_small):
+ return W_LongObject(w_small.asbigint())
+
+def delegate_SmallLong2Float(space, w_small):
+ return space.newfloat(float(w_small.longlong))
+
+def delegate_SmallLong2Complex(space, w_small):
+ return space.newcomplex(float(w_small.longlong), 0.0)
+
+
+def long__SmallLong(space, w_value):
+ return w_value
+
+def int__SmallLong(space, w_value):
+ a = w_value.longlong
+ b = intmask(a)
+ if b == a:
+ return space.newint(b)
+ else:
+ return w_value
+
+def index__SmallLong(space, w_value):
+ return w_value
+
+def float__SmallLong(space, w_value):
+ return space.newfloat(float(w_value.longlong))
+
+def int_w__SmallLong(space, w_value):
+ a = w_value.longlong
+ b = intmask(a)
+ if b == a:
+ return b
+ else:
+ raise OperationError(space.w_OverflowError, space.wrap(
+ "long int too large to convert to int"))
+
+def uint_w__SmallLong(space, w_value):
+ a = w_value.longlong
+ if a < 0:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "cannot convert negative integer to unsigned int"))
+ b = r_uint(a)
+ if r_longlong(b) == a:
+ return b
+ else:
+ raise OperationError(space.w_OverflowError, space.wrap(
+ "long int too large to convert to unsigned int"))
+
+def bigint_w__SmallLong(space, w_value):
+ return w_value.asbigint()
+
+def lt__SmallLong_SmallLong(space, w_small1, w_small2):
+ return space.newbool(w_small1.longlong < w_small2.longlong)
+def le__SmallLong_SmallLong(space, w_small1, w_small2):
+ return space.newbool(w_small1.longlong <= w_small2.longlong)
+def eq__SmallLong_SmallLong(space, w_small1, w_small2):
+ return space.newbool(w_small1.longlong == w_small2.longlong)
+def ne__SmallLong_SmallLong(space, w_small1, w_small2):
+ return space.newbool(w_small1.longlong != w_small2.longlong)
+def gt__SmallLong_SmallLong(space, w_small1, w_small2):
+ return space.newbool(w_small1.longlong > w_small2.longlong)
+def ge__SmallLong_SmallLong(space, w_small1, w_small2):
+ return space.newbool(w_small1.longlong >= w_small2.longlong)
+
+def lt__SmallLong_Long(space, w_small1, w_long2):
+ return space.newbool(w_small1.asbigint().lt(w_long2.num))
+def le__SmallLong_Long(space, w_small1, w_long2):
+ return space.newbool(w_small1.asbigint().le(w_long2.num))
+def eq__SmallLong_Long(space, w_small1, w_long2):
+ return space.newbool(w_small1.asbigint().eq(w_long2.num))
+def ne__SmallLong_Long(space, w_small1, w_long2):
+ return space.newbool(w_small1.asbigint().ne(w_long2.num))
+def gt__SmallLong_Long(space, w_small1, w_long2):
+ return space.newbool(w_small1.asbigint().gt(w_long2.num))
+def ge__SmallLong_Long(space, w_small1, w_long2):
+ return space.newbool(w_small1.asbigint().ge(w_long2.num))
+
+def lt__Long_SmallLong(space, w_long1, w_small2):
+ return space.newbool(w_long1.num.lt(w_small2.asbigint()))
+def le__Long_SmallLong(space, w_long1, w_small2):
+ return space.newbool(w_long1.num.le(w_small2.asbigint()))
+def eq__Long_SmallLong(space, w_long1, w_small2):
+ return space.newbool(w_long1.num.eq(w_small2.asbigint()))
+def ne__Long_SmallLong(space, w_long1, w_small2):
+ return space.newbool(w_long1.num.ne(w_small2.asbigint()))
+def gt__Long_SmallLong(space, w_long1, w_small2):
+ return space.newbool(w_long1.num.gt(w_small2.asbigint()))
+def ge__Long_SmallLong(space, w_long1, w_small2):
+ return space.newbool(w_long1.num.ge(w_small2.asbigint()))
+
+def lt__SmallLong_Int(space, w_small1, w_int2):
+ return space.newbool(w_small1.longlong < w_int2.intval)
+def le__SmallLong_Int(space, w_small1, w_int2):
+ return space.newbool(w_small1.longlong <= w_int2.intval)
+def eq__SmallLong_Int(space, w_small1, w_int2):
+ return space.newbool(w_small1.longlong == w_int2.intval)
+def ne__SmallLong_Int(space, w_small1, w_int2):
+ return space.newbool(w_small1.longlong != w_int2.intval)
+def gt__SmallLong_Int(space, w_small1, w_int2):
+ return space.newbool(w_small1.longlong > w_int2.intval)
+def ge__SmallLong_Int(space, w_small1, w_int2):
+ return space.newbool(w_small1.longlong >= w_int2.intval)
+
+def lt__Int_SmallLong(space, w_int1, w_small2):
+ return space.newbool(w_int1.intval < w_small2.longlong)
+def le__Int_SmallLong(space, w_int1, w_small2):
+ return space.newbool(w_int1.intval <= w_small2.longlong)
+def eq__Int_SmallLong(space, w_int1, w_small2):
+ return space.newbool(w_int1.intval == w_small2.longlong)
+def ne__Int_SmallLong(space, w_int1, w_small2):
+ return space.newbool(w_int1.intval != w_small2.longlong)
+def gt__Int_SmallLong(space, w_int1, w_small2):
+ return space.newbool(w_int1.intval > w_small2.longlong)
+def ge__Int_SmallLong(space, w_int1, w_small2):
+ return space.newbool(w_int1.intval >= w_small2.longlong)
+
+
+#hash: default implementation via Longs (a bit messy)
+
+def add__SmallLong_SmallLong(space, w_small1, w_small2):
+ x = w_small1.longlong
+ y = w_small2.longlong
+ try:
+ z = ovfcheck(x + y)
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer addition"))
+ return W_SmallLongObject(z)
+
+def add_ovr(space, w_int1, w_int2):
+ x = r_longlong(w_int1.intval)
+ y = r_longlong(w_int2.intval)
+ return W_SmallLongObject(x + y)
+
+def sub__SmallLong_SmallLong(space, w_small1, w_small2):
+ x = w_small1.longlong
+ y = w_small2.longlong
+ try:
+ z = ovfcheck(x - y)
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer subtraction"))
+ return W_SmallLongObject(z)
+
+def sub_ovr(space, w_int1, w_int2):
+ x = r_longlong(w_int1.intval)
+ y = r_longlong(w_int2.intval)
+ return W_SmallLongObject(x - y)
+
+def mul__SmallLong_SmallLong(space, w_small1, w_small2):
+ x = w_small1.longlong
+ y = w_small2.longlong
+ try:
+ z = ovfcheck(x * y)
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer multiplication"))
+ return W_SmallLongObject(z)
+
+def mul_ovr(space, w_int1, w_int2):
+ x = r_longlong(w_int1.intval)
+ y = r_longlong(w_int2.intval)
+ return W_SmallLongObject(x * y)
+
+#truediv: default implementation via Longs
+
+def floordiv__SmallLong_SmallLong(space, w_small1, w_small2):
+ x = w_small1.longlong
+ y = w_small2.longlong
+ try:
+ z = ovfcheck(x // y)
+ except ZeroDivisionError:
+ raise OperationError(space.w_ZeroDivisionError,
+ space.wrap("integer division by zero"))
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer division"))
+ return W_SmallLongObject(z)
+div__SmallLong_SmallLong = floordiv__SmallLong_SmallLong
+
+def floordiv_ovr(space, w_int1, w_int2):
+ x = r_longlong(w_int1.intval)
+ y = r_longlong(w_int2.intval)
+ return W_SmallLongObject(x // y)
+div_ovr = floordiv_ovr
+
+def mod__SmallLong_SmallLong(space, w_small1, w_small2):
+ x = w_small1.longlong
+ y = w_small2.longlong
+ try:
+ z = ovfcheck(x % y)
+ except ZeroDivisionError:
+ raise OperationError(space.w_ZeroDivisionError,
+ space.wrap("integer modulo by zero"))
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer modulo"))
+ return W_SmallLongObject(z)
+
+def mod_ovr(space, w_int1, w_int2):
+ x = r_longlong(w_int1.intval)
+ y = r_longlong(w_int2.intval)
+ return W_SmallLongObject(x % y)
+
+def divmod__SmallLong_SmallLong(space, w_small1, w_small2):
+ x = w_small1.longlong
+ y = w_small2.longlong
+ try:
+ z = ovfcheck(x // y)
+ except ZeroDivisionError:
+ raise OperationError(space.w_ZeroDivisionError,
+ space.wrap("integer divmod by zero"))
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer modulo"))
+ # no overflow possible
+ m = x % y
+ return space.newtuple([W_SmallLongObject(z), W_SmallLongObject(m)])
+
+def divmod_ovr(space, w_int1, w_int2):
+ return space.newtuple([div_ovr(space, w_int1, w_int2),
+ mod_ovr(space, w_int1, w_int2)])
+
+def _impl_pow(space, iv, w_int2, iz=r_longlong(0)):
+ iw = w_int2.intval
+ if iw < 0:
+ if iz != 0:
+ raise OperationError(space.w_TypeError,
+ space.wrap("pow() 2nd argument "
+ "cannot be negative when 3rd argument specified"))
+ ## bounce it, since it always returns float
+ raise FailedToImplementArgs(space.w_ValueError,
+ space.wrap("integer exponentiation"))
+ temp = iv
+ ix = r_longlong(1)
+ try:
+ while iw > 0:
+ if iw & 1:
+ ix = ovfcheck(ix*temp)
+ iw >>= 1 #/* Shift exponent down by 1 bit */
+ if iw==0:
+ break
+ temp = ovfcheck(temp*temp) #/* Square the value of temp */
+ if iz:
+ #/* If we did a multiplication, perform a modulo */
+ ix = ix % iz
+ temp = temp % iz
+ if iz:
+ ix = ix % iz
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer exponentiation"))
+ return W_SmallLongObject(ix)
+
+def pow__SmallLong_Int_SmallLong(space, w_small1, w_int2, w_small3):
+ z = w_small3.longlong
+ if z == 0:
+ raise OperationError(space.w_ValueError,
+ space.wrap("pow() 3rd argument cannot be 0"))
+ return _impl_pow(space, w_small1.longlong, w_int2, z)
+
+def pow__SmallLong_Int_None(space, w_small1, w_int2, _):
+ return _impl_pow(space, w_small1.longlong, w_int2)
+
+def pow_ovr(space, w_int1, w_int2):
+ try:
+ return _impl_pow(space, r_longlong(w_int1.intval), w_int2)
+ except FailedToImplementArgs:
+ from pypy.objspace.std import longobject
+ w_a = W_LongObject.fromint(space, w_int1.intval)
+ w_b = W_LongObject.fromint(space, w_int2.intval)
+ return longobject.pow__Long_Long_None(space, w_a, w_b, space.w_None)
+
+def neg__SmallLong(space, w_small):
+ a = w_small.longlong
+ try:
+ x = ovfcheck(-a)
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer negation"))
+ return W_SmallLongObject(x)
+get_negint = neg__SmallLong
+
+def neg_ovr(space, w_int):
+ a = r_longlong(w_int.intval)
+ return W_SmallLongObject(-a)
+
+
+def pos__SmallLong(space, w_small):
+ return w_small
+
+def abs__SmallLong(space, w_small):
+ if w_small.longlong >= 0:
+ return w_small
+ else:
+ return get_negint(space, w_small)
+
+def abs_ovr(space, w_int):
+ a = r_longlong(w_int.intval)
+ if a < 0: a = -a
+ return W_SmallLongObject(a)
+
+def nonzero__SmallLong(space, w_small):
+ return space.newbool(bool(w_small.longlong))
+
+def invert__SmallLong(space, w_small):
+ x = w_small.longlong
+ a = ~x
+ return W_SmallLongObject(a)
+
+def lshift__SmallLong_Int(space, w_small1, w_int2):
+ a = w_small1.longlong
+ b = w_int2.intval
+ if r_uint(b) < LONGLONG_BIT: # 0 <= b < LONGLONG_BIT
+ try:
+ c = ovfcheck(a << b)
+ except OverflowError:
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer left shift"))
+ return W_SmallLongObject(c)
+ if b < 0:
+ raise OperationError(space.w_ValueError,
+ space.wrap("negative shift count"))
+ else: #b >= LONGLONG_BIT
+ if a == 0:
+ return w_small1
+ raise FailedToImplementArgs(space.w_OverflowError,
+ space.wrap("integer left shift"))
+
+def lshift_ovr(space, w_int1, w_int2):
+ a = r_longlong(w_int1.intval)
+ try:
+ return lshift__SmallLong_Int(space, W_SmallLongObject(a), w_int2)
+ except FailedToImplementArgs:
+ from pypy.objspace.std import longobject
+ w_a = W_LongObject.fromint(space, w_int1.intval)
+ w_b = W_LongObject.fromint(space, w_int2.intval)
+ return longobject.lshift__Long_Long(space, w_a, w_b)
+
+def rshift__SmallLong_Int(space, w_small1, w_int2):
+ a = w_small1.longlong
+ b = w_int2.intval
+ if r_uint(b) >= LONGLONG_BIT: # not (0 <= b < LONGLONG_BIT)
+ if b < 0:
+ raise OperationError(space.w_ValueError,
+ space.wrap("negative shift count"))
+ else: # b >= LONGLONG_BIT
+ if a == 0:
+ return w_small1
+ if a < 0:
+ a = -1
+ else:
+ a = 0
+ else:
+ a = a >> b
+ return W_SmallLongObject(a)
+
+def and__SmallLong_SmallLong(space, w_small1, w_small2):
+ a = w_small1.longlong
+ b = w_small2.longlong
+ res = a & b
+ return W_SmallLongObject(res)
+
+def xor__SmallLong_SmallLong(space, w_small1, w_small2):
+ a = w_small1.longlong
+ b = w_small2.longlong
+ res = a ^ b
+ return W_SmallLongObject(res)
+
+def or__SmallLong_SmallLong(space, w_small1, w_small2):
+ a = w_small1.longlong
+ b = w_small2.longlong
+ res = a | b
+ return W_SmallLongObject(res)
+
+#oct: default implementation via Longs
+#hex: default implementation via Longs
+#getnewargs: default implementation via Longs
+
+register_all(vars())
Modified: pypy/branch/smalllong/pypy/objspace/std/strutil.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/strutil.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/strutil.py Wed Nov 3 12:40:46 2010
@@ -205,67 +205,66 @@
digits = '0'
# a few abbreviations
- from pypy.objspace.std import longobject
- mklong = longobject.W_LongObject.fromint
- d2long = longobject.W_LongObject.fromdecimalstr
- adlong = longobject.add__Long_Long
- longup = longobject.pow__Long_Long_None
- multip = longobject.mul__Long_Long
- divide = longobject.div__Long_Long
- lshift = longobject.lshift__Long_Long
- rshift = longobject.rshift__Long_Long
+ from pypy.rlib.rbigint import rbigint
+ mklong = rbigint.fromint
+ d2long = rbigint.fromdecimalstr
+ adlong = rbigint.static_add
+ longup = rbigint.static_pow
+ multip = rbigint.static_mul
+ divide = rbigint.static_floordiv
+ lshift = rbigint.static_lshift
+ rshift = rbigint.static_rshift
# 4) compute the exponent and truncate to +-400
if not exponent:
exponent = '0'
- w_le = d2long(exponent)
- w_le = adlong(space, w_le, mklong(space, dexp))
+ b_le = d2long(exponent)
+ b_le = adlong(b_le, mklong(dexp))
try:
- e = w_le.toint()
+ e = b_le.toint()
except OverflowError:
- # XXX poking at internals
- e = w_le.num.sign * 400
+ e = b_le.getsign() * 400
if e >= 400:
e = 400
elif e <= -400:
e = -400
# 5) compute the value using long math and proper rounding.
- w_lr = d2long(digits)
- w_10 = mklong(space, 10)
- w_1 = mklong(space, 1)
+ b_lr = d2long(digits)
+ b_10 = mklong(10)
+ b_1 = mklong(1)
if e >= 0:
bits = 0
- w_pten = longup(space, w_10, mklong(space, e), space.w_None)
- w_m = multip(space, w_lr, w_pten)
+ b_pten = longup(b_10, mklong(e))
+ b_m = multip(b_lr, b_pten)
else:
# compute a sufficiently large scale
prec = MANTISSA_DIGITS * 2 + 22 # 128, maybe
bits = - (int(math.ceil(-e / math.log10(2.0) - 1e-10)) + prec)
- w_scale = lshift(space, w_1, mklong(space, -bits))
- w_pten = longup(space, w_10, mklong(space, -e), None)
- w_tmp = multip(space, w_lr, w_scale)
- w_m = divide(space, w_tmp, w_pten)
+ b_scale = lshift(b_1, -bits)
+ b_pten = longup(b_10, mklong(-e))
+ b_tmp = multip(b_lr, b_scale)
+ b_m = divide(b_tmp, b_pten)
# we now have a fairly large mantissa.
# Shift it and round the last bit.
# first estimate the bits and do a big shift
- mbits = w_m._count_bits()
+ mbits = b_m._count_bits()
needed = MANTISSA_BITS
if mbits > needed:
if mbits > needed+1:
shifted = mbits - (needed+1)
- w_m = rshift(space, w_m, mklong(space, shifted))
+ b_m = rshift(b_m, shifted)
bits += shifted
# do the rounding
bits += 1
- round = w_m.is_odd()
- w_m = rshift(space, w_m, w_1)
- w_m = adlong(space, w_m, mklong(space, round))
+ round = b_m.is_odd()
+ b_m = rshift(b_m, 1)
+ b_m = adlong(b_m, mklong(round))
try:
- r = math.ldexp(w_m.tofloat(), bits)
+ r = math.ldexp(b_m.tofloat(), bits)
# XXX I guess we do not check for overflow in ldexp as we agreed to!
if r == 2*r and r != 0.0:
raise OverflowError
Modified: pypy/branch/smalllong/pypy/objspace/std/test/test_smalllongobject.py
==============================================================================
--- pypy/branch/smalllong/pypy/objspace/std/test/test_smalllongobject.py (original)
+++ pypy/branch/smalllong/pypy/objspace/std/test/test_smalllongobject.py Wed Nov 3 12:40:46 2010
@@ -1,5 +1,39 @@
+import py
+import sys
+from pypy.objspace.std.smalllongobject import W_SmallLongObject
from pypy.objspace.std.test import test_longobject
from pypy.conftest import gettestobjspace
+from pypy.rlib.rarithmetic import r_longlong
+from pypy.interpreter.error import OperationError
+
+
+def test_direct():
+ space = gettestobjspace(**{"objspace.std.withsmalllong": True})
+ w5 = space.wrap(r_longlong(5))
+ assert isinstance(w5, W_SmallLongObject)
+ wlarge = space.wrap(r_longlong(0x123456789ABCDEFL))
+ #
+ assert space.int_w(w5) == 5
+ if sys.maxint < 0x123456789ABCDEFL:
+ py.test.raises(OperationError, space.int_w, wlarge)
+ else:
+ assert space.int_w(wlarge) == 0x123456789ABCDEF
+ #
+ assert space.pos(w5) is w5
+ assert space.abs(w5) is w5
+ wm5 = space.wrap(r_longlong(-5))
+ assert space.int_w(space.abs(wm5)) == 5
+ assert space.int_w(space.neg(w5)) == -5
+ assert space.is_true(w5) is True
+ assert space.is_true(wm5) is True
+ w0 = space.wrap(r_longlong(0))
+ assert space.is_true(w0) is False
+ #
+ w14000000000000 = space.wrap(r_longlong(0x14000000000000L))
+ assert space.is_true(space.eq(
+ space.lshift(w5, space.wrap(49)), w14000000000000)) is False
+ assert space.is_true(space.eq(
+ space.lshift(w5, space.wrap(50)), w14000000000000)) is True
class AppTestSmallLong(test_longobject.AppTestLong):
@@ -10,3 +44,75 @@
import __pypy__
s = __pypy__.internal_repr(5L)
assert 'SmallLong' in s
+
+ def test_sl_hash(self):
+ import __pypy__
+ x = 5L
+ assert 'SmallLong' in __pypy__.internal_repr(x)
+ assert hash(5) == hash(x)
+ biglong = 5L
+ biglong ^= 2**100 # hack based on the fact that xor__Long_Long
+ biglong ^= 2**100 # does not call newlong()
+ assert biglong == 5L
+ assert 'SmallLong' not in __pypy__.internal_repr(biglong)
+ assert hash(5) == hash(biglong)
+ #
+ x = 0x123456789ABCDEFL
+ assert 'SmallLong' in __pypy__.internal_repr(x)
+ biglong = x
+ biglong ^= 2**100
+ biglong ^= 2**100
+ assert biglong == x
+ assert 'SmallLong' not in __pypy__.internal_repr(biglong)
+ assert hash(biglong) == hash(x)
+
+ def test_sl_int(self):
+ x = 0x123456789ABCDEFL
+ two = 2
+ assert int(x) == x
+ assert type(int(x)) == type(0x1234567 ** two)
+ y = x >> 32
+ assert int(y) == y
+ assert type(int(y)) is int
+
+ def test_sl_long(self):
+ import __pypy__
+ x = long(0)
+ assert 'SmallLong' in __pypy__.internal_repr(x)
+
+ def test_sl_add(self):
+ import __pypy__
+ x = 0x123456789ABCDEFL
+ assert x + x == 0x2468ACF13579BDEL
+ assert 'SmallLong' in __pypy__.internal_repr(x + x)
+ x = -0x123456789ABCDEFL
+ assert x + x == -0x2468ACF13579BDEL
+ assert 'SmallLong' in __pypy__.internal_repr(x + x)
+ x = 0x723456789ABCDEF0L
+ assert x + x == 0xE468ACF13579BDE0L
+ assert 'SmallLong' not in __pypy__.internal_repr(x + x)
+ x = -0x723456789ABCDEF0L
+ assert x + x == -0xE468ACF13579BDE0L
+ assert 'SmallLong' not in __pypy__.internal_repr(x + x)
+
+ def test_sl_add_32(self):
+ import sys, __pypy__
+ if sys.maxint == 2147483647:
+ x = 2147483647
+ assert x + x == 4294967294L
+ assert 'SmallLong' in __pypy__.internal_repr(x + x)
+ y = -1
+ assert x - y == 2147483648L
+ assert 'SmallLong' in __pypy__.internal_repr(x - y)
+
+ def test_sl_lshift(self):
+ for x in [1, 1L]:
+ assert x << 1 == 2L
+ assert x << 30 == 1073741824L
+ assert x << 31 == 2147483648L
+ assert x << 32 == 4294967296L
+ assert x << 62 == 4611686018427387904L
+ assert x << 63 == 9223372036854775808L
+ assert x << 64 == 18446744073709551616L
+ assert (x << 31) << 31 == 4611686018427387904L
+ assert (x << 32) << 32 == 18446744073709551616L
Modified: pypy/branch/smalllong/pypy/rlib/rarithmetic.py
==============================================================================
--- pypy/branch/smalllong/pypy/rlib/rarithmetic.py (original)
+++ pypy/branch/smalllong/pypy/rlib/rarithmetic.py Wed Nov 3 12:40:46 2010
@@ -49,6 +49,9 @@
LONG_BIT = _bits+1
LONG_MASK = _Ltest*2-1
LONG_TEST = _Ltest
+LONGLONG_BIT = 64
+LONGLONG_MASK = (2**LONGLONG_BIT)-1
+LONGLONG_TEST = 2**(LONGLONG_BIT-1)
LONG_BIT_SHIFT = 0
while (1 << LONG_BIT_SHIFT) != LONG_BIT:
@@ -76,6 +79,15 @@
n -= 2*LONG_TEST
return int(n)
+def longlongmask(n):
+ if isinstance(n, int):
+ n = long(n)
+ assert isinstance(n, long)
+ n &= LONGLONG_MASK
+ if n >= LONGLONG_TEST:
+ n -= 2*LONGLONG_TEST
+ return r_longlong(n)
+
def widen(n):
from pypy.rpython.lltypesystem import lltype
if _should_widen_type(lltype.typeOf(n)):
@@ -389,6 +401,8 @@
r_longlong = build_int('r_longlong', True, 64)
r_ulonglong = build_int('r_ulonglong', False, 64)
+longlongmax = r_longlong(LONGLONG_TEST - 1)
+
# float as string -> sign, beforept, afterpt, exponent
Modified: pypy/branch/smalllong/pypy/rlib/rbigint.py
==============================================================================
--- pypy/branch/smalllong/pypy/rlib/rbigint.py (original)
+++ pypy/branch/smalllong/pypy/rlib/rbigint.py Wed Nov 3 12:40:46 2010
@@ -558,6 +558,34 @@
if self._numdigits() == 1 and self.digits[0] == 0:
self.sign = 0
+ def getsign(self):
+ return self.sign
+
+
+ @staticmethod
+ def static_add(a, b):
+ return a.add(b)
+
+ @staticmethod
+ def static_mul(a, b):
+ return a.mul(b)
+
+ @staticmethod
+ def static_floordiv(a, b):
+ return a.floordiv(b)
+
+ @staticmethod
+ def static_lshift(a, b):
+ return a.lshift(b)
+
+ @staticmethod
+ def static_rshift(a, b):
+ return a.rshift(b)
+
+ @staticmethod
+ def static_pow(a, b):
+ return a.pow(b)
+
def __repr__(self):
return "<rbigint digits=%s, sign=%s, %s>" % (self.digits, self.sign, self.str())
Modified: pypy/branch/smalllong/pypy/translator/c/src/int.h
==============================================================================
--- pypy/branch/smalllong/pypy/translator/c/src/int.h (original)
+++ pypy/branch/smalllong/pypy/translator/c/src/int.h Wed Nov 3 12:40:46 2010
@@ -64,6 +64,11 @@
if ((r^(x)) >= 0 || (r^(y)) >= 0); \
else FAIL_OVF("integer addition")
+#define OP_LLONG_ADD_OVF(x,y,r) \
+ OP_LLONG_ADD(x,y,r); \
+ if ((r^(x)) >= 0 || (r^(y)) >= 0); \
+ else FAIL_OVF("integer addition")
+
#define OP_INT_ADD_NONNEG_OVF(x,y,r) /* y can be assumed >= 0 */ \
r = (long)((unsigned long)x + (unsigned long)y); \
if (r >= (x)); \
@@ -78,22 +83,17 @@
if ((r^(x)) >= 0 || (r^~(y)) >= 0); \
else FAIL_OVF("integer subtraction")
-#define OP_INT_MUL(x,y,r) r = (x) * (y)
-
-#if defined(HAVE_LONG_LONG) && SIZE_OF_LONG_LONG < SIZE_OF_LONG
-# define OP_INT_MUL_OVF_LL 1
-#lse
-# define OP_INT_MUL_OVF_LL 0
-#endif
+#define OP_LLONG_SUB_OVF(x,y,r) \
+ OP_LLONG_SUB(x,y,r); \
+ if ((r^(x)) >= 0 || (r^~(y)) >= 0); \
+ else FAIL_OVF("integer subtraction")
-#if !OP_INT_MUL_OVF_LL
+#define OP_INT_MUL(x,y,r) r = (x) * (y)
+#if SIZE_OF_LONG == SIZE_OF_LONG_LONG
#define OP_INT_MUL_OVF(x,y,r) \
- if (op_int_mul_ovf(x,y,&r)); \
- else FAIL_OVF("integer multiplication")
-
+ r = op_llong_mul_ovf(x, y)
#else
-
#define OP_INT_MUL_OVF(x,y,r) \
{ \
PY_LONG_LONG lr = (PY_LONG_LONG)(x) * (PY_LONG_LONG)(y); \
@@ -103,6 +103,9 @@
}
#endif
+#define OP_LLONG_MUL_OVF(x,y,r) \
+ r = op_llong_mul_ovf(x, y)
+
/* shifting */
/* NB. shifting has same limitations as C: the shift count must be
@@ -121,6 +124,10 @@
OP_INT_LSHIFT(x,y,r); \
if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \
FAIL_OVF("x<<y losing bits or changing sign")
+#define OP_LLONG_LSHIFT_OVF(x,y,r) \
+ OP_LLONG_LSHIFT(x,y,r); \
+ if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(PY_LONG_LONG, r, (y))) \
+ FAIL_OVF("x<<y losing bits or changing sign")
/* floor division */
@@ -133,6 +140,10 @@
if ((y) == -1 && (x) == LONG_MIN) \
{ FAIL_OVF("integer division"); } \
else OP_INT_FLOORDIV(x,y,r)
+#define OP_LLONG_FLOORDIV_OVF(x,y,r) \
+ if ((y) == -1 && (x) == LLONG_MIN) \
+ { FAIL_OVF("integer division"); } \
+ else OP_LLONG_FLOORDIV(x,y,r)
#define OP_INT_FLOORDIV_ZER(x,y,r) \
if ((y)) { OP_INT_FLOORDIV(x,y,r); } \
@@ -150,6 +161,9 @@
#define OP_INT_FLOORDIV_OVF_ZER(x,y,r) \
if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r); } \
else FAIL_ZER("integer division")
+#define OP_LLONG_FLOORDIV_OVF_ZER(x,y,r) \
+ if ((y)) { OP_LLONG_FLOORDIV_OVF(x,y,r); } \
+ else FAIL_ZER("integer division")
/* modulus */
@@ -162,6 +176,10 @@
if ((y) == -1 && (x) == LONG_MIN) \
{ FAIL_OVF("integer modulo"); }\
else OP_INT_MOD(x,y,r)
+#define OP_LLONG_MOD_OVF(x,y,r) \
+ if ((y) == -1 && (x) == LLONG_MIN) \
+ { FAIL_OVF("integer modulo"); }\
+ else OP_LLONG_MOD(x,y,r)
#define OP_INT_MOD_ZER(x,y,r) \
if ((y)) { OP_INT_MOD(x,y,r); } \
@@ -179,6 +197,9 @@
#define OP_INT_MOD_OVF_ZER(x,y,r) \
if ((y)) { OP_INT_MOD_OVF(x,y,r); } \
else FAIL_ZER("integer modulo")
+#define OP_LLONG_MOD_OVF_ZER(x,y,r) \
+ if ((y)) { OP_LLONG_MOD_OVF(x,y,r); } \
+ else FAIL_ZER("integer modulo")
/* bit operations */
@@ -208,31 +229,31 @@
/* _________________ certain implementations __________________ */
-#if !OP_INT_MUL_OVF_LL
/* adjusted from intobject.c, Python 2.3.3 */
/* prototypes */
-int op_int_mul_ovf(long a, long b, long *longprod);
+PY_LONG_LONG op_llong_mul_ovf(PY_LONG_LONG a, PY_LONG_LONG b);
/* implementations */
#ifndef PYPY_NOT_MAIN_FILE
-int
-op_int_mul_ovf(long a, long b, long *longprod)
+PY_LONG_LONG
+op_llong_mul_ovf(PY_LONG_LONG a, PY_LONG_LONG b)
{
double doubled_longprod; /* (double)longprod */
double doubleprod; /* (double)a * (double)b */
+ PY_LONG_LONG longprod;
- *longprod = a * b;
+ longprod = a * b;
doubleprod = (double)a * (double)b;
- doubled_longprod = (double)*longprod;
+ doubled_longprod = (double)longprod;
/* Fast path for normal case: small multiplicands, and no info
is lost in either method. */
if (doubled_longprod == doubleprod)
- return 1;
+ return longprod;
/* Somebody somewhere lost info. Close enough, or way off? Note
that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0).
@@ -247,15 +268,15 @@
/* absdiff/absprod <= 1/32 iff
32 * absdiff <= absprod -- 5 good bits is "close enough" */
if (32.0 * absdiff <= absprod)
- return 1;
- return 0;
+ return longprod;
+
+ FAIL_OVF("integer multiplication");
+ return -1;
}
}
#endif /* PYPY_NOT_MAIN_FILE */
-#endif /* !OP_INT_MUL_OVF_LL */
-
/* implementations */
#define OP_UINT_IS_TRUE OP_INT_IS_TRUE
More information about the Pypy-commit
mailing list