diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/umath/override.c | 4 | ||||
-rw-r--r-- | numpy/core/src/umath/ufunc_object.c | 18 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 2 | ||||
-rw-r--r-- | numpy/core/tests/test_umath.py | 92 |
4 files changed, 94 insertions, 22 deletions
diff --git a/numpy/core/src/umath/override.c b/numpy/core/src/umath/override.c index a899b0bd0..66fb759a4 100644 --- a/numpy/core/src/umath/override.c +++ b/numpy/core/src/umath/override.c @@ -366,11 +366,11 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method, if (out != NULL) { int nout = ufunc->nout; - if (PyTuple_Check(out)) { + if (PyTuple_CheckExact(out)) { int all_none = 1; if (PyTuple_GET_SIZE(out) != nout) { - PyErr_Format(PyExc_TypeError, + PyErr_Format(PyExc_ValueError, "The 'out' tuple must have exactly " "%d entries: one per ufunc output", nout); goto fail; diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index e1219039c..ea99560ea 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -1084,7 +1084,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc, "positional and keyword argument"); goto fail; } - if (PyTuple_Check(value)) { + if (PyTuple_CheckExact(value)) { if (PyTuple_GET_SIZE(value) != nout) { PyErr_SetString(PyExc_ValueError, "The 'out' tuple must have exactly " @@ -3894,6 +3894,7 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args, PyObject *obj_ind, *context; PyArrayObject *indices = NULL; PyArray_Descr *otype = NULL; + PyObject *out_obj = NULL; PyArrayObject *out = NULL; int keepdims = 0; static char *reduce_kwlist[] = { @@ -3927,7 +3928,20 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args, _reduce_type[operation]); return NULL; } - + /* if there is a tuple of 1 for `out` in kwds, unpack it */ + if (kwds != NULL) { + PyObject *out_obj = PyDict_GetItem(kwds, npy_um_str_out); + if (out_obj != NULL && PyTuple_CheckExact(out_obj)) { + if (PyTuple_GET_SIZE(out_obj) != 1) { + PyErr_SetString(PyExc_ValueError, + "The 'out' tuple must have exactly one entry"); + return NULL; + } + out_obj = PyTuple_GET_ITEM(out_obj, 0); + PyDict_SetItem(kwds, npy_um_str_out, out_obj); + } + } + if (operation == UFUNC_REDUCEAT) { PyArray_Descr *indtype; indtype = PyArray_DescrFromType(NPY_INTP); diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 835d03528..2b25d478e 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -3107,7 +3107,7 @@ class TestBinop(object): warnings.filterwarnings('always', '', DeprecationWarning) assert_equal(np.modf(dummy, out=a), (0,)) assert_(w[0].category is DeprecationWarning) - assert_raises(TypeError, np.modf, dummy, out=(a,)) + assert_raises(ValueError, np.modf, dummy, out=(a,)) # 2 inputs, 1 output assert_equal(np.add(a, dummy), 0) diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 32969bc68..120844c82 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -1765,8 +1765,8 @@ class TestSpecialMethods(TestCase): assert_equal(res[4], {'axis': None, 'dtype': None}) # reduce, wrong args - assert_raises(TypeError, np.multiply.reduce, a, out=()) - assert_raises(TypeError, np.multiply.reduce, a, out=('out0', 'out1')) + assert_raises(ValueError, np.multiply.reduce, a, out=()) + assert_raises(ValueError, np.multiply.reduce, a, out=('out0', 'out1')) assert_raises(TypeError, np.multiply.reduce, a, 'axis0', axis='axis0') # accumulate, pos args @@ -1799,8 +1799,8 @@ class TestSpecialMethods(TestCase): assert_equal(res[4], {'axis': None, 'dtype': None}) # accumulate, wrong args - assert_raises(TypeError, np.multiply.accumulate, a, out=()) - assert_raises(TypeError, np.multiply.accumulate, a, + assert_raises(ValueError, np.multiply.accumulate, a, out=()) + assert_raises(ValueError, np.multiply.accumulate, a, out=('out0', 'out1')) assert_raises(TypeError, np.multiply.accumulate, a, 'axis0', axis='axis0') @@ -1835,8 +1835,8 @@ class TestSpecialMethods(TestCase): assert_equal(res[4], {'axis': None, 'dtype': None}) # reduceat, wrong args - assert_raises(TypeError, np.multiply.reduce, a, [4, 2], out=()) - assert_raises(TypeError, np.multiply.reduce, a, [4, 2], + assert_raises(ValueError, np.multiply.reduce, a, [4, 2], out=()) + assert_raises(ValueError, np.multiply.reduce, a, [4, 2], out=('out0', 'out1')) assert_raises(TypeError, np.multiply.reduce, a, [4, 2], 'axis0', axis='axis0') @@ -1914,12 +1914,12 @@ class TestSpecialMethods(TestCase): # wrong number of arguments in the tuple is an error too. assert_raises(TypeError, np.multiply, a, b, 'one', out='two') assert_raises(TypeError, np.multiply, a, b, 'one', 'two') - assert_raises(TypeError, np.multiply, a, b, out=('one', 'two')) - assert_raises(TypeError, np.multiply, a, out=()) + assert_raises(ValueError, np.multiply, a, b, out=('one', 'two')) + assert_raises(ValueError, np.multiply, a, out=()) assert_raises(TypeError, np.modf, a, 'one', out=('two', 'three')) assert_raises(TypeError, np.modf, a, 'one', 'two', 'three') - assert_raises(TypeError, np.modf, a, out=('one', 'two', 'three')) - assert_raises(TypeError, np.modf, a, out=('one',)) + assert_raises(ValueError, np.modf, a, out=('one', 'two', 'three')) + assert_raises(ValueError, np.modf, a, out=('one',)) def test_ufunc_override_exception(self): @@ -2006,8 +2006,8 @@ class TestSpecialMethods(TestCase): assert_raises(TypeError, inner1d, a, out='two') assert_raises(TypeError, inner1d, a, a, 'one', out='two') assert_raises(TypeError, inner1d, a, a, 'one', 'two') - assert_raises(TypeError, inner1d, a, a, out=('one', 'two')) - assert_raises(TypeError, inner1d, a, a, out=()) + assert_raises(ValueError, inner1d, a, a, out=('one', 'two')) + assert_raises(ValueError, inner1d, a, a, out=()) def test_ufunc_override_with_super(self): @@ -2048,6 +2048,8 @@ class TestSpecialMethods(TestCase): return NotImplemented if method == 'at': + if isinstance(inputs[0], A): + inputs[0].info = info return if ufunc.nout == 1: @@ -2114,14 +2116,70 @@ class TestSpecialMethods(TestCase): assert_(a.__array_ufunc__(np.add, '__call__', a, b) is NotImplemented) assert_(b.__array_ufunc__(np.add, '__call__', a, b) == "A!") assert_(np.add(a, b) == "A!") - # regression check for gh-9102 - a = np.array([[1, 2, 3], [1, 2, 3]]).view(A) + # regression check for gh-9102 -- tests ufunc.reduce implicitly. + d = np.array([[1, 2, 3], [1, 2, 3]]) + a = d.view(A) + c = a.any() + check = d.any() + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) c = a.max() - assert_equal(c, 3) + check = d.max() + assert_equal(c, check) assert_(c.info, {'inputs': [0]}) - c = a.any() - assert_equal(c, True) + b = np.array(0).view(A) + c = a.max(out=b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + check = a.max(axis=0) + b = np.zeros_like(check).view(A) + c = a.max(axis=0, out=b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + # simple explicit tests of reduce, accumulate, reduceat + check = np.add.reduce(d, axis=1) + c = np.add.reduce(a, axis=1) + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + b = np.zeros_like(c) + c = np.add.reduce(a, 1, None, b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + check = np.add.accumulate(d, axis=0) + c = np.add.accumulate(a, axis=0) + assert_equal(c, check) + assert_(c.info, {'inputs': [0]}) + b = np.zeros_like(c) + c = np.add.accumulate(a, 0, None, b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + indices = [0, 2, 1] + check = np.add.reduceat(d, indices, axis=1) + c = np.add.reduceat(a, indices, axis=1) + assert_equal(c, check) assert_(c.info, {'inputs': [0]}) + b = np.zeros_like(c) + c = np.add.reduceat(a, indices, 1, None, b) + assert_equal(c, check) + assert_(c is b) + assert_(c.info, {'inputs': [0], 'outputs': [0]}) + # and a few tests for at + d = np.array([[1, 2, 3], [1, 2, 3]]) + check = d.copy() + a = d.copy().view(A) + np.add.at(check, ([0, 1], [0, 2]), 1.) + np.add.at(a, ([0, 1], [0, 2]), 1.) + assert_equal(a, check) + assert_(a.info, {'inputs': [0]}) + b = np.array(1.).view(A) + a = d.copy().view(A) + np.add.at(a, ([0, 1], [0, 2]), b) + assert_equal(a, check) + assert_(a.info, {'inputs': [0, 2]}) class TestChoose(TestCase): |