summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorHan Genuit <hangenuit@gmail.com>2012-09-14 01:01:49 +0200
committerSebastian Berg <sebastian@sipsolutions.net>2013-04-11 16:59:25 +0200
commit7e28af952cec5cb985b2a56d01e9acae48486b03 (patch)
tree3d70c1c585f90d619a4102df2bc54bebcb0b99f9 /numpy
parent698f57fb2d0c20f7ce7f37267a6e9a1463add0e6 (diff)
downloadnumpy-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.c31
-rw-r--r--numpy/core/tests/test_indexing.py47
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()