Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r54002:9e2168564ef3 Date: 2012-03-26 19:39 +0200 http://bitbucket.org/pypy/pypy/changeset/9e2168564ef3/
Log: merge heads diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py b/pypy/interpreter/astcompiler/test/test_astbuilder.py --- a/pypy/interpreter/astcompiler/test/test_astbuilder.py +++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py @@ -10,16 +10,6 @@ from pypy.interpreter.astcompiler import ast, consts -try: - all -except NameError: - def all(iterable): - for x in iterable: - if not x: - return False - return True - - class TestAstBuilder: def setup_class(cls): diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py --- a/pypy/module/micronumpy/app_numpy.py +++ b/pypy/module/micronumpy/app_numpy.py @@ -16,7 +16,7 @@ a[i][i] = 1 return a -def sum(a,axis=None): +def sum(a,axis=None, out=None): '''sum(a, axis=None) Sum of array elements over a given axis. @@ -43,17 +43,17 @@ # TODO: add to doc (once it's implemented): cumsum : Cumulative sum of array elements. if not hasattr(a, "sum"): a = _numpypy.array(a) - return a.sum(axis) + return a.sum(axis=axis, out=out) -def min(a, axis=None): +def min(a, axis=None, out=None): if not hasattr(a, "min"): a = _numpypy.array(a) - return a.min(axis) + return a.min(axis=axis, out=out) -def max(a, axis=None): +def max(a, axis=None, out=None): if not hasattr(a, "max"): a = _numpypy.array(a) - return a.max(axis) + return a.max(axis=axis, out=out) def arange(start, stop=None, step=1, dtype=None): '''arange([start], stop[, step], dtype=None) diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -62,21 +62,24 @@ return space.wrap(dtype.itemtype.bool(self)) def _binop_impl(ufunc_name): - def impl(self, space, w_other): + def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other]) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + [self, w_other, w_out]) return func_with_new_name(impl, "binop_%s_impl" % ufunc_name) def _binop_right_impl(ufunc_name): - def impl(self, space, w_other): + def impl(self, space, w_other, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self]) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) def _unaryop_impl(ufunc_name): - def impl(self, space): + def impl(self, space, w_out=None): from pypy.module.micronumpy import interp_ufuncs - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self]) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + [self, w_out]) return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name) descr_add = _binop_impl("add") diff --git a/pypy/module/micronumpy/interp_iter.py b/pypy/module/micronumpy/interp_iter.py --- a/pypy/module/micronumpy/interp_iter.py +++ b/pypy/module/micronumpy/interp_iter.py @@ -269,7 +269,7 @@ def apply_transformations(self, arr, transformations): v = BaseIterator.apply_transformations(self, arr, transformations) - if len(arr.shape) == 1: + if len(arr.shape) == 1 and len(v.res_shape) == 1: return OneDimIterator(self.offset, self.strides[0], self.res_shape[0]) return v diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -83,8 +83,9 @@ return space.wrap(W_NDimArray(shape[:], dtype=dtype)) def _unaryop_impl(ufunc_name): - def impl(self, space): - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self]) + def impl(self, space, w_out=None): + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + [self, w_out]) return func_with_new_name(impl, "unaryop_%s_impl" % ufunc_name) descr_pos = _unaryop_impl("positive") @@ -93,8 +94,9 @@ descr_invert = _unaryop_impl("invert") def _binop_impl(ufunc_name): - def impl(self, space, w_other): - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [self, w_other]) + def impl(self, space, w_other, w_out=None): + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, + [self, w_other, w_out]) return func_with_new_name(impl, "binop_%s_impl" % ufunc_name) descr_add = _binop_impl("add") @@ -124,12 +126,12 @@ return space.newtuple([w_quotient, w_remainder]) def _binop_right_impl(ufunc_name): - def impl(self, space, w_other): + def impl(self, space, w_other, w_out=None): w_other = scalar_w(space, interp_ufuncs.find_dtype_for_scalar(space, w_other, self.find_dtype()), w_other ) - return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self]) + return getattr(interp_ufuncs.get(space), ufunc_name).call(space, [w_other, self, w_out]) return func_with_new_name(impl, "binop_right_%s_impl" % ufunc_name) descr_radd = _binop_right_impl("add") @@ -152,13 +154,21 @@ return space.newtuple([w_quotient, w_remainder]) def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False): - def impl(self, space, w_axis=None): + def impl(self, space, w_axis=None, w_out=None): if space.is_w(w_axis, space.w_None): axis = -1 else: axis = space.int_w(w_axis) + if space.is_w(w_out, space.w_None) or not w_out: + out = None + elif not isinstance(w_out, BaseArray): + raise OperationError(space.w_TypeError, space.wrap( + 'output must be an array')) + else: + out = w_out return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space, - self, True, promote_to_largest, axis) + self, True, promote_to_largest, axis, + False, out) return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name) descr_sum = _reduce_ufunc_impl("add") @@ -213,6 +223,7 @@ def descr_dot(self, space, w_other): other = convert_to_array(space, w_other) if isinstance(other, Scalar): + #Note: w_out is not modified, this is numpy compliant. return self.descr_mul(space, other) elif len(self.shape) < 2 and len(other.shape) < 2: w_res = self.descr_mul(space, other) @@ -514,14 +525,14 @@ ) return w_result - def descr_mean(self, space, w_axis=None): + def descr_mean(self, space, w_axis=None, w_out=None): if space.is_w(w_axis, space.w_None): w_axis = space.wrap(-1) w_denom = space.wrap(support.product(self.shape)) else: dim = space.int_w(w_axis) w_denom = space.wrap(self.shape[dim]) - return space.div(self.descr_sum_promote(space, w_axis), w_denom) + return space.div(self.descr_sum_promote(space, w_axis, w_out), w_denom) def descr_var(self, space, w_axis=None): return get_appbridge_cache(space).call_method(space, '_var', self, @@ -714,11 +725,12 @@ """ Class for representing virtual arrays, such as binary ops or ufuncs """ - def __init__(self, name, shape, res_dtype): + def __init__(self, name, shape, res_dtype, out_arg=None): BaseArray.__init__(self, shape) self.forced_result = None self.res_dtype = res_dtype self.name = name + self.res = out_arg self.size = support.product(self.shape) * res_dtype.get_size() def _del_sources(self): @@ -727,13 +739,18 @@ raise NotImplementedError def compute(self): - ra = ResultArray(self, self.shape, self.res_dtype) + ra = ResultArray(self, self.shape, self.res_dtype, self.res) loop.compute(ra) + if self.res: + broadcast_dims = len(self.res.shape) - len(self.shape) + chunks = [Chunk(0,0,0,0)] * broadcast_dims + \ + [Chunk(0, i, 1, i) for i in self.shape] + return Chunks(chunks).apply(self.res) return ra.left def force_if_needed(self): if self.forced_result is None: - self.forced_result = self.compute() + self.forced_result = self.compute().get_concrete() self._del_sources() def get_concrete(self): @@ -773,8 +790,9 @@ class Call1(VirtualArray): - def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values): - VirtualArray.__init__(self, name, shape, res_dtype) + def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, values, + out_arg=None): + VirtualArray.__init__(self, name, shape, res_dtype, out_arg) self.values = values self.size = values.size self.ufunc = ufunc @@ -786,6 +804,12 @@ def create_sig(self): if self.forced_result is not None: return self.forced_result.create_sig() + if self.shape != self.values.shape: + #This happens if out arg is used + return signature.BroadcastUfunc(self.ufunc, self.name, + self.calc_dtype, + self.values.create_sig(), + self.res.create_sig()) return signature.Call1(self.ufunc, self.name, self.calc_dtype, self.values.create_sig()) @@ -793,8 +817,9 @@ """ Intermediate class for performing binary operations. """ - def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right): - VirtualArray.__init__(self, name, shape, res_dtype) + def __init__(self, ufunc, name, shape, calc_dtype, res_dtype, left, right, + out_arg=None): + VirtualArray.__init__(self, name, shape, res_dtype, out_arg) self.ufunc = ufunc self.left = left self.right = right @@ -832,8 +857,13 @@ Call2.__init__(self, None, 'assign', shape, dtype, dtype, res, child) def create_sig(self): - return signature.ResultSignature(self.res_dtype, self.left.create_sig(), - self.right.create_sig()) + if self.left.shape != self.right.shape: + sig = signature.BroadcastResultSignature(self.res_dtype, + self.left.create_sig(), self.right.create_sig()) + else: + sig = signature.ResultSignature(self.res_dtype, + self.left.create_sig(), self.right.create_sig()) + return sig class ToStringArray(Call1): def __init__(self, child): @@ -842,9 +872,9 @@ self.s = StringBuilder(child.size * self.item_size) Call1.__init__(self, None, 'tostring', child.shape, dtype, dtype, child) - self.res = W_NDimArray([1], dtype, 'C') - self.res_casted = rffi.cast(rffi.CArrayPtr(lltype.Char), - self.res.storage) + self.res_str = W_NDimArray([1], dtype, order='C') + self.res_str_casted = rffi.cast(rffi.CArrayPtr(lltype.Char), + self.res_str.storage) def create_sig(self): return signature.ToStringSignature(self.calc_dtype, @@ -950,7 +980,7 @@ def setitem(self, item, value): self.invalidated() - self.dtype.setitem(self, item, value) + self.dtype.setitem(self, item, value.convert_to(self.dtype)) def calc_strides(self, shape): dtype = self.find_dtype() 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 @@ -28,26 +28,38 @@ return self.identity def descr_call(self, space, __args__): + from interp_numarray import BaseArray args_w, kwds_w = __args__.unpack() # it occurs to me that we don't support any datatypes that # require casting, change it later when we do kwds_w.pop('casting', None) w_subok = kwds_w.pop('subok', None) w_out = kwds_w.pop('out', space.w_None) - if ((w_subok is not None and space.is_true(w_subok)) or - not space.is_w(w_out, space.w_None)): + # Setup a default value for out + if space.is_w(w_out, space.w_None): + out = None + else: + out = w_out + if (w_subok is not None and space.is_true(w_subok)): raise OperationError(space.w_NotImplementedError, space.wrap("parameters unsupported")) if kwds_w or len(args_w) < self.argcount: raise OperationError(space.w_ValueError, space.wrap("invalid number of arguments") ) - elif len(args_w) > self.argcount: - # The extra arguments should actually be the output array, but we - # don't support that yet. + elif (len(args_w) > self.argcount and out is not None) or \ + (len(args_w) > self.argcount + 1): raise OperationError(space.w_TypeError, space.wrap("invalid number of arguments") ) + # Override the default out value, if it has been provided in w_wargs + if len(args_w) > self.argcount: + out = args_w[-1] + else: + args_w = args_w[:] + [out] + if out is not None and not isinstance(out, BaseArray): + raise OperationError(space.w_TypeError, space.wrap( + 'output must be an array')) return self.call(space, args_w) @unwrap_spec(skipna=bool, keepdims=bool) @@ -105,28 +117,33 @@ array([[ 1, 5], [ 9, 13]]) """ - if not space.is_w(w_out, space.w_None): - raise OperationError(space.w_NotImplementedError, space.wrap( - "out not supported")) + from pypy.module.micronumpy.interp_numarray import BaseArray if w_axis is None: axis = 0 elif space.is_w(w_axis, space.w_None): axis = -1 else: axis = space.int_w(w_axis) - return self.reduce(space, w_obj, False, False, axis, keepdims) + if space.is_w(w_out, space.w_None): + out = None + elif not isinstance(w_out, BaseArray): + raise OperationError(space.w_TypeError, space.wrap( + 'output must be an array')) + else: + out = w_out + return self.reduce(space, w_obj, False, False, axis, keepdims, out) - def reduce(self, space, w_obj, multidim, promote_to_largest, dim, - keepdims=False): + def reduce(self, space, w_obj, multidim, promote_to_largest, axis, + keepdims=False, out=None): from pypy.module.micronumpy.interp_numarray import convert_to_array, \ - Scalar, ReduceArray + Scalar, ReduceArray, W_NDimArray if self.argcount != 2: raise OperationError(space.w_ValueError, space.wrap("reduce only " "supported for binary functions")) assert isinstance(self, W_Ufunc2) obj = convert_to_array(space, w_obj) - if dim >= len(obj.shape): - raise OperationError(space.w_ValueError, space.wrap("axis(=%d) out of bounds" % dim)) + if axis >= len(obj.shape): + raise OperationError(space.w_ValueError, space.wrap("axis(=%d) out of bounds" % axis)) if isinstance(obj, Scalar): raise OperationError(space.w_TypeError, space.wrap("cannot reduce " "on a scalar")) @@ -144,21 +161,55 @@ if self.identity is None and size == 0: raise operationerrfmt(space.w_ValueError, "zero-size array to " "%s.reduce without identity", self.name) - if shapelen > 1 and dim >= 0: - return self.do_axis_reduce(obj, dtype, dim, keepdims) - arr = ReduceArray(self.func, self.name, self.identity, obj, dtype) - return loop.compute(arr) + if shapelen > 1 and axis >= 0: + if keepdims: + shape = obj.shape[:axis] + [1] + obj.shape[axis + 1:] + else: + shape = obj.shape[:axis] + obj.shape[axis + 1:] + if out: + #Test for shape agreement + if len(out.shape) > len(shape): + raise operationerrfmt(space.w_ValueError, + 'output parameter for reduction operation %s' + + ' has too many dimensions', self.name) + elif len(out.shape) < len(shape): + raise operationerrfmt(space.w_ValueError, + 'output parameter for reduction operation %s' + + ' does not have enough dimensions', self.name) + elif out.shape != shape: + raise operationerrfmt(space.w_ValueError, + 'output parameter shape mismatch, expecting [%s]' + + ' , got [%s]', + ",".join([str(x) for x in shape]), + ",".join([str(x) for x in out.shape]), + ) + #Test for dtype agreement, perhaps create an itermediate + #if out.dtype != dtype: + # raise OperationError(space.w_TypeError, space.wrap( + # "mismatched dtypes")) + return self.do_axis_reduce(obj, out.find_dtype(), axis, out) + else: + result = W_NDimArray(shape, dtype) + return self.do_axis_reduce(obj, dtype, axis, result) + if out: + if len(out.shape)>0: + raise operationerrfmt(space.w_ValueError, "output parameter " + "for reduction operation %s has too many" + " dimensions",self.name) + arr = ReduceArray(self.func, self.name, self.identity, obj, + out.find_dtype()) + val = loop.compute(arr) + assert isinstance(out, Scalar) + out.value = val + else: + arr = ReduceArray(self.func, self.name, self.identity, obj, dtype) + val = loop.compute(arr) + return val - def do_axis_reduce(self, obj, dtype, dim, keepdims): - from pypy.module.micronumpy.interp_numarray import AxisReduce,\ - W_NDimArray - if keepdims: - shape = obj.shape[:dim] + [1] + obj.shape[dim + 1:] - else: - shape = obj.shape[:dim] + obj.shape[dim + 1:] - result = W_NDimArray(shape, dtype) + def do_axis_reduce(self, obj, dtype, axis, result): + from pypy.module.micronumpy.interp_numarray import AxisReduce arr = AxisReduce(self.func, self.name, self.identity, obj.shape, dtype, - result, obj, dim) + result, obj, axis) loop.compute(arr) return arr.left @@ -176,24 +227,55 @@ self.bool_result = bool_result def call(self, space, args_w): - from pypy.module.micronumpy.interp_numarray import (Call1, - convert_to_array, Scalar) - - [w_obj] = args_w + from pypy.module.micronumpy.interp_numarray import (Call1, BaseArray, + convert_to_array, Scalar, shape_agreement) + if len(args_w)<2: + [w_obj] = args_w + out = None + else: + [w_obj, out] = args_w + if space.is_w(out, space.w_None): + out = None w_obj = convert_to_array(space, w_obj) calc_dtype = find_unaryop_result_dtype(space, w_obj.find_dtype(), promote_to_float=self.promote_to_float, promote_bools=self.promote_bools) - if self.bool_result: + if out: + if not isinstance(out, BaseArray): + raise OperationError(space.w_TypeError, space.wrap( + 'output must be an array')) + res_dtype = out.find_dtype() + elif self.bool_result: res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype else: res_dtype = calc_dtype if isinstance(w_obj, Scalar): - return space.wrap(self.func(calc_dtype, w_obj.value.convert_to(calc_dtype))) - - w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, res_dtype, - w_obj) + arr = self.func(calc_dtype, w_obj.value.convert_to(calc_dtype)) + if isinstance(out,Scalar): + out.value=arr + elif isinstance(out, BaseArray): + out.fill(space, arr) + else: + out = arr + return space.wrap(out) + if out: + assert isinstance(out, BaseArray) # For translation + broadcast_shape = shape_agreement(space, w_obj.shape, out.shape) + if not broadcast_shape or broadcast_shape != out.shape: + raise operationerrfmt(space.w_ValueError, + 'output parameter shape mismatch, could not broadcast [%s]' + + ' to [%s]', + ",".join([str(x) for x in w_obj.shape]), + ",".join([str(x) for x in out.shape]), + ) + w_res = Call1(self.func, self.name, out.shape, calc_dtype, + res_dtype, w_obj, out) + #Force it immediately + w_res.get_concrete() + else: + w_res = Call1(self.func, self.name, w_obj.shape, calc_dtype, + res_dtype, w_obj) w_obj.add_invalidates(w_res) return w_res @@ -212,32 +294,61 @@ def call(self, space, args_w): from pypy.module.micronumpy.interp_numarray import (Call2, - convert_to_array, Scalar, shape_agreement) - - [w_lhs, w_rhs] = args_w + convert_to_array, Scalar, shape_agreement, BaseArray) + if len(args_w)>2: + [w_lhs, w_rhs, w_out] = args_w + else: + [w_lhs, w_rhs] = args_w + w_out = None w_lhs = convert_to_array(space, w_lhs) w_rhs = convert_to_array(space, w_rhs) - calc_dtype = find_binop_result_dtype(space, - w_lhs.find_dtype(), w_rhs.find_dtype(), - int_only=self.int_only, - promote_to_float=self.promote_to_float, - promote_bools=self.promote_bools, - ) + if space.is_w(w_out, space.w_None) or w_out is None: + out = None + calc_dtype = find_binop_result_dtype(space, + w_lhs.find_dtype(), w_rhs.find_dtype(), + int_only=self.int_only, + promote_to_float=self.promote_to_float, + promote_bools=self.promote_bools, + ) + elif not isinstance(w_out, BaseArray): + raise OperationError(space.w_TypeError, space.wrap( + 'output must be an array')) + else: + out = w_out + calc_dtype = out.find_dtype() if self.comparison_func: res_dtype = interp_dtype.get_dtype_cache(space).w_booldtype else: res_dtype = calc_dtype if isinstance(w_lhs, Scalar) and isinstance(w_rhs, Scalar): - return space.wrap(self.func(calc_dtype, + arr = self.func(calc_dtype, w_lhs.value.convert_to(calc_dtype), w_rhs.value.convert_to(calc_dtype) - )) + ) + if isinstance(out,Scalar): + out.value=arr + elif isinstance(out, BaseArray): + out.fill(space, arr) + else: + out = arr + return space.wrap(out) new_shape = shape_agreement(space, w_lhs.shape, w_rhs.shape) + # Test correctness of out.shape + if out and out.shape != shape_agreement(space, new_shape, out.shape): + raise operationerrfmt(space.w_ValueError, + 'output parameter shape mismatch, could not broadcast [%s]' + + ' to [%s]', + ",".join([str(x) for x in new_shape]), + ",".join([str(x) for x in out.shape]), + ) w_res = Call2(self.func, self.name, new_shape, calc_dtype, - res_dtype, w_lhs, w_rhs) + res_dtype, w_lhs, w_rhs, out) w_lhs.add_invalidates(w_res) w_rhs.add_invalidates(w_res) + if out: + #out.add_invalidates(w_res) #causes a recursion loop + w_res.get_concrete() return w_res diff --git a/pypy/module/micronumpy/signature.py b/pypy/module/micronumpy/signature.py --- a/pypy/module/micronumpy/signature.py +++ b/pypy/module/micronumpy/signature.py @@ -216,13 +216,14 @@ return self.child.eval(frame, arr.child) class Call1(Signature): - _immutable_fields_ = ['unfunc', 'name', 'child', 'dtype'] + _immutable_fields_ = ['unfunc', 'name', 'child', 'res', 'dtype'] - def __init__(self, func, name, dtype, child): + def __init__(self, func, name, dtype, child, res=None): self.unfunc = func self.child = child self.name = name self.dtype = dtype + self.res = res def hash(self): return compute_hash(self.name) ^ intmask(self.child.hash() << 1) @@ -256,6 +257,29 @@ v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype) return self.unfunc(arr.calc_dtype, v) + +class BroadcastUfunc(Call1): + def _invent_numbering(self, cache, allnumbers): + self.res._invent_numbering(cache, allnumbers) + self.child._invent_numbering(new_cache(), allnumbers) + + def debug_repr(self): + return 'BroadcastUfunc(%s, %s)' % (self.name, self.child.debug_repr()) + + def _create_iter(self, iterlist, arraylist, arr, transforms): + from pypy.module.micronumpy.interp_numarray import Call1 + + assert isinstance(arr, Call1) + vtransforms = transforms + [BroadcastTransform(arr.values.shape)] + self.child._create_iter(iterlist, arraylist, arr.values, vtransforms) + self.res._create_iter(iterlist, arraylist, arr.res, transforms) + + def eval(self, frame, arr): + from pypy.module.micronumpy.interp_numarray import Call1 + assert isinstance(arr, Call1) + v = self.child.eval(frame, arr.values).convert_to(arr.calc_dtype) + return self.unfunc(arr.calc_dtype, v) + class Call2(Signature): _immutable_fields_ = ['binfunc', 'name', 'calc_dtype', 'left', 'right'] @@ -316,7 +340,17 @@ assert isinstance(arr, ResultArray) offset = frame.get_final_iter().offset - arr.left.setitem(offset, self.right.eval(frame, arr.right)) + val = self.right.eval(frame, arr.right) + arr.left.setitem(offset, val) + +class BroadcastResultSignature(ResultSignature): + def _create_iter(self, iterlist, arraylist, arr, transforms): + from pypy.module.micronumpy.interp_numarray import ResultArray + + assert isinstance(arr, ResultArray) + rtransforms = transforms + [BroadcastTransform(arr.left.shape)] + self.left._create_iter(iterlist, arraylist, arr.left, transforms) + self.right._create_iter(iterlist, arraylist, arr.right, rtransforms) class ToStringSignature(Call1): def __init__(self, dtype, child): @@ -327,10 +361,10 @@ from pypy.module.micronumpy.interp_numarray import ToStringArray assert isinstance(arr, ToStringArray) - arr.res.setitem(0, self.child.eval(frame, arr.values).convert_to( + arr.res_str.setitem(0, self.child.eval(frame, arr.values).convert_to( self.dtype)) for i in range(arr.item_size): - arr.s.append(arr.res_casted[i]) + arr.s.append(arr.res_str_casted[i]) class BroadcastLeft(Call2): def _invent_numbering(self, cache, allnumbers): @@ -455,6 +489,5 @@ cur = arr.left.getitem(iterator.offset) value = self.binfunc(self.calc_dtype, cur, v) arr.left.setitem(iterator.offset, value) - def debug_repr(self): return 'AxisReduceSig(%s, %s)' % (self.name, self.right.debug_repr()) 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 @@ -995,6 +995,10 @@ assert a.sum() == 5 raises(TypeError, 'a.sum(2, 3)') + d = array(0.) + b = a.sum(out=d) + assert b == d + assert isinstance(b, float) def test_reduce_nd(self): from numpypy import arange, array, multiply @@ -1495,8 +1499,6 @@ a = array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13, 14]]) b = a[::2] - print a - print b assert (b == [[1, 2], [5, 6], [9, 10], [13, 14]]).all() c = b + b assert c[1][1] == 12 diff --git a/pypy/module/micronumpy/test/test_outarg.py b/pypy/module/micronumpy/test/test_outarg.py new file mode 100644 --- /dev/null +++ b/pypy/module/micronumpy/test/test_outarg.py @@ -0,0 +1,126 @@ +import py +from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest + +class AppTestOutArg(BaseNumpyAppTest): + def test_reduce_out(self): + from numpypy import arange, zeros, array + a = arange(15).reshape(5, 3) + b = arange(12).reshape(4,3) + c = a.sum(0, out=b[1]) + assert (c == [30, 35, 40]).all() + assert (c == b[1]).all() + raises(ValueError, 'a.prod(0, out=arange(10))') + a=arange(12).reshape(3,2,2) + raises(ValueError, 'a.sum(0, out=arange(12).reshape(3,2,2))') + raises(ValueError, 'a.sum(0, out=arange(3))') + c = array([-1, 0, 1]).sum(out=zeros([], dtype=bool)) + #You could argue that this should product False, but + # that would require an itermediate result. Cpython numpy + # gives True. + assert c == True + a = array([[-1, 0, 1], [1, 0, -1]]) + c = a.sum(0, out=zeros((3,), dtype=bool)) + assert (c == [True, False, True]).all() + c = a.sum(1, out=zeros((2,), dtype=bool)) + assert (c == [True, True]).all() + + def test_reduce_intermediary(self): + from numpypy import arange, array + a = arange(15).reshape(5, 3) + b = array(range(3), dtype=bool) + c = a.prod(0, out=b) + assert(b == [False, True, True]).all() + + def test_ufunc_out(self): + from _numpypy import array, negative, zeros, sin + from math import sin as msin + a = array([[1, 2], [3, 4]]) + c = zeros((2,2,2)) + b = negative(a + a, out=c[1]) + #test for view, and also test that forcing out also forces b + assert (c[:, :, 1] == [[0, 0], [-4, -8]]).all() + assert (b == [[-2, -4], [-6, -8]]).all() + #Test broadcast, type promotion + b = negative(3, out=a) + assert (a == -3).all() + c = zeros((2, 2), dtype=float) + b = negative(3, out=c) + assert b.dtype.kind == c.dtype.kind + assert b.shape == c.shape + a = array([1, 2]) + b = sin(a, out=c) + assert(c == [[msin(1), msin(2)]] * 2).all() + b = sin(a, out=c+c) + assert (c == b).all() + + #Test shape agreement + a = zeros((3,4)) + b = zeros((3,5)) + raises(ValueError, 'negative(a, out=b)') + b = zeros((1,4)) + raises(ValueError, 'negative(a, out=b)') + + def test_binfunc_out(self): + from _numpypy import array, add + a = array([[1, 2], [3, 4]]) + out = array([[1, 2], [3, 4]]) + c = add(a, a, out=out) + assert (c == out).all() + assert c.shape == a.shape + assert c.dtype is a.dtype + c[0,0] = 100 + assert out[0, 0] == 100 + out[:] = 100 + raises(ValueError, 'c = add(a, a, out=out[1])') + c = add(a[0], a[1], out=out[1]) + assert (c == out[1]).all() + assert (c == [4, 6]).all() + assert (out[0] == 100).all() + c = add(a[0], a[1], out=out) + assert (c == out[1]).all() + assert (c == out[0]).all() + out = array(16, dtype=int) + b = add(10, 10, out=out) + assert b==out + assert b.dtype == out.dtype + + def test_applevel(self): + from _numpypy import array, sum, max, min + a = array([[1, 2], [3, 4]]) + out = array([[0, 0], [0, 0]]) + c = sum(a, axis=0, out=out[0]) + assert (c == [4, 6]).all() + assert (c == out[0]).all() + assert (c != out[1]).all() + c = max(a, axis=1, out=out[0]) + assert (c == [2, 4]).all() + assert (c == out[0]).all() + assert (c != out[1]).all() + + def test_ufunc_cast(self): + from _numpypy import array, negative, add, sum + a = array(16, dtype = int) + c = array(0, dtype = float) + b = negative(a, out=c) + assert b == c + b = add(a, a, out=c) + assert b == c + d = array([16, 16], dtype=int) + b = sum(d, out=c) + assert b == c + try: + from _numpypy import version + v = version.version.split('.') + except: + v = ['1', '6', '0'] # numpypy is api compatable to what version? + if v[0]<'2': + b = negative(c, out=a) + assert b == a + b = add(c, c, out=a) + assert b == a + b = sum(array([16, 16], dtype=float), out=a) + assert b == a + else: + cast_error = raises(TypeError, negative, c, a) + assert str(cast_error.value) == \ + "Cannot cast ufunc negative output from dtype('float64') to dtype('int64') with casting rule 'same_kind'" 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 @@ -131,7 +131,7 @@ # bogus. We need to improve the situation somehow. self.check_simple_loop({'getinteriorfield_raw': 2, 'setinteriorfield_raw': 1, - 'arraylen_gc': 1, + 'arraylen_gc': 2, 'guard_true': 1, 'int_lt': 1, 'jump': 1, diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py --- a/pypy/objspace/flow/test/test_objspace.py +++ b/pypy/objspace/flow/test/test_objspace.py @@ -1,6 +1,6 @@ from __future__ import with_statement import new -import py +import py, sys from pypy.objspace.flow.model import Constant, Block, Link, Variable from pypy.objspace.flow.model import mkentrymap, c_last_exception from pypy.interpreter.argument import Arguments @@ -893,6 +893,8 @@ """ Tests code generated by pypy-c compiled with BUILD_LIST_FROM_ARG bytecode """ + if sys.version_info < (2, 7): + py.test.skip("2.7 only test") self.patch_opcodes('BUILD_LIST_FROM_ARG') try: def f(): diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -58,33 +58,13 @@ binaries = [(pypy_c, rename_pypy_c)] # if sys.platform == 'win32': - #What runtime do we need? - msvc_runtime = 'msvcr80.dll' #default is studio 2005 vc8 - try: - import subprocess - out,err = subprocess.Popen([str(pypy_c), '-c', - 'import sys; print sys.version'], - stdout=subprocess.PIPE).communicate() - indx=out.find('MSC v.') + 6 - if indx> 10: - if out[indx:].startswith('1600'): - msvc_runtime = 'msvcr100.dll' #studio 2010 vc10 - elif out[indx:].startwith('1500'): - msvc_runtime = 'msvcr90.dll' #studio 2009 vc9 - elif out[indx:].startswith('1400'): - msvc_runtime = 'msvcr80.dll' #studio 2005 vc8 - else: - print 'Cannot determine runtime dll for pypy' \ - ' version "%s"'%out - else: - print 'Cannot determine runtime dll for pypy' \ - ' version "%s"'%out - except : - pass + #Don't include a mscvrXX.dll, users should get their own. + #Instructions are provided on the website. + # Can't rename a DLL: it is always called 'libpypy-c.dll' for extra in ['libpypy-c.dll', - 'libexpat.dll', 'sqlite3.dll', msvc_runtime, + 'libexpat.dll', 'sqlite3.dll', 'libeay32.dll', 'ssleay32.dll']: p = pypy_c.dirpath().join(extra) if not p.check(): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit