Skip to content

Commit

Permalink
BUG: fix not returning out array from ufuncs with subok=False set
Browse files Browse the repository at this point in the history
  • Loading branch information
juliantaylor committed Oct 28, 2014
1 parent 76fc3e7 commit b40e686
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 6 deletions.
15 changes: 9 additions & 6 deletions numpy/core/src/umath/ufunc_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -3932,18 +3932,19 @@ _find_array_wrap(PyObject *args, PyObject *kwds,
PyObject *with_wrap[NPY_MAXARGS], *wraps[NPY_MAXARGS];
PyObject *obj, *wrap = NULL;

/* If a 'subok' parameter is passed and isn't True, don't wrap */
/*
* If a 'subok' parameter is passed and isn't True, don't wrap but put None
* into slots with out arguments which means return the out argument
*/
if (kwds != NULL && (obj = PyDict_GetItem(kwds,
npy_um_str_subok)) != NULL) {
if (obj != Py_True) {
for (i = 0; i < nout; i++) {
output_wrap[i] = NULL;
}
return;
/* skip search for wrap members */
goto handle_out;
}
}

nargs = PyTuple_GET_SIZE(args);

for (i = 0; i < nin; i++) {
obj = PyTuple_GET_ITEM(args, i);
if (PyArray_CheckExact(obj) || PyArray_IsAnyScalar(obj)) {
Expand Down Expand Up @@ -4001,6 +4002,8 @@ _find_array_wrap(PyObject *args, PyObject *kwds,
* exact ndarray so that no PyArray_Return is
* done in that case.
*/
handle_out:
nargs = PyTuple_GET_SIZE(args);
for (i = 0; i < nout; i++) {
int j = nin + i;
int incref = 1;
Expand Down
14 changes: 14 additions & 0 deletions numpy/core/tests/test_numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -1686,6 +1686,20 @@ def test_ddof2(self):
assert_almost_equal(std(self.A, ddof=2)**2,
self.real_var*len(self.A)/float(len(self.A)-2))

def test_out_scalar(self):
d = np.arange(10)
out = np.array(0.)
r = np.std(d, out=out)
assert_(r is out)
assert_array_equal(r, out)
r = np.var(d, out=out)
assert_(r is out)
assert_array_equal(r, out)
r = np.mean(d, out=out)
assert_(r is out)
assert_array_equal(r, out)


class TestStdVarComplex(TestCase):
def test_basic(self):
A = array([1, 1.j, -1, -1.j])
Expand Down
30 changes: 30 additions & 0 deletions numpy/core/tests/test_umath.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@ def test_e(self):
def test_euler_gamma(self):
assert_allclose(ncu.euler_gamma, 0.5772156649015329, 1e-15)

class TestOut(TestCase):
def test_out_subok(self):
for b in (True, False):
aout = np.array(0.5)

r = np.add(aout, 2, out=aout)
assert_(r is aout)
assert_array_equal(r, aout)

r = np.add(aout, 2, out=aout, subok=b)
assert_(r is aout)
assert_array_equal(r, aout)

r = np.add(aout, 2, aout, subok=False)
assert_(r is aout)
assert_array_equal(r, aout)

d = np.ones(5)
o1 = np.zeros(5)
o2 = np.zeros(5, dtype=np.int32)
r1, r2 = np.frexp(d, o1, o2, subok=b)
assert_(r1 is o1)
assert_array_equal(r1, o1)
assert_(r2 is o2)
assert_array_equal(r2, o2)

r1, r2 = np.frexp(d, out=o1, subok=b)
assert_(r1 is o1)
assert_array_equal(r1, o1)


class TestDivision(TestCase):
def test_division_int(self):
Expand Down
2 changes: 2 additions & 0 deletions numpy/ma/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,8 @@ def __call__ (self, a, b):
# component of numpy's import time.
if self.tolerance is None:
self.tolerance = np.finfo(float).tiny
# don't call ma ufuncs from __array_wrap__ which would fail for scalars
a, b = np.asarray(a), np.asarray(b)
return umath.absolute(a) * self.tolerance >= umath.absolute(b)


Expand Down

0 comments on commit b40e686

Please sign in to comment.