| 37 | } |
| 38 | |
| 39 | NPY_NO_EXPORT PyObject * |
| 40 | _PyArray_ArgMinMaxCommon(PyArrayObject *op, |
| 41 | int axis, PyArrayObject *out, int keepdims, |
| 42 | npy_bool is_argmax) |
| 43 | { |
| 44 | PyArrayObject *ap = NULL, *rp = NULL; |
| 45 | PyArray_ArgFunc* arg_func = NULL; |
| 46 | char *ip, *func_name; |
| 47 | npy_intp *rptr; |
| 48 | npy_intp i, n, m; |
| 49 | int elsize; |
| 50 | // Keep a copy because axis changes via call to PyArray_CheckAxis |
| 51 | int axis_copy = axis; |
| 52 | npy_intp _shape_buf[NPY_MAXDIMS]; |
| 53 | npy_intp *out_shape; |
| 54 | // Keep the number of dimensions and shape of |
| 55 | // original array. Helps when `keepdims` is True. |
| 56 | npy_intp* original_op_shape = PyArray_DIMS(op); |
| 57 | int out_ndim = PyArray_NDIM(op); |
| 58 | NPY_BEGIN_THREADS_DEF; |
| 59 | |
| 60 | if ((ap = (PyArrayObject *)PyArray_CheckAxis(op, &axis, 0)) == NULL) { |
| 61 | return NULL; |
| 62 | } |
| 63 | /* |
| 64 | * We need to permute the array so that axis is placed at the end. |
| 65 | * And all other dimensions are shifted left. |
| 66 | */ |
| 67 | if (axis != PyArray_NDIM(ap)-1) { |
| 68 | PyArray_Dims newaxes; |
| 69 | npy_intp dims[NPY_MAXDIMS]; |
| 70 | int j; |
| 71 | |
| 72 | newaxes.ptr = dims; |
| 73 | newaxes.len = PyArray_NDIM(ap); |
| 74 | for (j = 0; j < axis; j++) { |
| 75 | dims[j] = j; |
| 76 | } |
| 77 | for (j = axis; j < PyArray_NDIM(ap) - 1; j++) { |
| 78 | dims[j] = j + 1; |
| 79 | } |
| 80 | dims[PyArray_NDIM(ap) - 1] = axis; |
| 81 | op = (PyArrayObject *)PyArray_Transpose(ap, &newaxes); |
| 82 | Py_DECREF(ap); |
| 83 | if (op == NULL) { |
| 84 | return NULL; |
| 85 | } |
| 86 | } |
| 87 | else { |
| 88 | op = ap; |
| 89 | } |
| 90 | |
| 91 | // Will get native-byte order contiguous copy. |
| 92 | PyArray_Descr *descr = NPY_DT_CALL_ensure_canonical(PyArray_DESCR(op)); |
| 93 | if (descr == NULL) { |
| 94 | return NULL; |
| 95 | } |
| 96 | ap = (PyArrayObject *)PyArray_FromArray(op, descr, NPY_ARRAY_DEFAULT); |
no test coverage detected