summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarten van Kerkwijk <mhvk@astro.utoronto.ca>2017-05-11 19:09:08 -0400
committerMarten van Kerkwijk <mhvk@astro.utoronto.ca>2017-05-12 11:11:40 -0400
commit0545f682a34cfd9b8dc362efc0a78b6aa4c4f439 (patch)
tree8e3c14a875dcb1c0469e1427f36f5bcdff3f7ae5
parent14ff219a13e194c5e7995218fea3c7648eb1c875 (diff)
downloadnumpy-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.c48
-rw-r--r--numpy/core/tests/test_umath.py41
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):