* Check whether a trivial loop is possible and call the innerloop if it is. * A trivial loop is defined as one where a single strided inner-loop call * is possible. * * This function only supports a single output (due to the overlap check). * It always accepts 0-D arrays and will broadcast them. The function * cannot broadcast any other array (as it requires a single stride). * The functio
| 1257 | * Returns -2 if a trivial loop is not possible, 0 on success and -1 on error. |
| 1258 | */ |
| 1259 | static int |
| 1260 | try_trivial_single_output_loop(PyArrayMethod_Context *context, |
| 1261 | PyArrayObject *op[], NPY_ORDER order, |
| 1262 | PyObject *arr_prep[], ufunc_full_args full_args, |
| 1263 | int errormask, PyObject *extobj) |
| 1264 | { |
| 1265 | int nin = context->method->nin; |
| 1266 | int nop = nin + 1; |
| 1267 | assert(context->method->nout == 1); |
| 1268 | |
| 1269 | /* The order of all N-D contiguous operands, can be fixed by `order` */ |
| 1270 | int operation_order = 0; |
| 1271 | if (order == NPY_CORDER) { |
| 1272 | operation_order = NPY_ARRAY_C_CONTIGUOUS; |
| 1273 | } |
| 1274 | else if (order == NPY_FORTRANORDER) { |
| 1275 | operation_order = NPY_ARRAY_F_CONTIGUOUS; |
| 1276 | } |
| 1277 | |
| 1278 | int operation_ndim = 0; |
| 1279 | npy_intp *operation_shape = NULL; |
| 1280 | npy_intp fixed_strides[NPY_MAXARGS]; |
| 1281 | |
| 1282 | for (int iop = 0; iop < nop; iop++) { |
| 1283 | if (op[iop] == NULL) { |
| 1284 | /* The out argument may be NULL (and only that one); fill later */ |
| 1285 | assert(iop == nin); |
| 1286 | continue; |
| 1287 | } |
| 1288 | |
| 1289 | int op_ndim = PyArray_NDIM(op[iop]); |
| 1290 | |
| 1291 | /* Special case 0-D since we can handle broadcasting using a 0-stride */ |
| 1292 | if (op_ndim == 0 && iop < nin) { |
| 1293 | fixed_strides[iop] = 0; |
| 1294 | continue; |
| 1295 | } |
| 1296 | |
| 1297 | /* First non 0-D op: fix dimensions, shape (order is fixed later) */ |
| 1298 | if (operation_ndim == 0) { |
| 1299 | operation_ndim = op_ndim; |
| 1300 | operation_shape = PyArray_SHAPE(op[iop]); |
| 1301 | } |
| 1302 | else if (op_ndim != operation_ndim) { |
| 1303 | return -2; /* dimension mismatch (except 0-d input ops) */ |
| 1304 | } |
| 1305 | else if (!PyArray_CompareLists( |
| 1306 | operation_shape, PyArray_DIMS(op[iop]), op_ndim)) { |
| 1307 | return -2; /* shape mismatch */ |
| 1308 | } |
| 1309 | |
| 1310 | if (op_ndim == 1) { |
| 1311 | fixed_strides[iop] = PyArray_STRIDES(op[iop])[0]; |
| 1312 | } |
| 1313 | else { |
| 1314 | fixed_strides[iop] = PyArray_ITEMSIZE(op[iop]); /* contiguous */ |
| 1315 | |
| 1316 | /* This op must match the operation order (and be contiguous) */ |
no test coverage detected