diff options
author | Han Genuit <hangenuit@gmail.com> | 2012-09-14 01:01:49 +0200 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2013-04-11 16:59:25 +0200 |
commit | 7e28af952cec5cb985b2a56d01e9acae48486b03 (patch) | |
tree | 3d70c1c585f90d619a4102df2bc54bebcb0b99f9 /numpy | |
parent | 698f57fb2d0c20f7ce7f37267a6e9a1463add0e6 (diff) | |
download | numpy-7e28af952cec5cb985b2a56d01e9acae48486b03.tar.gz |
BUG: Fix failing subscript test cases
This fixes indexing with NumPy boolean scalar values, which caused
crashes before. Both Python and NumPy boolean scalars now behave the
same. This contains a few small changes to PyArrayMapIterNew, where
the PyArrayMapIterObject is memset to zero and a fix for the crash,
which was caused by _nonzero_indices, which did not initialize any
iterators because ndim is zero for scalars. *IterNew will now check
for scalars before running that part of the code.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/mapping.c | 31 | ||||
-rw-r--r-- | numpy/core/tests/test_indexing.py | 47 |
2 files changed, 48 insertions, 30 deletions
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index 8c5a38d9b..990f95d3b 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -1058,9 +1058,8 @@ array_subscript_fromobject(PyArrayObject *self, PyObject *op) npy_intp vals[NPY_MAXDIMS]; /* Integer index */ - if (PyInt_Check(op) || PyArray_IsScalar(op, Integer) || - PyLong_Check(op) || (PyIndex_Check(op) && - !PySequence_Check(op))) { + if (PyArray_IsIntegerScalar(op) || (PyIndex_Check(op) && + !PySequence_Check(op))) { npy_intp value = PyArray_PyIntAsIntp(op); if (value == -1 && PyErr_Occurred()) { /* fail on error */ @@ -1375,9 +1374,8 @@ array_ass_sub(PyArrayObject *self, PyObject *ind, PyObject *op) } /* Integer index */ - if (PyInt_Check(ind) || PyArray_IsScalar(ind, Integer) || - PyLong_Check(ind) || (PyIndex_Check(ind) && - !PySequence_Check(ind))) { + if (PyArray_IsIntegerScalar(ind) || (PyIndex_Check(ind) && + !PySequence_Check(ind))) { npy_intp value = PyArray_PyIntAsIntp(ind); if (value == -1 && PyErr_Occurred()) { /* fail on error */ @@ -1970,20 +1968,14 @@ PyArray_MapIterNew(PyObject *indexobj, int oned, int fancy) } mit = (PyArrayMapIterObject *)PyArray_malloc(sizeof(PyArrayMapIterObject)); + /* set all attributes of mapiter to zero */ + memset(mit, 0, sizeof(PyArrayMapIterObject)); PyObject_Init((PyObject *)mit, &PyArrayMapIter_Type); if (mit == NULL) { return NULL; } - for (i = 0; i < NPY_MAXDIMS; i++) { - mit->iters[i] = NULL; - } - mit->index = 0; - mit->ait = NULL; - mit->subspace = NULL; - mit->numiter = 0; + /* initialize mapiter attributes */ mit->consec = 1; - Py_INCREF(indexobj); - mit->indexobj = indexobj; if (fancy == SOBJ_LISTTUP) { PyObject *newobj; @@ -1991,10 +1983,13 @@ PyArray_MapIterNew(PyObject *indexobj, int oned, int fancy) if (newobj == NULL) { goto fail; } - Py_DECREF(indexobj); indexobj = newobj; mit->indexobj = indexobj; } + else { + Py_INCREF(indexobj); + mit->indexobj = indexobj; + } if (oned) { @@ -2007,8 +2002,8 @@ PyArray_MapIterNew(PyObject *indexobj, int oned, int fancy) */ /* convert all inputs to iterators */ - if (PyArray_Check(indexobj) && - (PyArray_TYPE((PyArrayObject *)indexobj) == NPY_BOOL)) { + if (PyArray_Check(indexobj) && PyArray_ISBOOL(indexobj) + && !PyArray_IsZeroDim(indexobj)) { mit->numiter = _nonzero_indices(indexobj, mit->iters); if (mit->numiter < 0) { goto fail; diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index 2d7a3effe..eb185e291 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -28,10 +28,12 @@ class TestIndexing(TestCase): assert_equal(a[()], a) assert_(a[()].base is a) - def _test_empty_list_index(self): - # Empty list index (is buggy!) + def test_empty_list_index(self): + # Empty list index creates an empty array + # with the same dtype (but with weird shape) a = np.array([1, 2, 3]) - assert_equal(a[[]], a) + assert_equal(a[[]], []) + assert_equal(a[[]].dtype, a.dtype) def test_empty_array_index(self): # Empty array index is illegal @@ -71,27 +73,48 @@ class TestIndexing(TestCase): # Index overflow produces ValueError assert_raises(ValueError, a.__getitem__, 1<<64) - def _test_single_bool_index(self): - # Single boolean index (is buggy?) + def test_single_bool_index(self): + # Single boolean index a = np.array([[1, 2, 3], [4 ,5, 6], [7, 8, 9]]) - # Python boolean converts to integer (invalid?) + # Python boolean converts to integer assert_equal(a[True], a[1]) + assert_equal(a[False], a[0]) - # NumPy zero-dimensional boolean array (*crashes*) - assert_equal(a[np.array(True)], a) # what should be the behaviour? - assert_equal(a[np.array(False)], []) # what should be the behaviour? + # Same with NumPy boolean scalar + assert_equal(a[np.array(True)], a[1]) + assert_equal(a[np.array(False)], a[0]) - def test_boolean_indexing(self): - # Indexing a 2-dimensional array with a length-1 array of 'True' + def test_boolean_indexing_onedim(self): + # Indexing a 2-dimensional array with + # boolean array of length one a = np.array([[ 0., 0., 0.]]) b = np.array([ True], dtype=bool) assert_equal(a[b], a) - + # boolean assignment a[b] = 1. assert_equal(a, [[1., 1., 1.]]) + def test_boolean_indexing_twodim(self): + # Indexing a 2-dimensional array with + # 2-dimensional boolean array + a = np.array([[1, 2, 3], + [4 ,5, 6], + [7, 8, 9]]) + b = np.array([[ True, False, True], + [False, True, False], + [ True, False, True]]) + assert_equal(a[b], [1, 3, 5, 7, 9]) + assert_equal(a[b[1], [4, 5, 6]) + assert_equal(a[b[0]], a[b[2]]) + + # boolean assignment + a[b] = 0 + assert_equal(a, [[0, 2, 0], + [4, 0, 6], + [0, 8, 0]]) + if __name__ == "__main__": run_module_suite() |