Skip to content

Commit

Permalink
Merge branch 'index_error_info'
Browse files Browse the repository at this point in the history
  • Loading branch information
njsmith committed Jun 15, 2012
2 parents 6fe584f + 004082c commit 1b6582d
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 197 deletions.
9 changes: 2 additions & 7 deletions numpy/core/src/multiarray/arraytypes.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
39 changes: 30 additions & 9 deletions numpy/core/src/multiarray/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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
Expand Down
10 changes: 10 additions & 0 deletions numpy/core/src/multiarray/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion numpy/core/src/multiarray/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
62 changes: 10 additions & 52 deletions numpy/core/src/multiarray/item_selection.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
55 changes: 17 additions & 38 deletions numpy/core/src/multiarray/iterators.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit 1b6582d

Please sign in to comment.