Author: Justin Peel <notmuchtot...@gmail.com> Branch: Changeset: r47805:1255f9205eda Date: 2011-10-03 13:44 -0600 http://bitbucket.org/pypy/pypy/changeset/1255f9205eda/
Log: merge unsigned-dtypes branch diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py --- a/pypy/jit/codewriter/effectinfo.py +++ b/pypy/jit/codewriter/effectinfo.py @@ -74,6 +74,7 @@ OS_LLONG_UGE = 91 OS_LLONG_URSHIFT = 92 OS_LLONG_FROM_UINT = 93 + OS_LLONG_U_TO_FLOAT = 94 # OS_MATH_SQRT = 100 diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py --- a/pypy/jit/codewriter/jtransform.py +++ b/pypy/jit/codewriter/jtransform.py @@ -440,6 +440,7 @@ rewrite_op_ullong_mod_zer = _do_builtin_call rewrite_op_gc_identityhash = _do_builtin_call rewrite_op_gc_id = _do_builtin_call + rewrite_op_uint_mod = _do_builtin_call # ---------- # getfield/setfield/mallocs etc. @@ -883,9 +884,15 @@ v = v_arg oplist = [] if unsigned1: - opname = 'cast_uint_to_longlong' + if unsigned2: + opname = 'cast_uint_to_ulonglong' + else: + opname = 'cast_uint_to_longlong' else: - opname = 'cast_int_to_longlong' + if unsigned2: + opname = 'cast_int_to_ulonglong' + else: + opname = 'cast_int_to_longlong' op2 = self.rewrite_operation( SpaceOperation(opname, [v], v_result) ) @@ -995,6 +1002,21 @@ return op2 ''' % (_op, _oopspec.lower(), _oopspec, _oopspec)).compile() + for _op, _oopspec in [('cast_int_to_ulonglong', 'FROM_INT'), + ('cast_uint_to_ulonglong', 'FROM_UINT'), + ('cast_float_to_ulonglong', 'FROM_FLOAT'), + ('cast_ulonglong_to_float', 'U_TO_FLOAT'), + ]: + exec py.code.Source(''' + def rewrite_op_%s(self, op): + args = op.args + op1 = self.prepare_builtin_call(op, "ullong_%s", args) + op2 = self._handle_oopspec_call(op1, args, + EffectInfo.OS_LLONG_%s, + EffectInfo.EF_ELIDABLE_CANNOT_RAISE) + return op2 + ''' % (_op, _oopspec.lower(), _oopspec)).compile() + def _normalize(self, oplist): if isinstance(oplist, SpaceOperation): return [oplist] diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py --- a/pypy/jit/codewriter/support.py +++ b/pypy/jit/codewriter/support.py @@ -315,18 +315,30 @@ def _ll_1_llong_from_int(x): return r_longlong(intmask(x)) +def _ll_1_ullong_from_int(x): + return r_ulonglong(intmask(x)) + def _ll_1_llong_from_uint(x): return r_longlong(r_uint(x)) +def _ll_1_ullong_from_uint(x): + return r_ulonglong(r_uint(x)) + def _ll_1_llong_to_int(xll): return intmask(xll) def _ll_1_llong_from_float(xf): return r_longlong(xf) +def _ll_1_ullong_from_float(xf): + return r_ulonglong(xf) + def _ll_1_llong_to_float(xll): return float(rffi.cast(lltype.SignedLongLong, xll)) +def _ll_1_ullong_u_to_float(xull): + return float(rffi.cast(lltype.UnsignedLongLong, xull)) + def _ll_1_llong_abs(xll): if xll < 0: @@ -351,20 +363,23 @@ return llop.llong_mod(lltype.SignedLongLong, xll, yll) def _ll_2_ullong_floordiv(xll, yll): - return llop.ullong_floordiv(lltype.SignedLongLong, xll, yll) + return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll) def _ll_2_ullong_floordiv_zer(xll, yll): if yll == 0: raise ZeroDivisionError - return llop.ullong_floordiv(lltype.SignedLongLong, xll, yll) + return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll) def _ll_2_ullong_mod(xll, yll): - return llop.ullong_mod(lltype.SignedLongLong, xll, yll) + return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll) def _ll_2_ullong_mod_zer(xll, yll): if yll == 0: raise ZeroDivisionError - return llop.ullong_mod(lltype.SignedLongLong, xll, yll) + return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll) + +def _ll_2_uint_mod(xll, yll): + return llop.uint_mod(lltype.Unsigned, xll, yll) # libffi support diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py --- a/pypy/jit/codewriter/test/test_flatten.py +++ b/pypy/jit/codewriter/test/test_flatten.py @@ -829,14 +829,15 @@ self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr, transform=True) elif TO in (rffi.LONG, rffi.ULONG): + if rffi.cast(FROM, -1) < 0: + fnname = "llong_from_int" + else: + fnname = "llong_from_uint" if TO == rffi.LONG: TO = rffi.LONGLONG else: TO = rffi.ULONGLONG - if rffi.cast(FROM, -1) < 0: - fnname = "llong_from_int" - else: - fnname = "llong_from_uint" + fnname = "u" + fnname expected.pop() # remove int_return expected.append( "residual_call_irf_f $<* fn %s>, <Descr>, I[%s], R[], F[] -> %%f0" diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py --- a/pypy/jit/codewriter/test/test_longlong.py +++ b/pypy/jit/codewriter/test/test_longlong.py @@ -57,7 +57,8 @@ assert op1.opname == 'residual_call_irf_f' else: assert op1.opname == 'residual_call_irf_i' - gotindex = getattr(EffectInfo, 'OS_' + op1.args[0].value.upper()) + gotindex = getattr(EffectInfo, + 'OS_' + op1.args[0].value.upper().lstrip('U')) assert gotindex == oopspecindex assert op1.args[1] == 'calldescr-%d' % oopspecindex assert list(op1.args[2]) == [v for v in vlist @@ -192,8 +193,12 @@ [lltype.SignedLongLong], lltype.Signed) self.do_check('cast_float_to_longlong', EffectInfo.OS_LLONG_FROM_FLOAT, [lltype.Float], lltype.SignedLongLong) + self.do_check('cast_float_to_ulonglong', EffectInfo.OS_LLONG_FROM_FLOAT, + [lltype.Float], lltype.UnsignedLongLong) self.do_check('cast_longlong_to_float', EffectInfo.OS_LLONG_TO_FLOAT, [lltype.SignedLongLong], lltype.Float) + self.do_check('cast_ulonglong_to_float', EffectInfo.OS_LLONG_U_TO_FLOAT, + [lltype.UnsignedLongLong], lltype.Float) for T1 in [lltype.SignedLongLong, lltype.UnsignedLongLong]: for T2 in [lltype.Signed, lltype.Unsigned]: self.do_check('cast_primitive', EffectInfo.OS_LLONG_TO_INT, diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py --- a/pypy/jit/metainterp/test/test_ajit.py +++ b/pypy/jit/metainterp/test/test_ajit.py @@ -2956,6 +2956,18 @@ assert res == f(32) self.check_loops(arraylen_gc=2) + def test_ulonglong_mod(self): + myjitdriver = JitDriver(greens = [], reds = ['n', 'sa', 'i']) + def f(n): + sa = i = rffi.cast(rffi.ULONGLONG, 1) + while i < rffi.cast(rffi.ULONGLONG, n): + myjitdriver.jit_merge_point(sa=sa, n=n, i=i) + sa += sa % i + i += 1 + res = self.meta_interp(f, [32]) + assert res == f(32) + + class TestOOtype(BasicTests, OOJitMixin): def test_oohash(self): diff --git a/pypy/jit/metainterp/test/test_longlong.py b/pypy/jit/metainterp/test/test_longlong.py --- a/pypy/jit/metainterp/test/test_longlong.py +++ b/pypy/jit/metainterp/test/test_longlong.py @@ -118,6 +118,26 @@ res = self.interp_operations(f, [1000000000]) assert res == 123500000000.0 + def test_floats_negative(self): + def f(i): + # i == 1000000000 + f = i * -123.5 + n = r_longlong(f) + compare(n, -29, 1054051584) + return float(n) + res = self.interp_operations(f, [1000000000]) + assert res == -123500000000.0 + + def test_floats_ulonglong(self): + def f(i): + # i == 1000000000 + f = i * 12350000000.0 + n = r_ulonglong(f) + compare(n, -1419508847, 538116096) + return float(n) + res = self.interp_operations(f, [1000000000]) + assert res == 12350000000000000000.0 + def test_unsigned_compare_ops(self): def f(n1, n2): # n == 30002000000000 diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -7,13 +7,14 @@ from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty from pypy.module.micronumpy import signature from pypy.objspace.std.floatobject import float2string -from pypy.rlib import rfloat -from pypy.rlib.rarithmetic import widen +from pypy.rlib import rarithmetic, rfloat +from pypy.rlib.rarithmetic import LONG_BIT, widen from pypy.rlib.objectmodel import specialize, enforceargs from pypy.rlib.unroll import unrolling_iterable from pypy.rpython.lltypesystem import lltype, rffi +UNSIGNEDLTR = "u" SIGNEDLTR = "i" BOOLLTR = "b" FLOATINGLTR = "f" @@ -61,7 +62,10 @@ self.val = val def wrap(self, space): - return space.wrap(self.val) + val = self.val + if valtype is rarithmetic.r_singlefloat: + val = float(val) + return space.wrap(val) def convert_to(self, dtype): return dtype.adapt_val(self.val) @@ -145,7 +149,7 @@ return self.adapt_val(func(self, self.for_computation(self.unbox(v)))) return impl -class ArithmaticTypeMixin(object): +class ArithmeticTypeMixin(object): _mixin_ = True @binop @@ -200,11 +204,17 @@ return v1 >= v2 -class FloatArithmeticDtype(ArithmaticTypeMixin): +class FloatArithmeticDtype(ArithmeticTypeMixin): _mixin_ = True + def unwrap(self, space, w_item): + return self.adapt_val(space.float_w(space.float(w_item))) + def for_computation(self, v): - return v + return float(v) + + def str_format(self, item): + return float2string(self.for_computation(self.unbox(item)), 'g', rfloat.DTSF_STR_PRECISION) @binop def mod(self, v1, v2): @@ -265,7 +275,7 @@ def arcsinh(self, v): return math.asinh(v) -class IntegerArithmeticDtype(ArithmaticTypeMixin): +class IntegerArithmeticDtype(ArithmeticTypeMixin): _mixin_ = True def unwrap(self, space, w_item): @@ -274,10 +284,16 @@ def for_computation(self, v): return widen(v) + def str_format(self, item): + return str(widen(self.unbox(item))) + @binop def mod(self, v1, v2): return v1 % v2 +class SignedIntegerArithmeticDtype(IntegerArithmeticDtype): + _mixin_ = True + @unaryop def sign(self, v): if v > 0: @@ -288,17 +304,22 @@ assert v == 0 return 0 - def str_format(self, item): - return str(widen(self.unbox(item))) +class UnsignedIntegerArithmeticDtype(IntegerArithmeticDtype): + _mixin_ = True + + @unaryop + def sign(self, v): + return int(v != 0) + W_BoolDtype = create_low_level_dtype( num = 0, kind = BOOLLTR, name = "bool", - aliases = ["?"], + aliases = ["?", "bool", "bool8"], applevel_types = ["bool"], T = lltype.Bool, valtype = bool, ) -class W_BoolDtype(IntegerArithmeticDtype, W_BoolDtype): +class W_BoolDtype(SignedIntegerArithmeticDtype, W_BoolDtype): def unwrap(self, space, w_item): return self.adapt_val(space.is_true(w_item)) @@ -311,67 +332,139 @@ W_Int8Dtype = create_low_level_dtype( num = 1, kind = SIGNEDLTR, name = "int8", - aliases = ["int8"], + aliases = ["b", "int8", "i1"], applevel_types = [], T = rffi.SIGNEDCHAR, valtype = rffi.SIGNEDCHAR._type, expected_size = 1, ) -class W_Int8Dtype(IntegerArithmeticDtype, W_Int8Dtype): +class W_Int8Dtype(SignedIntegerArithmeticDtype, W_Int8Dtype): + pass + +W_UInt8Dtype = create_low_level_dtype( + num = 2, kind = UNSIGNEDLTR, name = "uint8", + aliases = ["B", "uint8", "I1"], + applevel_types = [], + T = rffi.UCHAR, + valtype = rffi.UCHAR._type, + expected_size = 1, +) +class W_UInt8Dtype(UnsignedIntegerArithmeticDtype, W_UInt8Dtype): pass W_Int16Dtype = create_low_level_dtype( num = 3, kind = SIGNEDLTR, name = "int16", - aliases = ["int16"], + aliases = ["h", "int16", "i2"], applevel_types = [], T = rffi.SHORT, valtype = rffi.SHORT._type, expected_size = 2, ) -class W_Int16Dtype(IntegerArithmeticDtype, W_Int16Dtype): +class W_Int16Dtype(SignedIntegerArithmeticDtype, W_Int16Dtype): + pass + +W_UInt16Dtype = create_low_level_dtype( + num = 4, kind = UNSIGNEDLTR, name = "uint16", + aliases = ["H", "uint16", "I2"], + applevel_types = [], + T = rffi.USHORT, + valtype = rffi.USHORT._type, + expected_size = 2, +) +class W_UInt16Dtype(UnsignedIntegerArithmeticDtype, W_UInt16Dtype): pass W_Int32Dtype = create_low_level_dtype( num = 5, kind = SIGNEDLTR, name = "int32", - aliases = ["i"], + aliases = ["i", "int32", "i4"], applevel_types = [], T = rffi.INT, valtype = rffi.INT._type, expected_size = 4, ) -class W_Int32Dtype(IntegerArithmeticDtype, W_Int32Dtype): +class W_Int32Dtype(SignedIntegerArithmeticDtype, W_Int32Dtype): + pass + +W_UInt32Dtype = create_low_level_dtype( + num = 6, kind = UNSIGNEDLTR, name = "uint32", + aliases = ["I", "uint32", "I4"], + applevel_types = [], + T = rffi.UINT, + valtype = rffi.UINT._type, + expected_size = 4, +) +class W_UInt32Dtype(UnsignedIntegerArithmeticDtype, W_UInt32Dtype): pass W_Int64Dtype = create_low_level_dtype( num = 9, kind = SIGNEDLTR, name = "int64", - aliases = [], + aliases = ["q", "int64", "i8"], applevel_types = ["long"], T = rffi.LONGLONG, valtype = rffi.LONGLONG._type, expected_size = 8, ) -class W_Int64Dtype(IntegerArithmeticDtype, W_Int64Dtype): +class W_Int64Dtype(SignedIntegerArithmeticDtype, W_Int64Dtype): + pass + +W_UInt64Dtype = create_low_level_dtype( + num = 10, kind = UNSIGNEDLTR, name = "uint64", + aliases = ["Q", "uint64", "I8"], + applevel_types = [], + T = rffi.ULONGLONG, + valtype = rffi.ULONGLONG._type, + expected_size = 8, +) +class W_UInt64Dtype(UnsignedIntegerArithmeticDtype, W_UInt64Dtype): + pass + +if LONG_BIT == 32: + class W_LongDtype(W_Int32Dtype): + pass + + class W_ULongDtype(W_UInt32Dtype): + pass +else: + class W_LongDtype(W_Int64Dtype): + pass + + class W_ULongDtype(W_UInt64Dtype): + pass + +W_LongDtype.num = 7 +W_LongDtype.aliases = ["l"] +W_LongDtype.applevel_types = ["int"] +W_ULongDtype.num = 8 +W_ULongDtype.aliases = ["L"] + +W_Float32Dtype = create_low_level_dtype( + num = 11, kind = FLOATINGLTR, name = "float32", + aliases = ["f", "float32", "f4"], + applevel_types = [], + T = lltype.SingleFloat, + valtype = rarithmetic.r_singlefloat, + expected_size = 4, +) +class W_Float32Dtype(FloatArithmeticDtype, W_Float32Dtype): pass W_Float64Dtype = create_low_level_dtype( num = 12, kind = FLOATINGLTR, name = "float64", - aliases = [], + aliases = ["d", "float64", "f8"], applevel_types = ["float"], T = lltype.Float, valtype = float, expected_size = 8, ) class W_Float64Dtype(FloatArithmeticDtype, W_Float64Dtype): - def unwrap(self, space, w_item): - return self.adapt_val(space.float_w(space.float(w_item))) - - def str_format(self, item): - return float2string(self.unbox(item), 'g', rfloat.DTSF_STR_PRECISION) + pass ALL_DTYPES = [ W_BoolDtype, - W_Int8Dtype, W_Int16Dtype, W_Int32Dtype, W_Int64Dtype, - W_Float64Dtype + W_Int8Dtype, W_UInt8Dtype, W_Int16Dtype, W_UInt16Dtype, + W_Int32Dtype, W_UInt32Dtype, W_LongDtype, W_ULongDtype, + W_Int64Dtype, W_UInt64Dtype, + W_Float32Dtype, W_Float64Dtype, ] dtypes_by_alias = unrolling_iterable([ @@ -398,6 +491,7 @@ num = interp_attrproperty("num", cls=W_Dtype), kind = interp_attrproperty("kind", cls=W_Dtype), + itemsize = interp_attrproperty("num_bytes", cls=W_Dtype), shape = GetSetProperty(W_Dtype.descr_get_shape), ) W_Dtype.typedef.acceptable_as_base_class = False diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py --- a/pypy/module/micronumpy/interp_ufuncs.py +++ b/pypy/module/micronumpy/interp_ufuncs.py @@ -4,6 +4,7 @@ from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.module.micronumpy import interp_dtype, signature from pypy.rlib import jit +from pypy.rlib.rarithmetic import LONG_BIT from pypy.tool.sourcetools import func_with_new_name @@ -180,23 +181,56 @@ # Everything promotes to float, and bool promotes to everything. if dt2.kind == interp_dtype.FLOATINGLTR or dt1.kind == interp_dtype.BOOLLTR: + # Float32 + 8-bit int = Float64 + if dt2.num == 11 and dt1.num_bytes >= 4: + return space.fromcache(interp_dtype.W_Float64Dtype) return dt2 - assert False + # for now this means mixing signed and unsigned + if dt2.kind == interp_dtype.SIGNEDLTR: + # if dt2 has a greater number of bytes, then just go with it + if dt1.num_bytes < dt2.num_bytes: + return dt2 + # we need to promote both dtypes + dtypenum = dt2.num + 2 + else: + # increase to the next signed type (or to float) + dtypenum = dt2.num + 1 + # UInt64 + signed = Float64 + if dt2.num == 10: + dtypenum += 1 + newdtype = interp_dtype.ALL_DTYPES[dtypenum] + + if newdtype.num_bytes > dt2.num_bytes or newdtype.kind == interp_dtype.FLOATINGLTR: + return space.fromcache(newdtype) + else: + # we only promoted to long on 32-bit or to longlong on 64-bit + # this is really for dealing with the Long and Ulong dtypes + if LONG_BIT == 32: + dtypenum += 2 + else: + dtypenum += 3 + return space.fromcache(interp_dtype.ALL_DTYPES[dtypenum]) def find_unaryop_result_dtype(space, dt, promote_to_float=False, promote_bools=False, promote_to_largest=False): if promote_bools and (dt.kind == interp_dtype.BOOLLTR): return space.fromcache(interp_dtype.W_Int8Dtype) if promote_to_float: + if dt.kind == interp_dtype.FLOATINGLTR: + return dt + if dt.num >= 5: + return space.fromcache(interp_dtype.W_Float64Dtype) for bytes, dtype in interp_dtype.dtypes_by_num_bytes: - if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes >= dt.num_bytes: + if dtype.kind == interp_dtype.FLOATINGLTR and dtype.num_bytes > dt.num_bytes: return space.fromcache(dtype) if promote_to_largest: if dt.kind == interp_dtype.BOOLLTR or dt.kind == interp_dtype.SIGNEDLTR: return space.fromcache(interp_dtype.W_Int64Dtype) elif dt.kind == interp_dtype.FLOATINGLTR: return space.fromcache(interp_dtype.W_Float64Dtype) + elif dt.kind == interp_dtype.UNSIGNEDLTR: + return space.fromcache(interp_dtype.W_UInt64Dtype) else: assert False return dt @@ -205,15 +239,23 @@ w_type = space.type(w_obj) bool_dtype = space.fromcache(interp_dtype.W_BoolDtype) + long_dtype = space.fromcache(interp_dtype.W_LongDtype) int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype) if space.is_w(w_type, space.w_bool): - if current_guess is None: + if current_guess is None or current_guess is bool_dtype: return bool_dtype + return current_guess elif space.is_w(w_type, space.w_int): if (current_guess is None or current_guess is bool_dtype or - current_guess is int64_dtype): + current_guess is long_dtype): + return long_dtype + return current_guess + elif space.is_w(w_type, space.w_long): + if (current_guess is None or current_guess is bool_dtype or + current_guess is long_dtype or current_guess is int64_dtype): return int64_dtype + return current_guess return space.fromcache(interp_dtype.W_Float64Dtype) @@ -225,7 +267,9 @@ def impl(res_dtype, lvalue, rvalue): res = getattr(res_dtype, op_name)(lvalue, rvalue) if comparison_func: - res = space.fromcache(interp_dtype.W_BoolDtype).box(res) + booldtype = space.fromcache(interp_dtype.W_BoolDtype) + assert isinstance(booldtype, interp_dtype.W_BoolDtype) + res = booldtype.box(res) return res return func_with_new_name(impl, ufunc_name) @@ -278,7 +322,7 @@ identity = extra_kwargs.get("identity") if identity is not None: - identity = space.fromcache(interp_dtype.W_Int64Dtype).adapt_val(identity) + identity = space.fromcache(interp_dtype.W_LongDtype).adapt_val(identity) extra_kwargs["identity"] = identity func = ufunc_dtype_caller(space, ufunc_name, op_name, argcount, @@ -291,4 +335,4 @@ setattr(self, ufunc_name, ufunc) def get(space): - return space.fromcache(UfuncState) \ No newline at end of file + return space.fromcache(UfuncState) diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py --- a/pypy/module/micronumpy/test/test_base.py +++ b/pypy/module/micronumpy/test/test_base.py @@ -64,18 +64,46 @@ def test_unaryops(self, space): bool_dtype = space.fromcache(interp_dtype.W_BoolDtype) int8_dtype = space.fromcache(interp_dtype.W_Int8Dtype) + uint8_dtype = space.fromcache(interp_dtype.W_UInt8Dtype) + int16_dtype = space.fromcache(interp_dtype.W_Int16Dtype) + uint16_dtype = space.fromcache(interp_dtype.W_UInt16Dtype) int32_dtype = space.fromcache(interp_dtype.W_Int32Dtype) + uint32_dtype = space.fromcache(interp_dtype.W_UInt32Dtype) + long_dtype = space.fromcache(interp_dtype.W_LongDtype) + ulong_dtype = space.fromcache(interp_dtype.W_ULongDtype) + int64_dtype = space.fromcache(interp_dtype.W_Int64Dtype) + uint64_dtype = space.fromcache(interp_dtype.W_UInt64Dtype) + float32_dtype = space.fromcache(interp_dtype.W_Float32Dtype) float64_dtype = space.fromcache(interp_dtype.W_Float64Dtype) - # Normal rules, everythign returns itself + # Normal rules, everything returns itself assert find_unaryop_result_dtype(space, bool_dtype) is bool_dtype assert find_unaryop_result_dtype(space, int8_dtype) is int8_dtype + assert find_unaryop_result_dtype(space, uint8_dtype) is uint8_dtype + assert find_unaryop_result_dtype(space, int16_dtype) is int16_dtype + assert find_unaryop_result_dtype(space, uint16_dtype) is uint16_dtype assert find_unaryop_result_dtype(space, int32_dtype) is int32_dtype + assert find_unaryop_result_dtype(space, uint32_dtype) is uint32_dtype + assert find_unaryop_result_dtype(space, long_dtype) is long_dtype + assert find_unaryop_result_dtype(space, ulong_dtype) is ulong_dtype + assert find_unaryop_result_dtype(space, int64_dtype) is int64_dtype + assert find_unaryop_result_dtype(space, uint64_dtype) is uint64_dtype + assert find_unaryop_result_dtype(space, float32_dtype) is float32_dtype assert find_unaryop_result_dtype(space, float64_dtype) is float64_dtype # Coerce to floats, some of these will eventually be float16, or # whatever our smallest float type is. - assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float64_dtype - assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float64_dtype + assert find_unaryop_result_dtype(space, bool_dtype, promote_to_float=True) is float32_dtype # will be float16 if we ever put that in + assert find_unaryop_result_dtype(space, int8_dtype, promote_to_float=True) is float32_dtype # will be float16 if we ever put that in + assert find_unaryop_result_dtype(space, uint8_dtype, promote_to_float=True) is float32_dtype # will be float16 if we ever put that in + assert find_unaryop_result_dtype(space, int16_dtype, promote_to_float=True) is float32_dtype + assert find_unaryop_result_dtype(space, uint16_dtype, promote_to_float=True) is float32_dtype assert find_unaryop_result_dtype(space, int32_dtype, promote_to_float=True) is float64_dtype - assert find_unaryop_result_dtype(space, float64_dtype, promote_to_float=True) is float64_dtype \ No newline at end of file + assert find_unaryop_result_dtype(space, uint32_dtype, promote_to_float=True) is float64_dtype + assert find_unaryop_result_dtype(space, int64_dtype, promote_to_float=True) is float64_dtype + assert find_unaryop_result_dtype(space, uint64_dtype, promote_to_float=True) is float64_dtype + assert find_unaryop_result_dtype(space, float32_dtype, promote_to_float=True) is float32_dtype + assert find_unaryop_result_dtype(space, float64_dtype, promote_to_float=True) is float64_dtype + + # promote bools, happens with sign ufunc + assert find_unaryop_result_dtype(space, bool_dtype, promote_bools=True) is int8_dtype diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -17,6 +17,7 @@ from numpy import dtype assert dtype(bool).num == 0 + assert dtype(int).num == 7 assert dtype(long).num == 9 assert dtype(float).num == 12 @@ -81,6 +82,48 @@ assert isinstance(a[i], (int, long)) assert a[1] == 1 + def test_overflow(self): + from numpy import array, dtype + assert array([128], 'b')[0] == -128 + assert array([256], 'B')[0] == 0 + assert array([32768], 'h')[0] == -32768 + assert array([65536], 'H')[0] == 0 + if dtype('l').itemsize == 4: # 32-bit + raises(OverflowError, "array([2**32/2], 'i')") + raises(OverflowError, "array([2**32], 'I')") + raises(OverflowError, "array([2**64/2], 'q')") + raises(OverflowError, "array([2**64], 'Q')") + + def test_bool_binop_types(self): + from numpy import array, dtype + types = ('?','b','B','h','H','i','I','l','L','q','Q','f','d') + N = len(types) + a = array([True], '?') + for t in types: + assert (a + array([0], t)).dtype is dtype(t) + + def test_binop_types(self): + from numpy import array, dtype + tests = [('b','B','h'), ('b','h','h'), ('b','H','i'), ('b','i','i'), + ('b','l','l'), ('b','q','q'), ('b','Q','d'), ('B','h','h'), + ('B','H','H'), ('B','i','i'), ('B','I','I'), ('B','l','l'), + ('B','L','L'), ('B','q','q'), ('B','Q','Q'), ('h','H','i'), + ('h','i','i'), ('h','l','l'), ('h','q','q'), ('h','Q','d'), + ('H','i','i'), ('H','I','I'), ('H','l','l'), ('H','L','L'), + ('H','q','q'), ('H','Q','Q'), ('i','l','l'), ('i','q','q'), + ('i','Q','d'), ('I','L','L'), ('I','q','q'), ('I','Q','Q'), + ('q','Q','d'), ('b','f','f'), ('B','f','f'), ('h','f','f'), + ('H','f','f'), ('i','f','d'), ('I','f','d'), ('l','f','d'), + ('L','f','d'), ('q','f','d'), ('Q','f','d'), ('q','d','d')] + if dtype('i').itemsize == dtype('l').itemsize: # 32-bit + tests.extend([('b','I','q'), ('b','L','q'), ('h','I','q'), + ('h','L','q'), ('i','I','q'), ('i','L','q')]) + else: + tests.extend([('b','I','l'), ('b','L','d'), ('h','I','l'), + ('h','L','d'), ('i','I','l'), ('i','L','d')]) + for d1, d2, dout in tests: + assert (array([1], d1) + array([1], d2)).dtype is dtype(dout) + def test_add_int8(self): from numpy import array, dtype @@ -99,6 +142,15 @@ for i in range(5): assert b[i] == i * 2 + def test_add_uint32(self): + from numpy import array, dtype + + a = array(range(5), dtype="I") + b = a + a + assert b.dtype is dtype("I") + for i in range(5): + assert b[i] == i * 2 + def test_shape(self): from numpy import dtype diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -551,8 +551,10 @@ from numpy import array, dtype assert array([True]).dtype is dtype(bool) - assert array([True, 1]).dtype is dtype(long) - assert array([1, 2, 3]).dtype is dtype(long) + assert array([True, False]).dtype is dtype(bool) + assert array([True, 1]).dtype is dtype(int) + assert array([1, 2, 3]).dtype is dtype(int) + assert array([1L, 2, 3]).dtype is dtype(long) assert array([1.2, True]).dtype is dtype(float) assert array([1.2, 5]).dtype is dtype(float) assert array([]).dtype is dtype(float) diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py --- a/pypy/module/micronumpy/test/test_ufuncs.py +++ b/pypy/module/micronumpy/test/test_ufuncs.py @@ -234,7 +234,7 @@ assert b[i] == math.sin(a[i]) a = sin(array([True, False], dtype=bool)) - assert a[0] == sin(1) + assert abs(a[0] - sin(1)) < 1e-7 # a[0] will be less precise assert a[1] == 0.0 def test_cos(self): diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py --- a/pypy/module/micronumpy/test/test_zjit.py +++ b/pypy/module/micronumpy/test/test_zjit.py @@ -1,20 +1,24 @@ from pypy.jit.metainterp.test.support import LLJitMixin from pypy.module.micronumpy import interp_ufuncs, signature from pypy.module.micronumpy.compile import (numpy_compile, FakeSpace, - FloatObject) -from pypy.module.micronumpy.interp_dtype import W_Float64Dtype, W_Int64Dtype + FloatObject, IntObject) +from pypy.module.micronumpy.interp_dtype import W_Int32Dtype, W_Float64Dtype, W_Int64Dtype, W_UInt64Dtype from pypy.module.micronumpy.interp_numarray import (BaseArray, SingleDimArray, SingleDimSlice, scalar_w) from pypy.rlib.nonconst import NonConstant from pypy.rpython.annlowlevel import llstr from pypy.rpython.test.test_llinterp import interpret +import py + class TestNumpyJIt(LLJitMixin): def setup_class(cls): cls.space = FakeSpace() cls.float64_dtype = cls.space.fromcache(W_Float64Dtype) cls.int64_dtype = cls.space.fromcache(W_Int64Dtype) + cls.uint64_dtype = cls.space.fromcache(W_UInt64Dtype) + cls.int32_dtype = cls.space.fromcache(W_Int32Dtype) def test_add(self): def f(i): @@ -303,6 +307,31 @@ 'int_lt': 1, 'guard_true': 1, 'jump': 1}) assert result == 11.0 + def test_int32_sum(self): + py.test.skip("pypy/jit/backend/llimpl.py needs to be changed to " + "deal correctly with int dtypes for this test to " + "work. skip for now until someone feels up to the task") + space = self.space + float64_dtype = self.float64_dtype + int32_dtype = self.int32_dtype + + def f(n): + if NonConstant(False): + dtype = float64_dtype + else: + dtype = int32_dtype + ar = SingleDimArray(n, dtype=dtype) + i = 0 + while i < n: + ar.get_concrete().setitem(i, int32_dtype.box(7)) + i += 1 + v = ar.descr_add(space, ar).descr_sum(space) + assert isinstance(v, IntObject) + return v.intval + + result = self.meta_interp(f, [5], listops=True, backendopt=True) + assert result == f(5) + class TestTranslation(object): def test_compile(self): x = numpy_compile('aa+f*f/a-', 10) diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py --- a/pypy/rpython/lltypesystem/opimpl.py +++ b/pypy/rpython/lltypesystem/opimpl.py @@ -357,7 +357,7 @@ def op_cast_float_to_uint(f): assert type(f) is float - return r_uint(int(f)) + return r_uint(long(f)) def op_cast_float_to_longlong(f): assert type(f) is float @@ -369,7 +369,7 @@ def op_cast_float_to_ulonglong(f): assert type(f) is float - return r_ulonglong(r_longlong(f)) + return r_ulonglong(long(f)) def op_cast_char_to_int(b): assert type(b) is str and len(b) == 1 diff --git a/pypy/rpython/lltypesystem/test/test_lloperation.py b/pypy/rpython/lltypesystem/test/test_lloperation.py --- a/pypy/rpython/lltypesystem/test/test_lloperation.py +++ b/pypy/rpython/lltypesystem/test/test_lloperation.py @@ -5,6 +5,7 @@ from pypy.rpython.llinterp import LLFrame from pypy.rpython.test.test_llinterp import interpret from pypy.rpython import rclass +from pypy.rlib.rarithmetic import LONGLONG_MASK, r_longlong, r_ulonglong LL_INTERP_OPERATIONS = [name[3:] for name in LLFrame.__dict__.keys() if name.startswith('op_')] @@ -133,6 +134,14 @@ py.test.raises(TypeError, llop.getinteriorfield, lltype.Signed, s3, 'y') +def test_cast_float_to_ulonglong(): + f = 12350000000000000000.0 + py.test.raises(OverflowError, r_longlong, f) + r_longlong(f / 2) # does not raise OverflowError + # + x = llop.cast_float_to_ulonglong(lltype.UnsignedLongLong, f) + assert x == r_ulonglong(f) + # ___________________________________________________________________________ # This tests that the LLInterpreter and the LL_OPERATIONS tables are in sync. _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit