diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/src/multiarray/arraytypes.c.src | 9 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.c | 39 | ||||
-rw-r--r-- | numpy/core/src/multiarray/common.h | 10 | ||||
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 3 | ||||
-rw-r--r-- | numpy/core/src/multiarray/descriptor.c | 3 | ||||
-rw-r--r-- | numpy/core/src/multiarray/item_selection.c | 62 | ||||
-rw-r--r-- | numpy/core/src/multiarray/iterators.c | 55 | ||||
-rw-r--r-- | numpy/core/src/multiarray/mapping.c | 92 | ||||
-rw-r--r-- | numpy/core/src/multiarray/methods.c | 18 | ||||
-rw-r--r-- | numpy/core/src/multiarray/multiarraymodule.c | 3 | ||||
-rw-r--r-- | numpy/core/tests/test_indexerrors.py | 149 |
11 files changed, 246 insertions, 197 deletions
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src index 3ad8d1a75..1846d8114 100644 --- a/numpy/core/src/multiarray/arraytypes.c.src +++ b/numpy/core/src/multiarray/arraytypes.c.src @@ -3531,14 +3531,9 @@ static int for (i = 0; i < n_outer; i++) { for (j = 0; j < m_middle; j++) { tmp = indarray[j]; - if (tmp < 0) { - tmp = tmp + nindarray; - } - if ((tmp < 0) || (tmp >= nindarray)) { - PyErr_SetString(PyExc_IndexError, - "index out of range for array"); + /* We don't know what axis we're operating on, so don't report it in case of an error. */ + if (check_and_adjust_index(&tmp, nindarray, -1) < 0) return 1; - } if (nelem == 1) { *dest++ = *(src + tmp); } diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index 613632c45..4be3afb4d 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -506,6 +506,32 @@ _array_typedescr_fromstr(char *c_str) return descr; } +NPY_NO_EXPORT int +check_and_adjust_index(npy_intp *index, npy_intp max_item, int axis) +{ + /* Check that index is valid, taking into account negative indices */ + if ((*index < -max_item) || (*index >= max_item)) { + /* Try to be as clear as possible about what went wrong. */ + if (axis >= 0) { + PyErr_Format(PyExc_IndexError, + "index %"NPY_INTP_FMT" is out of bounds " + "for axis %d with size %"NPY_INTP_FMT, + *index, axis, max_item); + } else { + PyErr_Format(PyExc_IndexError, + "index %"NPY_INTP_FMT" is out of bounds " + "for size %"NPY_INTP_FMT, + *index, max_item); + } + return -1; + } + /* adjust negative indices */ + if (*index < 0) { + *index += max_item; + } + return 0; +} + NPY_NO_EXPORT char * index2ptr(PyArrayObject *mp, npy_intp i) { @@ -516,17 +542,12 @@ index2ptr(PyArrayObject *mp, npy_intp i) return NULL; } dim0 = PyArray_DIMS(mp)[0]; - if (i < 0) { - i += dim0; - } - if (i == 0 && dim0 > 0) { + if (check_and_adjust_index(&i, dim0, 0) < 0) + return NULL; + if (i == 0) { return PyArray_DATA(mp); } - if (i > 0 && i < dim0) { - return PyArray_DATA(mp)+i*PyArray_STRIDES(mp)[0]; - } - PyErr_SetString(PyExc_IndexError,"index out of bounds"); - return NULL; + return PyArray_DATA(mp)+i*PyArray_STRIDES(mp)[0]; } NPY_NO_EXPORT int diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index 60b4008d8..a682a4a9d 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -41,6 +41,16 @@ _array_find_python_scalar_type(PyObject *op); NPY_NO_EXPORT PyArray_Descr * _array_typedescr_fromstr(char *str); +/* + * Returns -1 and sets an exception if *index is an invalid index for + * an array of size max_item, otherwise adjusts it in place to be + * 0 <= *index < max_item, and returns 0. + * 'axis' should be the array axis that is being indexed over, if known. If + * unknown, use -1. + */ +NPY_NO_EXPORT int +check_and_adjust_index(npy_intp *index, npy_intp max_item, int axis); + NPY_NO_EXPORT char * index2ptr(PyArrayObject *mp, npy_intp i); diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index eac9ba437..311e2f863 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -2913,6 +2913,7 @@ PyArray_CheckAxis(PyArrayObject *arr, int *axis, int flags) { PyObject *temp1, *temp2; int n = PyArray_NDIM(arr); + int axis_orig = *axis; if (*axis == NPY_MAXDIMS || n == 0) { if (n != 1) { @@ -2955,7 +2956,7 @@ PyArray_CheckAxis(PyArrayObject *arr, int *axis, int flags) } if ((*axis < 0) || (*axis >= n)) { PyErr_Format(PyExc_ValueError, - "axis(=%d) out of bounds", *axis); + "axis(=%d) out of bounds", axis_orig); Py_DECREF(temp2); return NULL; } diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index b10f9eb85..5090dc39c 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -3395,6 +3395,7 @@ descr_subscript(PyArray_Descr *self, PyObject *op) PyObject *name; int size = PyTuple_GET_SIZE(self->names); int value = PyArray_PyIntAsInt(op); + int orig_value = value; if (PyErr_Occurred()) { return NULL; @@ -3404,7 +3405,7 @@ descr_subscript(PyArray_Descr *self, PyObject *op) } if (value < 0 || value >= size) { PyErr_Format(PyExc_IndexError, - "Field index out of range."); + "Field index %d out of range.", orig_value); return NULL; } name = PyTuple_GET_ITEM(self->names, value); diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c index 010aa8aa5..3cbd5391c 100644 --- a/numpy/core/src/multiarray/item_selection.c +++ b/numpy/core/src/multiarray/item_selection.c @@ -174,12 +174,7 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis, for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { tmp = ((npy_intp *)(PyArray_DATA(indices)))[j]; - if (tmp < 0) { - tmp = tmp + max_item; - } - if ((tmp < 0) || (tmp >= max_item)) { - PyErr_SetString(PyExc_IndexError, - "index out of range for array"); + if (check_and_adjust_index(&tmp, max_item, axis) < 0) { NPY_AUXDATA_FREE(transferdata); goto fail; } @@ -252,13 +247,7 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis, for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { tmp = ((npy_intp *)(PyArray_DATA(indices)))[j]; - if (tmp < 0) { - tmp = tmp + max_item; - } - if ((tmp < 0) || (tmp >= max_item)) { - PyErr_SetString(PyExc_IndexError, - "index out of range "\ - "for array"); + if (check_and_adjust_index(&tmp, max_item, axis) < 0) { goto fail; } memmove(dest, src + tmp*chunk, chunk); @@ -389,13 +378,7 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0, for (i = 0; i < ni; i++) { src = PyArray_DATA(values) + chunk*(i % nv); tmp = ((npy_intp *)(PyArray_DATA(indices)))[i]; - if (tmp < 0) { - tmp = tmp + max_item; - } - if ((tmp < 0) || (tmp >= max_item)) { - PyErr_SetString(PyExc_IndexError, - "index out of " \ - "range for array"); + if (check_and_adjust_index(&tmp, max_item, 0) < 0) { goto fail; } PyArray_Item_INCREF(src, PyArray_DESCR(self)); @@ -445,13 +428,7 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0, for (i = 0; i < ni; i++) { src = PyArray_DATA(values) + chunk * (i % nv); tmp = ((npy_intp *)(PyArray_DATA(indices)))[i]; - if (tmp < 0) { - tmp = tmp + max_item; - } - if ((tmp < 0) || (tmp >= max_item)) { - PyErr_SetString(PyExc_IndexError, - "index out of " \ - "range for array"); + if (check_and_adjust_index(&tmp, max_item, 0) < 0) { goto fail; } memmove(dest + tmp * chunk, src, chunk); @@ -1102,6 +1079,7 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which) PyArrayObject *ap = NULL, *store_arr = NULL; char *ip; int i, n, m, elsize, orign; + int axis_orig=axis; n = PyArray_NDIM(op); if ((n == 0) || (PyArray_SIZE(op) == 1)) { @@ -1111,7 +1089,7 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which) axis += n; } if ((axis < 0) || (axis >= n)) { - PyErr_Format(PyExc_ValueError, "axis(=%d) out of bounds", axis); + PyErr_Format(PyExc_ValueError, "axis(=%d) out of bounds", axis_orig); return -1; } if (PyArray_FailUnlessWriteable(op, "sort array") < 0) { @@ -2535,12 +2513,7 @@ PyArray_MultiIndexGetItem(PyArrayObject *self, npy_intp *multi_index) npy_intp shapevalue = shape[idim]; npy_intp ind = multi_index[idim]; - if (ind < 0) { - ind += shapevalue; - } - - if (ind < 0 || ind >= shapevalue) { - PyErr_SetString(PyExc_ValueError, "index out of bounds"); + if (check_and_adjust_index(&ind, shapevalue, idim) < 0) { return NULL; } @@ -2564,12 +2537,7 @@ PyArray_MultiIndexGetItem(PyArrayObject *self, npy_intp *multi_index) npy_intp shapevalue = shape[idim]; npy_intp ind = multi_index[idim]; - if (ind < 0) { - ind += shapevalue; - } - - if (ind < 0 || ind >= shapevalue) { - PyErr_SetString(PyExc_ValueError, "index out of bounds"); + if (check_and_adjust_index(&ind, shapevalue, idim) < 0) { return NULL; } @@ -2612,12 +2580,7 @@ PyArray_MultiIndexSetItem(PyArrayObject *self, npy_intp *multi_index, npy_intp shapevalue = shape[idim]; npy_intp ind = multi_index[idim]; - if (ind < 0) { - ind += shapevalue; - } - - if (ind < 0 || ind >= shapevalue) { - PyErr_SetString(PyExc_ValueError, "index out of bounds"); + if (check_and_adjust_index(&ind, shapevalue, idim) < 0) { return -1; } @@ -2654,12 +2617,7 @@ PyArray_MultiIndexSetItem(PyArrayObject *self, npy_intp *multi_index, npy_intp shapevalue = shape[idim]; npy_intp ind = multi_index[idim]; - if (ind < 0) { - ind += shapevalue; - } - - if (ind < 0 || ind >= shapevalue) { - PyErr_SetString(PyExc_ValueError, "index out of bounds"); + if (check_and_adjust_index(&ind, shapevalue, idim) < 0) { return -1; } diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c index 0e1a498da..1933b145d 100644 --- a/numpy/core/src/multiarray/iterators.c +++ b/numpy/core/src/multiarray/iterators.c @@ -31,7 +31,8 @@ slice_coerce_index(PyObject *o, npy_intp *v); */ NPY_NO_EXPORT npy_intp parse_index_entry(PyObject *op, npy_intp *step_size, - npy_intp *n_steps, npy_intp max) + npy_intp *n_steps, npy_intp max, + int axis, int check_index) { npy_intp i; @@ -69,12 +70,10 @@ parse_index_entry(PyObject *op, npy_intp *step_size, } *n_steps = SINGLE_INDEX; *step_size = 0; - if (i < 0) { - i += max; - } - if (i >= max || i < 0) { - PyErr_SetString(PyExc_IndexError, "invalid index"); + if (check_index) { + if (check_and_adjust_index(&i, max, axis) < 0) { goto fail; + } } } return i; @@ -134,8 +133,9 @@ parse_index(PyArrayObject *self, PyObject *op, } } start = parse_index_entry(op1, &step_size, &n_steps, - nd_old < PyArray_NDIM(self) ? - PyArray_DIMS(self)[nd_old] : 0); + nd_old < PyArray_NDIM(self) ? + PyArray_DIMS(self)[nd_old] : 0, + nd_old, nd_old < PyArray_NDIM(self)); Py_DECREF(op1); if (start == -1) { break; @@ -717,14 +717,7 @@ iter_subscript_int(PyArrayIterObject *self, PyArrayObject *ind) itemsize = PyArray_DESCR(self->ao)->elsize; if (PyArray_NDIM(ind) == 0) { num = *((npy_intp *)PyArray_DATA(ind)); - if (num < 0) { - num += self->size; - } - if (num < 0 || num >= self->size) { - PyErr_Format(PyExc_IndexError, - "index %"NPY_INTP_FMT" out of bounds" \ - " 0<=index<%"NPY_INTP_FMT, - num, self->size); + if (check_and_adjust_index(&num, self->size, -1) < 0) { PyArray_ITER_RESET(self); return NULL; } @@ -758,14 +751,7 @@ iter_subscript_int(PyArrayIterObject *self, PyArrayObject *ind) swap = (PyArray_ISNOTSWAPPED(ret) != PyArray_ISNOTSWAPPED(self->ao)); while (counter--) { num = *((npy_intp *)(ind_it->dataptr)); - if (num < 0) { - num += self->size; - } - if (num < 0 || num >= self->size) { - PyErr_Format(PyExc_IndexError, - "index %"NPY_INTP_FMT" out of bounds" \ - " 0<=index<%"NPY_INTP_FMT, - num, self->size); + if (check_and_adjust_index(&num, self->size, -1) < 0) { Py_DECREF(ind_it); Py_DECREF(ret); PyArray_ITER_RESET(self); @@ -841,7 +827,7 @@ iter_subscript(PyArrayIterObject *self, PyObject *ind) /* Check for Integer or Slice */ if (PyLong_Check(ind) || PyInt_Check(ind) || PySlice_Check(ind)) { start = parse_index_entry(ind, &step_size, &n_steps, - self->size); + self->size, 0, 1); if (start == -1) { goto fail; } @@ -989,6 +975,9 @@ iter_ass_sub_int(PyArrayIterObject *self, PyArrayObject *ind, copyswap = PyArray_DESCR(self->ao)->f->copyswap; if (PyArray_NDIM(ind) == 0) { num = *((npy_intp *)PyArray_DATA(ind)); + if (check_and_adjust_index(&num, self->size, -1) < 0) { + return -1; + } PyArray_ITER_GOTO1D(self, num); copyswap(self->dataptr, val->dataptr, swap, self->ao); return 0; @@ -1000,14 +989,7 @@ iter_ass_sub_int(PyArrayIterObject *self, PyArrayObject *ind, counter = ind_it->size; while (counter--) { num = *((npy_intp *)(ind_it->dataptr)); - if (num < 0) { - num += self->size; - } - if ((num < 0) || (num >= self->size)) { - PyErr_Format(PyExc_IndexError, - "index %"NPY_INTP_FMT" out of bounds" \ - " 0<=index<%"NPY_INTP_FMT, num, - self->size); + if (check_and_adjust_index(&num, self->size, -1) < 0) { Py_DECREF(ind_it); return -1; } @@ -1084,10 +1066,7 @@ iter_ass_subscript(PyArrayIterObject *self, PyObject *ind, PyObject *val) PyErr_Clear(); } else { - if (start < -self->size || start >= self->size) { - PyErr_Format(PyExc_ValueError, - "index (%" NPY_INTP_FMT \ - ") out of range", start); + if (check_and_adjust_index(&start, self->size, -1) < 0) { goto finish; } retval = 0; @@ -1121,7 +1100,7 @@ iter_ass_subscript(PyArrayIterObject *self, PyObject *ind, PyObject *val) /* Check Slice */ if (PySlice_Check(ind)) { - start = parse_index_entry(ind, &step_size, &n_steps, self->size); + start = parse_index_entry(ind, &step_size, &n_steps, self->size, 0, 0); if (start == -1) { goto finish; } diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index f260cf8d9..7034f5797 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -57,11 +57,7 @@ array_big_item(PyArrayObject *self, npy_intp i) /* Bounds check and get the data pointer */ dim0 = PyArray_DIM(self, 0); - if (i < 0) { - i += dim0; - } - if (i < 0 || i >= dim0) { - PyErr_SetString(PyExc_IndexError,"index out of bounds"); + if (check_and_adjust_index(&i, dim0, 0) < 0) { return NULL; } item = PyArray_DATA(self) + i * PyArray_STRIDE(self, 0); @@ -113,19 +109,18 @@ _array_ass_item(PyArrayObject *self, Py_ssize_t i, PyObject *v) /* contains optimization for 1-d arrays */ NPY_NO_EXPORT PyObject * -array_item_nice(PyArrayObject *self, Py_ssize_t i) +array_item_nice(PyArrayObject *self, Py_ssize_t _i) { + /* Workaround Python 2.4: Py_ssize_t not the same as npyint_p */ + npy_intp i = _i; + if (PyArray_NDIM(self) == 1) { char *item; npy_intp dim0; /* Bounds check and get the data pointer */ dim0 = PyArray_DIM(self, 0); - if (i < 0) { - i += dim0; - } - if (i < 0 || i >= dim0) { - PyErr_SetString(PyExc_IndexError,"index out of bounds"); + if (check_and_adjust_index(&i, dim0, 0) < 0) { return NULL; } item = PyArray_DATA(self) + i * PyArray_STRIDE(self, 0); @@ -200,11 +195,7 @@ array_ass_big_item(PyArrayObject *self, npy_intp i, PyObject *v) /* Bounds check and get the data pointer */ dim0 = PyArray_DIM(self, 0); - if (i < 0) { - i += dim0; - } - if (i < 0 || i >= dim0) { - PyErr_SetString(PyExc_IndexError,"index out of bounds"); + if (check_and_adjust_index(&i, dim0, 0) < 0) { return -1; } item = PyArray_DATA(self) + i * PyArray_STRIDE(self, 0); @@ -1600,19 +1591,10 @@ array_ass_sub(PyArrayObject *self, PyObject *ind, PyObject *op) if (!PyArray_HASMASKNA(self)) { for (idim = 0; idim < ndim; idim++) { npy_intp v = vals[idim]; - if (v < 0) { - v += shape[idim]; - } - if (v < 0 || v >= shape[idim]) { - PyErr_Format(PyExc_IndexError, - "index (%"NPY_INTP_FMT") out of range "\ - "(0<=index<%"NPY_INTP_FMT") in dimension %d", - vals[idim], PyArray_DIMS(self)[idim], idim); + if (check_and_adjust_index(&v, shape[idim], idim) < 0) { return -1; } - else { - item += v * strides[idim]; - } + item += v * strides[idim]; } return PyArray_DESCR(self)->f->setitem(op, item, self); } @@ -1623,20 +1605,11 @@ array_ass_sub(PyArrayObject *self, PyObject *ind, PyObject *op) for (idim = 0; idim < ndim; idim++) { npy_intp v = vals[idim]; - if (v < 0) { - v += shape[idim]; - } - if (v < 0 || v >= shape[idim]) { - PyErr_Format(PyExc_IndexError, - "index (%"NPY_INTP_FMT") out of range "\ - "(0<=index<%"NPY_INTP_FMT") in dimension %d", - vals[idim], PyArray_DIMS(self)[idim], idim); + if (check_and_adjust_index(&v, shape[idim], idim) < 0) { return -1; } - else { - item += v * strides[idim]; - maskna_item += v * maskna_strides[idim]; - } + item += v * strides[idim]; + maskna_item += v * maskna_strides[idim]; } na = NpyNA_FromObject(op, 1); if (na == NULL) { @@ -1758,19 +1731,10 @@ array_subscript_nice(PyArrayObject *self, PyObject *op) if (!PyArray_HASMASKNA(self)) { for (idim = 0; idim < ndim; idim++) { npy_intp v = vals[idim]; - if (v < 0) { - v += shape[idim]; - } - if (v < 0 || v >= shape[idim]) { - PyErr_Format(PyExc_IndexError, - "index (%"NPY_INTP_FMT") out of range "\ - "(0<=index<%"NPY_INTP_FMT") in dimension %d", - vals[idim], PyArray_DIMS(self)[idim], idim); + if (check_and_adjust_index(&v, shape[idim], idim) < 0) { return NULL; } - else { - item += v * strides[idim]; - } + item += v * strides[idim]; } return PyArray_Scalar(item, PyArray_DESCR(self), (PyObject *)self); } @@ -1780,20 +1744,11 @@ array_subscript_nice(PyArrayObject *self, PyObject *op) for (idim = 0; idim < ndim; idim++) { npy_intp v = vals[idim]; - if (v < 0) { - v += shape[idim]; - } - if (v < 0 || v >= shape[idim]) { - PyErr_Format(PyExc_IndexError, - "index (%"NPY_INTP_FMT") out of range "\ - "(0<=index<%"NPY_INTP_FMT") in dimension %d", - vals[idim], PyArray_DIMS(self)[idim], idim); + if (check_and_adjust_index(&v, shape[idim], idim) < 0) { return NULL; } - else { - item += v * strides[idim]; - maskna_item += v * maskna_strides[idim]; - } + item += v * strides[idim]; + maskna_item += v * maskna_strides[idim]; } if (NpyMaskValue_IsExposed((npy_mask)*maskna_item)) { return PyArray_Scalar(item, PyArray_DESCR(self), @@ -2131,7 +2086,7 @@ PyArray_MapIterBind(PyArrayMapIterObject *mit, PyArrayObject *arr) subnd = PyArray_NDIM(arr) - mit->numiter; if (subnd < 0) { - PyErr_SetString(PyExc_ValueError, + PyErr_SetString(PyExc_IndexError, "too many indices for array"); return; } @@ -2247,7 +2202,7 @@ PyArray_MapIterBind(PyArrayMapIterObject *mit, PyArrayObject *arr) goto fail; } if (mit->ait->size == 0 && mit->size != 0) { - PyErr_SetString(PyExc_ValueError, + PyErr_SetString(PyExc_IndexError, "invalid index into a 0-size array"); goto fail; } @@ -2260,14 +2215,7 @@ PyArray_MapIterBind(PyArrayMapIterObject *mit, PyArrayObject *arr) while (it->index < it->size) { indptr = ((npy_intp *)it->dataptr); indval = *indptr; - if (indval < 0) { - indval += dimsize; - } - if (indval < 0 || indval >= dimsize) { - PyErr_Format(PyExc_IndexError, - "index (%"NPY_INTP_FMT") out of range "\ - "(0<=index<%"NPY_INTP_FMT") in dimension %d", - indval, (dimsize-1), mit->iteraxes[i]); + if (check_and_adjust_index(&indval, dimsize, mit->iteraxes[i]) < 0) { goto fail; } PyArray_ITER_NEXT(it); diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index 6d1a52edc..dacfabcbd 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -694,14 +694,7 @@ array_toscalar(PyArrayObject *self, PyObject *args) return NULL; } - /* Negative indexing */ - if (value < 0) { - value += size; - } - - if (value < 0 || value >= size) { - PyErr_SetString(PyExc_ValueError, - "index out of bounds"); + if (check_and_adjust_index(&value, size, -1) < 0) { return NULL; } @@ -778,14 +771,7 @@ array_setscalar(PyArrayObject *self, PyObject *args) return NULL; } - /* Negative indexing */ - if (value < 0) { - value += size; - } - - if (value < 0 || value >= size) { - PyErr_SetString(PyExc_ValueError, - "index out of bounds"); + if (check_and_adjust_index(&value, size, -1) < 0) { return NULL; } diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 7a657d8b9..75929198d 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -320,6 +320,7 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis) PyArrayObject *ret = NULL; PyArrayObject_fields *sliding_view = NULL; int has_maskna; + int orig_axis = axis; if (narrays <= 0) { PyErr_SetString(PyExc_ValueError, @@ -342,7 +343,7 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis) } if (axis < 0 || axis >= ndim) { PyErr_Format(PyExc_IndexError, - "axis %d out of bounds [0, %d)", axis, ndim); + "axis %d out of bounds [0, %d)", orig_axis, ndim); return NULL; } diff --git a/numpy/core/tests/test_indexerrors.py b/numpy/core/tests/test_indexerrors.py new file mode 100644 index 000000000..230ca4955 --- /dev/null +++ b/numpy/core/tests/test_indexerrors.py @@ -0,0 +1,149 @@ +import numpy as np +from numpy.testing import TestCase, run_module_suite, assert_raises, assert_equal, assert_ +import sys + +class TestIndexErrors(TestCase): + '''Tests to exercise indexerrors not covered by other tests.''' + + def test_arraytypes_fasttake(self): + 'take from a 0-length dimension' + x = np.empty((2, 3, 0, 4)) + assert_raises(IndexError, x.take, [0], axis=2) + assert_raises(IndexError, x.take, [1], axis=2) + + def test_maskna_take_1D(self): + # Check exception taking from masked array + a = np.array([1, np.NA, 2, np.NA], maskna=True) + assert_raises(IndexError, a.take, [6]) + a = np.array(np.NA, maskna=True) + assert_raises(IndexError, a.take, [6]) + + # Check exception taking from masked 0-d array + d = np.empty((5, 0), maskna=True) + assert_raises(IndexError, d.take, [1], axis=1) + assert_raises(IndexError, d.take, [0], axis=1) + assert_raises(IndexError, d.take, [0]) + + def test_take_from_object(self): + # Check exception taking from object array + d = np.zeros(5, dtype=object) + assert_raises(IndexError, d.take, [6]) + + # Check exception taking from 0-d array + d = np.zeros((5, 0), dtype=object) + assert_raises(IndexError, d.take, [1], axis=1) + assert_raises(IndexError, d.take, [0], axis=1) + assert_raises(IndexError, d.take, [0]) + + def test_multiindex_exceptions(self): + a = np.empty(5, dtype=object) + assert_raises(IndexError, a.item, 20) + a = np.empty((5, 0), dtype=object) + assert_raises(IndexError, a.item, (0, 0)) + a = np.empty(5, dtype=object, maskna=True) + assert_raises(IndexError, a.item, 20) + a = np.empty((5, 0), dtype=object, maskna=True) + assert_raises(IndexError, a.item, (0, 0)) + + a = np.empty(5, dtype=object) + assert_raises(IndexError, a.itemset, 20, 0) + a = np.empty((5, 0), dtype=object) + assert_raises(IndexError, a.itemset, (0, 0), 0) + a = np.empty(5, dtype=object, maskna=True) + assert_raises(IndexError, a.itemset, 20, 0) + a = np.empty((5, 0), dtype=object, maskna=True) + assert_raises(IndexError, a.itemset, (0, 0), 0) + + def test_put_exceptions(self): + a = np.zeros((5, 5)) + assert_raises(IndexError, a.put, 100, 0) + a = np.zeros((5, 5), dtype=object) + assert_raises(IndexError, a.put, 100, 0) + a = np.zeros((5, 5, 0)) + assert_raises(IndexError, a.put, 100, 0) + a = np.zeros((5, 5, 0), dtype=object) + assert_raises(IndexError, a.put, 100, 0) + + def test_iterators_exceptions(self): + "cases in iterators.c" + def assign(obj, ind, val): + obj[ind] = val + + a = np.zeros([1,2,3]) + assert_raises(IndexError, lambda: a[0,5,None,2]) + assert_raises(IndexError, lambda: a[0,5,0,2]) + assert_raises(IndexError, lambda: assign(a, (0,5,None,2), 1)) + assert_raises(IndexError, lambda: assign(a, (0,5,0,2), 1)) + + a = np.zeros([1,0,3]) + assert_raises(IndexError, lambda: a[0,0,None,2]) + assert_raises(IndexError, lambda: assign(a, (0,0,None,2), 1)) + + a = np.zeros([1,2,3]) + assert_raises(IndexError, lambda: a.flat[10]) + assert_raises(IndexError, lambda: assign(a.flat, 10, 5)) + a = np.zeros([1,0,3]) + assert_raises(IndexError, lambda: a.flat[10]) + assert_raises(IndexError, lambda: assign(a.flat, 10, 5)) + + a = np.zeros([1,2,3]) + assert_raises(IndexError, lambda: a.flat[np.array(10)]) + assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5)) + a = np.zeros([1,0,3]) + assert_raises(IndexError, lambda: a.flat[np.array(10)]) + assert_raises(IndexError, lambda: assign(a.flat, np.array(10), 5)) + + a = np.zeros([1,2,3]) + assert_raises(IndexError, lambda: a.flat[np.array([10])]) + assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5)) + a = np.zeros([1,0,3]) + assert_raises(IndexError, lambda: a.flat[np.array([10])]) + assert_raises(IndexError, lambda: assign(a.flat, np.array([10]), 5)) + + def test_mapping(self): + "cases from mapping.c" + + def assign(obj, ind, val): + obj[ind] = val + + a = np.zeros((0, 10)) + assert_raises(IndexError, lambda: a[12]) + + a = np.zeros((3,5)) + assert_raises(IndexError, lambda: a[(10, 20)]) + assert_raises(IndexError, lambda: assign(a, (10, 20), 1)) + a = np.zeros((3,0)) + assert_raises(IndexError, lambda: a[(1, 0)]) + assert_raises(IndexError, lambda: assign(a, (1, 0), 1)) + + a = np.zeros((3,5), maskna=True) + assert_raises(IndexError, lambda: a[(10, 20)]) + assert_raises(IndexError, lambda: assign(a, (10, 20), 1)) + a = np.zeros((3,0), maskna=True) + assert_raises(IndexError, lambda: a[(1, 0)]) + assert_raises(IndexError, lambda: assign(a, (1, 0), 1)) + + a = np.zeros((10,)) + assert_raises(IndexError, lambda: assign(a, 10, 1)) + a = np.zeros((0,)) + assert_raises(IndexError, lambda: assign(a, 10, 1)) + + a = np.zeros((3,5)) + assert_raises(IndexError, lambda: a[(1, [1, 20])]) + assert_raises(IndexError, lambda: assign(a, (1, [1, 20]), 1)) + a = np.zeros((3,0)) + assert_raises(IndexError, lambda: a[(1, [0, 1])]) + assert_raises(IndexError, lambda: assign(a, (1, [0, 1]), 1)) + + def test_methods(self): + "cases from methods.c" + + a = np.zeros((3, 3)) + assert_raises(IndexError, lambda: a.item(100)) + assert_raises(IndexError, lambda: a.itemset(100, 1)) + a = np.zeros((0, 3)) + assert_raises(IndexError, lambda: a.item(100)) + assert_raises(IndexError, lambda: a.itemset(100, 1)) + +if __name__ == "__main__": + run_module_suite() |