summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src9
-rw-r--r--numpy/core/src/multiarray/common.c39
-rw-r--r--numpy/core/src/multiarray/common.h10
-rw-r--r--numpy/core/src/multiarray/ctors.c3
-rw-r--r--numpy/core/src/multiarray/descriptor.c3
-rw-r--r--numpy/core/src/multiarray/item_selection.c62
-rw-r--r--numpy/core/src/multiarray/iterators.c55
-rw-r--r--numpy/core/src/multiarray/mapping.c92
-rw-r--r--numpy/core/src/multiarray/methods.c18
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c3
-rw-r--r--numpy/core/tests/test_indexerrors.py149
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()