* Inner loop for unravel_index * order must be NPY_CORDER or NPY_FORTRANORDER */
| 1187 | * order must be NPY_CORDER or NPY_FORTRANORDER |
| 1188 | */ |
| 1189 | static int |
| 1190 | unravel_index_loop(int unravel_ndim, npy_intp const *unravel_dims, |
| 1191 | npy_intp unravel_size, npy_intp count, |
| 1192 | char *indices, npy_intp indices_stride, |
| 1193 | npy_intp *coords, NPY_ORDER order) |
| 1194 | { |
| 1195 | int i, idx; |
| 1196 | int idx_start = (order == NPY_CORDER) ? unravel_ndim - 1: 0; |
| 1197 | int idx_step = (order == NPY_CORDER) ? -1 : 1; |
| 1198 | char invalid = 0; |
| 1199 | npy_intp val = 0; |
| 1200 | |
| 1201 | NPY_BEGIN_ALLOW_THREADS; |
| 1202 | /* NPY_KEEPORDER or NPY_ANYORDER have no meaning in this setting */ |
| 1203 | assert(order == NPY_CORDER || order == NPY_FORTRANORDER); |
| 1204 | while (count--) { |
| 1205 | val = *(npy_intp *)indices; |
| 1206 | if (val < 0 || val >= unravel_size) { |
| 1207 | invalid = 1; |
| 1208 | break; |
| 1209 | } |
| 1210 | idx = idx_start; |
| 1211 | for (i = 0; i < unravel_ndim; ++i) { |
| 1212 | /* |
| 1213 | * Using a local seems to enable single-divide optimization |
| 1214 | * but only if the / precedes the % |
| 1215 | */ |
| 1216 | npy_intp tmp = val / unravel_dims[idx]; |
| 1217 | coords[idx] = val % unravel_dims[idx]; |
| 1218 | val = tmp; |
| 1219 | idx += idx_step; |
| 1220 | } |
| 1221 | coords += unravel_ndim; |
| 1222 | indices += indices_stride; |
| 1223 | } |
| 1224 | NPY_END_ALLOW_THREADS; |
| 1225 | if (invalid) { |
| 1226 | PyErr_Format(PyExc_ValueError, |
| 1227 | "index %" NPY_INTP_FMT " is out of bounds for array with size " |
| 1228 | "%" NPY_INTP_FMT, |
| 1229 | val, unravel_size |
| 1230 | ); |
| 1231 | return NPY_FAIL; |
| 1232 | } |
| 1233 | return NPY_SUCCEED; |
| 1234 | } |
| 1235 | |
| 1236 | /* unravel_index implementation - see add_newdocs.py */ |
| 1237 | NPY_NO_EXPORT PyObject * |