diff options
author | Marten van Kerkwijk <mhvk@astro.utoronto.ca> | 2017-05-11 19:09:08 -0400 |
---|---|---|
committer | Marten van Kerkwijk <mhvk@astro.utoronto.ca> | 2017-05-12 11:11:40 -0400 |
commit | 0545f682a34cfd9b8dc362efc0a78b6aa4c4f439 (patch) | |
tree | 8e3c14a875dcb1c0469e1427f36f5bcdff3f7ae5 | |
parent | 14ff219a13e194c5e7995218fea3c7648eb1c875 (diff) | |
download | numpy-0545f682a34cfd9b8dc362efc0a78b6aa4c4f439.tar.gz |
BUG: ensure axis=None gets passed on correctly to ufunc.reduce.
By mistake, any arguments to ufunc.reduce, ufunc.accumulate,
and ufunc.reduceat that were None were removed, rather than just
removing the 'out' argument. This is corrected here, with
tests added.
-rw-r--r-- | numpy/core/src/umath/override.c | 48 | ||||
-rw-r--r-- | numpy/core/tests/test_umath.py | 41 |
2 files changed, 55 insertions, 34 deletions
diff --git a/numpy/core/src/umath/override.c b/numpy/core/src/umath/override.c index 6b441cbbb..a899b0bd0 100644 --- a/numpy/core/src/umath/override.c +++ b/numpy/core/src/umath/override.c @@ -144,14 +144,16 @@ normalize_reduce_args(PyUFuncObject *ufunc, PyObject *args, return -1; } obj = PyTuple_GET_ITEM(args, i); - if (obj != Py_None) { - if (i == 3) { - obj = PyTuple_GetSlice(args, 3, 4); - } - PyDict_SetItemString(*normal_kwds, kwlist[i], obj); - if (i == 3) { - Py_DECREF(obj); + if (i == 3) { + /* remove out=None */ + if (obj == Py_None) { + continue; } + obj = PyTuple_GetSlice(args, 3, 4); + } + PyDict_SetItemString(*normal_kwds, kwlist[i], obj); + if (i == 3) { + Py_DECREF(obj); } } return 0; @@ -188,14 +190,16 @@ normalize_accumulate_args(PyUFuncObject *ufunc, PyObject *args, return -1; } obj = PyTuple_GET_ITEM(args, i); - if (obj != Py_None) { - if (i == 3) { - obj = PyTuple_GetSlice(args, 3, 4); - } - PyDict_SetItemString(*normal_kwds, kwlist[i], obj); - if (i == 3) { - Py_DECREF(obj); + if (i == 3) { + /* remove out=None */ + if (obj == Py_None) { + continue; } + obj = PyTuple_GetSlice(args, 3, 4); + } + PyDict_SetItemString(*normal_kwds, kwlist[i], obj); + if (i == 3) { + Py_DECREF(obj); } } return 0; @@ -234,14 +238,16 @@ normalize_reduceat_args(PyUFuncObject *ufunc, PyObject *args, return -1; } obj = PyTuple_GET_ITEM(args, i); - if (obj != Py_None) { - if (i == 4) { - obj = PyTuple_GetSlice(args, 4, 5); - } - PyDict_SetItemString(*normal_kwds, kwlist[i], obj); - if (i == 4) { - Py_DECREF(obj); + if (i == 4) { + /* remove out=None */ + if (obj == Py_None) { + continue; } + obj = PyTuple_GetSlice(args, 4, 5); + } + PyDict_SetItemString(*normal_kwds, kwlist[i], obj); + if (i == 4) { + Py_DECREF(obj); } } return 0; diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 13f29504a..32969bc68 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -1755,11 +1755,14 @@ class TestSpecialMethods(TestCase): 'keepdims': 'keep0', 'axis': 'axis0'}) - # reduce, output equal to None removed. - res = np.multiply.reduce(a, out=None) - assert_equal(res[4], {}) - res = np.multiply.reduce(a, out=(None,)) - assert_equal(res[4], {}) + # reduce, output equal to None removed, but not other explicit ones, + # even if they are at their default value. + res = np.multiply.reduce(a, 0, None, None, False) + assert_equal(res[4], {'axis': 0, 'dtype': None, 'keepdims': False}) + res = np.multiply.reduce(a, out=None, axis=0, keepdims=True) + assert_equal(res[4], {'axis': 0, 'keepdims': True}) + res = np.multiply.reduce(a, None, out=(None,), dtype=None) + assert_equal(res[4], {'axis': None, 'dtype': None}) # reduce, wrong args assert_raises(TypeError, np.multiply.reduce, a, out=()) @@ -1788,10 +1791,12 @@ class TestSpecialMethods(TestCase): 'axis': 'axis0'}) # accumulate, output equal to None removed. - res = np.multiply.accumulate(a, out=None) - assert_equal(res[4], {}) - res = np.multiply.accumulate(a, out=(None,)) - assert_equal(res[4], {}) + res = np.multiply.accumulate(a, 0, None, None) + assert_equal(res[4], {'axis': 0, 'dtype': None}) + res = np.multiply.accumulate(a, out=None, axis=0, dtype='dtype1') + assert_equal(res[4], {'axis': 0, 'dtype': 'dtype1'}) + res = np.multiply.accumulate(a, None, out=(None,), dtype=None) + assert_equal(res[4], {'axis': None, 'dtype': None}) # accumulate, wrong args assert_raises(TypeError, np.multiply.accumulate, a, out=()) @@ -1822,10 +1827,12 @@ class TestSpecialMethods(TestCase): 'axis': 'axis0'}) # reduceat, output equal to None removed. - res = np.multiply.reduceat(a, [4, 2], out=None) - assert_equal(res[4], {}) - res = np.multiply.reduceat(a, [4, 2], out=(None,)) - assert_equal(res[4], {}) + res = np.multiply.reduceat(a, [4, 2], 0, None, None) + assert_equal(res[4], {'axis': 0, 'dtype': None}) + res = np.multiply.reduceat(a, [4, 2], axis=None, out=None, dtype='dt') + assert_equal(res[4], {'axis': None, 'dtype': 'dt'}) + res = np.multiply.reduceat(a, [4, 2], None, None, out=(None,)) + assert_equal(res[4], {'axis': None, 'dtype': None}) # reduceat, wrong args assert_raises(TypeError, np.multiply.reduce, a, [4, 2], out=()) @@ -2107,6 +2114,14 @@ 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) + c = a.max() + assert_equal(c, 3) + assert_(c.info, {'inputs': [0]}) + c = a.any() + assert_equal(c, True) + assert_(c.info, {'inputs': [0]}) class TestChoose(TestCase): |