* This code handles reduce, reduceat, and accumulate * (accumulate and reduce are special cases of the more general reduceat * but they are handled separately for speed) */
| 3966 | * but they are handled separately for speed) |
| 3967 | */ |
| 3968 | static PyObject * |
| 3969 | PyUFunc_GenericReduction(PyUFuncObject *ufunc, |
| 3970 | PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames, int operation) |
| 3971 | { |
| 3972 | int i, naxes=0, ndim; |
| 3973 | int axes[NPY_MAXDIMS]; |
| 3974 | |
| 3975 | ufunc_full_args full_args = {NULL, NULL}; |
| 3976 | PyObject *axes_obj = NULL; |
| 3977 | PyArrayObject *mp = NULL, *wheremask = NULL, *ret = NULL; |
| 3978 | PyObject *op = NULL; |
| 3979 | PyArrayObject *indices = NULL; |
| 3980 | PyArray_DTypeMeta *signature[3] = {NULL, NULL, NULL}; |
| 3981 | PyArrayObject *out = NULL; |
| 3982 | int keepdims = 0; |
| 3983 | PyObject *initial = NULL; |
| 3984 | npy_bool out_is_passed_by_position; |
| 3985 | |
| 3986 | |
| 3987 | static char *_reduce_type[] = {"reduce", "accumulate", "reduceat", NULL}; |
| 3988 | |
| 3989 | if (ufunc == NULL) { |
| 3990 | PyErr_SetString(PyExc_ValueError, "function not supported"); |
| 3991 | return NULL; |
| 3992 | } |
| 3993 | if (ufunc->core_enabled) { |
| 3994 | PyErr_Format(PyExc_RuntimeError, |
| 3995 | "Reduction not defined on ufunc with signature"); |
| 3996 | return NULL; |
| 3997 | } |
| 3998 | if (ufunc->nin != 2) { |
| 3999 | PyErr_Format(PyExc_ValueError, |
| 4000 | "%s only supported for binary functions", |
| 4001 | _reduce_type[operation]); |
| 4002 | return NULL; |
| 4003 | } |
| 4004 | if (ufunc->nout != 1) { |
| 4005 | PyErr_Format(PyExc_ValueError, |
| 4006 | "%s only supported for functions " |
| 4007 | "returning a single value", |
| 4008 | _reduce_type[operation]); |
| 4009 | return NULL; |
| 4010 | } |
| 4011 | |
| 4012 | /* |
| 4013 | * Perform argument parsing, but start by only extracting. This is |
| 4014 | * just to preserve the behaviour that __array_ufunc__ did not perform |
| 4015 | * any checks on arguments, and we could change this or change it for |
| 4016 | * certain parameters. |
| 4017 | */ |
| 4018 | PyObject *otype_obj = NULL, *out_obj = NULL, *indices_obj = NULL; |
| 4019 | PyObject *keepdims_obj = NULL, *wheremask_obj = NULL; |
| 4020 | if (operation == UFUNC_REDUCEAT) { |
| 4021 | NPY_PREPARE_ARGPARSER; |
| 4022 | |
| 4023 | if (npy_parse_arguments("reduceat", args, len_args, kwnames, |
| 4024 | "array", NULL, &op, |
| 4025 | "indices", NULL, &indices_obj, |
no test coverage detected