[pypy-commit] pypy numpy-fixes: cleanup and call __array_wrap__ where needed, also add missing subtype compatability on reduce()
mattip
noreply at buildbot.pypy.org
Sat May 9 22:36:13 CEST 2015
Author: mattip <matti.picus at gmail.com>
Branch: numpy-fixes
Changeset: r77263:ca9c0847ff2c
Date: 2015-05-09 23:08 +0300
http://bitbucket.org/pypy/pypy/changeset/ca9c0847ff2c/
Log: cleanup and call __array_wrap__ where needed, also add missing
subtype compatability on reduce()
diff --git a/pypy/module/micronumpy/base.py b/pypy/module/micronumpy/base.py
--- a/pypy/module/micronumpy/base.py
+++ b/pypy/module/micronumpy/base.py
@@ -3,16 +3,14 @@
from rpython.tool.pairtype import extendabletype
from pypy.module.micronumpy import support
-def wrap_impl(space, w_cls, w_instance, impl, postpone_finalize=False):
+def wrap_impl(space, w_cls, w_instance, impl):
if w_cls is None or space.is_w(w_cls, space.gettypefor(W_NDimArray)):
w_ret = W_NDimArray(impl)
else:
w_ret = space.allocate_instance(W_NDimArray, w_cls)
W_NDimArray.__init__(w_ret, impl)
assert isinstance(w_ret, W_NDimArray)
- if not postpone_finalize:
- # ufuncs need to call finalize after wrap
- space.call_method(w_ret, '__array_finalize__', w_instance)
+ space.call_method(w_ret, '__array_finalize__', w_instance)
return w_ret
@@ -35,8 +33,7 @@
self.implementation = implementation
@staticmethod
- def from_shape(space, shape, dtype, order='C', w_instance=None,
- zero=True, postpone_finalize=False):
+ def from_shape(space, shape, dtype, order='C', w_instance=None, zero=True):
from pypy.module.micronumpy import concrete, descriptor, boxes
from pypy.module.micronumpy.strides import calc_strides
strides, backstrides = calc_strides(shape, dtype.base, order)
@@ -45,8 +42,7 @@
if dtype == descriptor.get_dtype_cache(space).w_objectdtype:
impl.fill(space, boxes.W_ObjectBox(space.w_None))
if w_instance:
- return wrap_impl(space, space.type(w_instance), w_instance,
- impl, postpone_finalize=postpone_finalize)
+ return wrap_impl(space, space.type(w_instance), w_instance, impl)
return W_NDimArray(impl)
@staticmethod
diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py
--- a/pypy/module/micronumpy/loop.py
+++ b/pypy/module/micronumpy/loop.py
@@ -22,9 +22,8 @@
# handle array_priority
# w_lhs and w_rhs could be of different ndarray subtypes. Numpy does:
# 1. if __array_priorities__ are equal and one is an ndarray and the
- # other is a subtype, flip the order
- # 2. elif rhs.__array_priority__ is higher, flip the order
- # Now return the subtype of the first one
+ # other is a subtype, return a subtype
+ # 2. elif rhs.__array_priority__ is higher, return the type of rhs
w_ndarray = space.gettypefor(W_NDimArray)
lhs_type = space.type(w_lhs)
@@ -38,10 +37,15 @@
if not space.is_true(space.issubtype(rhs_type, w_ndarray)):
rhs_type = space.type(w_rhs.base)
rhs_for_subtype = w_rhs.base
+
+ w_highpriority = w_lhs
+ highpriority_subtype = lhs_for_subtype
if space.is_w(lhs_type, w_ndarray) and not space.is_w(rhs_type, w_ndarray):
- lhs_for_subtype = rhs_for_subtype
-
- # TODO handle __array_priorities__ and maybe flip the order
+ highpriority_subtype = rhs_for_subtype
+ w_highpriority = w_rhs
+ if support.is_rhs_priority_higher(space, w_lhs, w_rhs):
+ highpriority_subtype = rhs_for_subtype
+ w_highpriority = w_rhs
if w_lhs.get_size() == 1:
w_left = w_lhs.get_scalar_value().convert_to(space, calc_dtype)
@@ -61,7 +65,7 @@
if out is None:
w_ret = W_NDimArray.from_shape(space, shape, res_dtype,
- w_instance=lhs_for_subtype, postpone_finalize=True)
+ w_instance=highpriority_subtype)
else:
w_ret = out
out_iter, out_state = w_ret.create_iter(shape)
@@ -79,8 +83,7 @@
space, res_dtype))
out_state = out_iter.next(out_state)
if out is None:
- w_ret = space.call_method(w_rhs, '__array_wrap__', w_ret)
- space.call_method(w_ret, '__array_finalize__', lhs_for_subtype)
+ w_ret = space.call_method(w_highpriority, '__array_wrap__', w_ret)
return w_ret
call1_driver = jit.JitDriver(
@@ -93,8 +96,10 @@
obj_iter.track_index = False
if out is None:
- out = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
- out_iter, out_state = out.create_iter(shape)
+ w_ret = W_NDimArray.from_shape(space, shape, res_dtype, w_instance=w_obj)
+ else:
+ w_ret = out
+ out_iter, out_state = w_ret.create_iter(shape)
shapelen = len(shape)
while not out_iter.done(out_state):
call1_driver.jit_merge_point(shapelen=shapelen, func=func,
@@ -103,7 +108,9 @@
out_iter.setitem(out_state, func(calc_dtype, elem).convert_to(space, res_dtype))
out_state = out_iter.next(out_state)
obj_state = obj_iter.next(obj_state)
- return out
+ if out is None:
+ w_ret = space.call_method(w_obj, '__array_wrap__', w_ret)
+ return w_ret
call_many_to_one_driver = jit.JitDriver(
name='numpy_call_many_to_one',
diff --git a/pypy/module/micronumpy/support.py b/pypy/module/micronumpy/support.py
--- a/pypy/module/micronumpy/support.py
+++ b/pypy/module/micronumpy/support.py
@@ -152,3 +152,9 @@
def get_storage_as_int(storage, start=0):
return rffi.cast(lltype.Signed, storage) + start
+def is_rhs_priority_higher(space, w_lhs, w_rhs):
+ w_zero = space.wrap(0.0)
+ w_priority_l = space.findattr(w_lhs, space.wrap('__array_priority__')) or w_zero
+ w_priority_r = space.findattr(w_rhs, space.wrap('__array_priority__')) or w_zero
+ # XXX what is better, unwrapping values or space.gt?
+ return space.is_true(space.gt(w_priority_r, w_priority_l))
diff --git a/pypy/module/micronumpy/test/test_subtype.py b/pypy/module/micronumpy/test/test_subtype.py
--- a/pypy/module/micronumpy/test/test_subtype.py
+++ b/pypy/module/micronumpy/test/test_subtype.py
@@ -640,7 +640,7 @@
def __array_finalize__(self, obj):
self.output += 'In __array_finalize__:'
self.output += ' self is %s' % repr(self)
- self.output += ' obj is %s' % repr(obj)
+ self.output += ' obj is %s\n' % repr(obj)
print self.output
if obj is None: return
self.info = getattr(obj, 'info', None)
@@ -648,7 +648,7 @@
def __array_wrap__(self, out_arr, context=None):
self.output += 'In __array_wrap__:'
self.output += ' self is %s' % repr(self)
- self.output += ' arr is %s' % repr(out_arr)
+ self.output += ' arr is %r\n' % (out_arr,)
# then just call the parent
ret = np.ndarray.__array_wrap__(self, out_arr, context)
print 'wrap',self.output
@@ -657,15 +657,18 @@
obj = MySubClass(np.arange(5), info='spam')
assert obj.output.startswith('In __array_finalize')
obj.output = ''
- arr2 = np.arange(5)+1
+ print 'np.arange(5) + 1'
+ arr2 = np.arange(5) + 1
assert len(obj.output) < 1
+ print 'np.add(arr2, obj)'
ret = np.add(arr2, obj)
- print obj.output
assert obj.output.startswith('In __array_wrap')
assert 'finalize' not in obj.output
assert ret.info == 'spam'
+ print 'np.negative(obj)'
ret = np.negative(obj)
assert ret.info == 'spam'
+ print 'obj.sum()'
ret = obj.sum()
+ print type(ret)
assert ret.info == 'spam'
- assert False
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -13,7 +13,8 @@
from pypy.module.micronumpy.ctors import numpify
from pypy.module.micronumpy.nditer import W_NDIter, coalesce_iter
from pypy.module.micronumpy.strides import shape_agreement
-from pypy.module.micronumpy.support import _parse_signature, product, get_storage_as_int
+from pypy.module.micronumpy.support import (_parse_signature, product,
+ get_storage_as_int, is_rhs_priority_higher)
from rpython.rlib.rawstorage import (raw_storage_setitem, free_raw_storage,
alloc_raw_storage)
from rpython.rtyper.lltypesystem import rffi, lltype
@@ -286,8 +287,7 @@
axis, out, self.identity, cumulative,
temp)
if call__array_wrap__:
- pass
- # XXX if out is not type(obj) call __array_wrap__
+ out = space.call_method(w_obj, '__array_wrap__', out)
return out
if cumulative:
if out:
@@ -301,8 +301,7 @@
loop.compute_reduce_cumulative(space, obj, out, dtype, self.func,
self.identity)
if call__array_wrap__:
- pass
- # XXX if out is not a type(obj) call __array_wrap__
+ out = space.call_method(w_obj, '__array_wrap__', out)
return out
if out:
call__array_wrap__ = False
@@ -318,13 +317,16 @@
return out
if keepdims:
shape = [1] * len(obj_shape)
- out = W_NDimArray.from_shape(space, [1] * len(obj_shape), dtype,
- w_instance=obj)
+ out = W_NDimArray.from_shape(space, shape, dtype, w_instance=obj)
+ out.implementation.setitem(0, res)
+ res = out
+ elif not space.is_w(space.gettypefor(w_obj), space.gettypefor(W_NDimArray)):
+ # subtypes return a ndarray subtype, not a scalar
+ out = W_NDimArray.from_shape(space, [1], dtype, w_instance=obj)
out.implementation.setitem(0, res)
res = out
if call__array_wrap__:
- pass
- # XXX if res is not a type(obj) call __array_wrap__
+ res = space.call_method(w_obj, '__array_wrap__', res)
return res
def descr_outer(self, space, __args__):
@@ -494,11 +496,7 @@
# the __r<op>__ method and has __array_priority__ as
# an attribute (signalling it can handle ndarray's)
# and is not already an ndarray or a subtype of the same type.
- w_zero = space.wrap(0.0)
- w_priority_l = space.findattr(w_lhs, space.wrap('__array_priority__')) or w_zero
- w_priority_r = space.findattr(w_rhs, space.wrap('__array_priority__')) or w_zero
- # XXX what is better, unwrapping values or space.gt?
- r_greater = space.is_true(space.gt(w_priority_r, w_priority_l))
+ r_greater = is_rhs_priority_higher(space, w_lhs, w_rhs)
if r_greater and _has_reflected_op(space, w_rhs, self.name):
return space.w_NotImplemented
w_lhs = numpify(space, w_lhs)
More information about the pypy-commit
mailing list