Author: mattip
Branch: numpypy-axisops
Changeset: r50955:af55619e4fb9
Date: 2011-12-30 16:37 +0200
http://bitbucket.org/pypy/pypy/changeset/af55619e4fb9/
Log: rework default arg, tests finally pass, cleanup
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
@@ -113,8 +113,8 @@
dim, start)
class AxisIterator(object):
- """ This object will return offsets of each start of a stride on the
- desired dimension, starting at "start" which is an index along
+ """ This object will return offsets of each start of a stride on the
+ desired dimension, starting at "start" which is an index along
each axis
"""
def __init__(self, arr_start, strides, backstrides, shape, dim, start):
@@ -131,6 +131,7 @@
if len(start) == len(shape):
for i in range(len(start)):
self.offset += strides[i] * start[i]
+
def next(self, shapelen):
#shapelen will always be one less than self.shapelen
offset = self.offset
@@ -159,4 +160,3 @@
res.dim = self.dim
res.done = self.done
return res
-
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
@@ -283,9 +283,9 @@
descr_rmod = _binop_right_impl("mod")
def _reduce_ufunc_impl(ufunc_name, promote_to_largest=False):
- def impl(self, space, w_dim=-1):
- if isinstance(w_dim,int):
- w_dim = space.wrap(w_dim)
+ def impl(self, space, w_dim=None):
+ if space.is_w(w_dim, space.w_None):
+ w_dim = space.wrap(-1)
return getattr(interp_ufuncs.get(space), ufunc_name).reduce(space,
self, True, promote_to_largest, w_dim)
return func_with_new_name(impl, "reduce_%s_impl" % ufunc_name)
@@ -376,7 +376,7 @@
else:
w_res = self.descr_mul(space, w_other)
assert isinstance(w_res, BaseArray)
- return w_res.descr_sum(space)
+ return w_res.descr_sum(space, space.wrap(-1))
def get_concrete(self):
raise NotImplementedError
@@ -560,8 +560,11 @@
)
return w_result
- def descr_mean(self, space):
- return space.div(self.descr_sum_promote(space), space.wrap(self.size))
+ def descr_mean(self, space, w_dim=None):
+ if space.is_w(w_dim, space.w_None):
+ w_dim = space.wrap(-1)
+ return space.div(self.descr_sum_promote(space, w_dim),
+ space.wrap(self.size))
def descr_nonzero(self, space):
if self.size > 1:
@@ -672,7 +675,7 @@
self.name = name
def _del_sources(self):
- # Function for deleting references to source arrays,
+ # Function for deleting references to source arrays,
# to allow garbage-collecting them
raise NotImplementedError
@@ -739,9 +742,10 @@
def _del_sources(self):
self.child = None
+
class Reduce(VirtualArray):
def __init__(self, ufunc, name, dim, res_dtype, values, identity=None):
- shape=values.shape[0:dim] + values.shape[dim+1:len(values.shape)]
+ shape = values.shape[0:dim] + values.shape[dim+1:len(values.shape)]
VirtualArray.__init__(self, name, shape, res_dtype)
self.values = values
self.size = 1
@@ -770,7 +774,7 @@
shapelen = len(result.shape)
objlen = len(self.values.shape)
target_len = self.values.shape[self.dim]
- #sig = self.find_sig(result.shape) ##Don't do this, it causes an
infinite recursion
+ #sig = self.find_sig(result.shape) ##Don't do this, infinite recursion
sig = self.create_sig(result.shape)
ri = ArrayIterator(result.size)
si = axis_iter_from_arr(self.values, self.dim)
@@ -778,12 +782,12 @@
chunks = []
#for i in range(objlen - 1, -1, -1):
for i in range(objlen):
- if i==self.dim:
+ if i == self.dim:
chunks.append((0, target_len, 1, target_len))
else:
chunks.append((si.indices[i], 0, 0, 1))
- frame = sig.create_frame(self.values,
- res_shape = [target_len], chunks = [chunks,])
+ frame = sig.create_frame(self.values,
+ res_shape=[target_len], chunks = [chunks, ])
if self.identity is None:
value = sig.eval(frame, self.values).convert_to(dtype)
frame.next(shapelen)
@@ -800,7 +804,6 @@
return result
-
class Call1(VirtualArray):
def __init__(self, ufunc, name, shape, res_dtype, values):
VirtualArray.__init__(self, name, shape, res_dtype)
@@ -930,10 +933,9 @@
builder.append('\n' + indent)
else:
builder.append(indent)
- # create_slice requires len(chunks) > 1 in order to reduce
- # shape
- view = self.create_slice([(i, 0, 0, 1), (0, self.shape[1],
1, self.shape[1])]).get_concrete()
- view.to_str(space, comma, builder, indent=indent + ' ',
use_ellipsis=use_ellipsis)
+ view = self.create_slice([(i, 0, 0, 1)]).get_concrete()
+ view.to_str(space, comma, builder, indent=indent + ' ',
+ use_ellipsis=use_ellipsis)
builder.append('\n' + indent + '..., ')
i = self.shape[0] - 3
while i < self.shape[0]:
@@ -945,10 +947,9 @@
builder.append('\n' + indent)
else:
builder.append(indent)
- # create_slice requires len(chunks) > 1 in order to reduce
- # shape
- view = self.create_slice([(i, 0, 0, 1), (0, self.shape[1], 1,
self.shape[1])]).get_concrete()
- view.to_str(space, comma, builder, indent=indent + ' ',
use_ellipsis=use_ellipsis)
+ view = self.create_slice([(i, 0, 0, 1)]).get_concrete()
+ view.to_str(space, comma, builder, indent=indent + ' ',
+ use_ellipsis=use_ellipsis)
i += 1
elif ndims == 1:
spacer = ',' * comma + ' '
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
@@ -10,12 +10,13 @@
from pypy.tool.sourcetools import func_with_new_name
reduce_driver = jit.JitDriver(
- greens = ['shapelen', "sig"],
- virtualizables = ["frame"],
- reds = ["frame", "self", "dtype", "value", "obj"],
+ greens=['shapelen', "sig"],
+ virtualizables=["frame"],
+ reds=["frame", "self", "dtype", "value", "obj"],
get_printable_location=new_printable_location('reduce'),
)
+
class W_Ufunc(Wrappable):
_attrs_ = ["name", "promote_to_float", "promote_bools", "identity"]
_immutable_fields_ = ["promote_to_float", "promote_bools", "name"]
@@ -51,23 +52,23 @@
def descr_reduce(self, space, w_obj, w_dim=0):
'''reduce(...)
reduce(a, axis=0)
-
+
Reduces `a`'s dimension by one, by applying ufunc along one axis.
-
+
Let :math:`a.shape = (N_0, ..., N_i, ..., N_{M-1})`. Then
:math:`ufunc.reduce(a, axis=i)[k_0, ..,k_{i-1}, k_{i+1}, .., k_{M-1}]` =
the result of iterating `j` over :math:`range(N_i)`, cumulatively applying
ufunc to each :math:`a[k_0, ..,k_{i-1}, j, k_{i+1}, .., k_{M-1}]`.
For a one-dimensional array, reduce produces results equivalent to:
::
-
+
r = op.identity # op = ufunc
for i in xrange(len(A)):
r = op(r, A[i])
return r
-
+
For example, add.reduce() is equivalent to sum().
-
+
Parameters
----------
a : array_like
@@ -79,9 +80,9 @@
--------
>>> np.multiply.reduce([2,3,5])
30
-
+
A multi-dimensional array example:
-
+
>>> X = np.arange(8).reshape((2,2,2))
>>> X
array([[[0, 1],
@@ -104,7 +105,8 @@
return self.reduce(space, w_obj, False, False, w_dim)
def reduce(self, space, w_obj, multidim, promote_to_largest, w_dim):
- from pypy.module.micronumpy.interp_numarray import convert_to_array,
Scalar
+ from pypy.module.micronumpy.interp_numarray import convert_to_array, \
+ Scalar
if self.argcount != 2:
raise OperationError(space.w_ValueError, space.wrap("reduce only "
"supported for binary functions"))
@@ -126,9 +128,9 @@
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:
+ if shapelen > 1 and dim >= 0:
from pypy.module.micronumpy.interp_numarray import Reduce
- return space.wrap(Reduce(self.func, self.name, dim, dtype,
+ return space.wrap(Reduce(self.func, self.name, dim, dtype,
obj, self.identity))
sig = find_sig(ReduceSignature(self.func, self.name, dtype,
ScalarSignature(dtype),
@@ -148,10 +150,12 @@
value=value, obj=obj, frame=frame,
dtype=dtype)
assert isinstance(sig, ReduceSignature)
- value = sig.binfunc(dtype, value, sig.eval(frame,
obj).convert_to(dtype))
+ value = sig.binfunc(dtype, value,
+ sig.eval(frame, obj).convert_to(dtype))
frame.next(shapelen)
return value
+
class W_Ufunc1(W_Ufunc):
argcount = 1
@@ -236,6 +240,7 @@
reduce = interp2app(W_Ufunc.descr_reduce),
)
+
def find_binop_result_dtype(space, dt1, dt2, promote_to_float=False,
promote_bools=False):
# dt1.num should be <= dt2.num
@@ -284,6 +289,7 @@
dtypenum += 3
return interp_dtype.get_dtype_cache(space).builtin_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):
@@ -308,6 +314,7 @@
assert False
return dt
+
def find_dtype_for_scalar(space, w_obj, current_guess=None):
bool_dtype = interp_dtype.get_dtype_cache(space).w_booldtype
long_dtype = interp_dtype.get_dtype_cache(space).w_longdtype
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
@@ -95,7 +95,7 @@
allnumbers.append(no)
self.iter_no = no
- def create_frame(self, arr, res_shape=None, chunks = None):
+ def create_frame(self, arr, res_shape=None, chunks=None):
if chunks is None:
chunks = []
res_shape = res_shape or arr.shape
@@ -104,6 +104,7 @@
self._create_iter(iterlist, arraylist, arr, res_shape, chunks)
return NumpyEvalFrame(iterlist, arraylist)
+
class ConcreteSignature(Signature):
_immutable_fields_ = ['dtype']
diff --git a/pypy/module/micronumpy/test/test_iterators.py
b/pypy/module/micronumpy/test/test_iterators.py
--- a/pypy/module/micronumpy/test/test_iterators.py
+++ b/pypy/module/micronumpy/test/test_iterators.py
@@ -2,53 +2,56 @@
from pypy.module.micronumpy.interp_iter import axis_iter_from_arr
from pypy.module.micronumpy.interp_numarray import W_NDimArray
+
class MockDtype(object):
def malloc(self, size):
return None
+
class TestAxisIteratorDirect(object):
def test_axis_iterator(self):
- a = W_NDimArray(5*3, [5, 3], MockDtype(), 'C')
+ a = W_NDimArray(5 * 3, [5, 3], MockDtype(), 'C')
i = axis_iter_from_arr(a)
ret = []
while not i.done:
ret.append(i.offset)
i = i.next(1)
assert ret == [0, 3, 6, 9, 12]
- a = W_NDimArray(7*5*3, [7, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(7 * 5 * 3, [7, 5, 3], MockDtype(), 'C')
i = axis_iter_from_arr(a)
ret = []
while not i.done:
ret.append(i.offset)
i = i.next(1)
- assert ret == [3*v for v in range(7*5)]
- i = axis_iter_from_arr(a,2)
+ assert ret == [3 * v for v in range(7 * 5)]
+ i = axis_iter_from_arr(a, 2)
ret = []
while not i.done:
ret.append(i.offset)
i = i.next(1)
- assert ret == [3*v for v in range(7*5)]
- i = axis_iter_from_arr(a,1)
+ assert ret == [3 * v for v in range(7 * 5)]
+ i = axis_iter_from_arr(a, 1)
ret = []
while not i.done:
ret.append(i.offset)
i = i.next(1)
assert ret == [ 0, 1, 2, 15, 16, 17, 30, 31, 32, 45, 46, 47,
- 60, 61, 62, 75, 76, 77, 90, 91, 92]
+ 60, 61, 62, 75, 76, 77, 90, 91, 92]
+
def test_axis_iterator_with_start(self):
- a = W_NDimArray(7*5*3, [7, 5, 3], MockDtype(), 'C')
+ a = W_NDimArray(7 * 5 * 3, [7, 5, 3], MockDtype(), 'C')
i = axis_iter_from_arr(a, start=[0, 0, 0])
ret = []
while not i.done:
ret.append(i.offset)
i = i.next(2)
- assert ret == [3*v for v in range(7*5)]
+ assert ret == [3 * v for v in range(7 * 5)]
i = axis_iter_from_arr(a, start=[1, 1, 0])
ret = []
while not i.done:
ret.append(i.offset)
i = i.next(2)
- assert ret == [3*v+18 for v in range(7*5)]
+ assert ret == [3 * v + 18 for v in range(7 * 5)]
i = axis_iter_from_arr(a, 1, [2, 0, 2])
ret = []
while not i.done:
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
@@ -298,7 +298,7 @@
for i in range(len(a)):
assert b[i] == math.atan(a[i])
- a = array([float('nan')])
+ a = array([float('nan')])
b = arctan(a)
assert math.isnan(b[0])
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit