* For each positional argument and each argument in a possible "out" * keyword, look for overrides of the standard ufunc behaviour, i.e., * non-default __array_ufunc__ methods. * * Returns the number of overrides, setting corresponding objects * in PyObject array ``with_override`` and the corresponding * __array_ufunc__ methods in ``methods`` (both using new references). * * Only the first
| 23 | * Returns -1 on failure. |
| 24 | */ |
| 25 | static int |
| 26 | get_array_ufunc_overrides(PyObject *in_args, PyObject *out_args, PyObject *wheremask_obj, |
| 27 | PyObject **with_override, PyObject **methods) |
| 28 | { |
| 29 | int i; |
| 30 | int num_override_args = 0; |
| 31 | int narg, nout, nwhere; |
| 32 | |
| 33 | narg = (int)PyTuple_GET_SIZE(in_args); |
| 34 | /* It is valid for out_args to be NULL: */ |
| 35 | nout = (out_args != NULL) ? (int)PyTuple_GET_SIZE(out_args) : 0; |
| 36 | nwhere = (wheremask_obj != NULL) ? 1: 0; |
| 37 | |
| 38 | for (i = 0; i < narg + nout + nwhere; ++i) { |
| 39 | PyObject *obj; |
| 40 | int j; |
| 41 | int new_class = 1; |
| 42 | |
| 43 | if (i < narg) { |
| 44 | obj = PyTuple_GET_ITEM(in_args, i); |
| 45 | } |
| 46 | else if (i < narg + nout){ |
| 47 | obj = PyTuple_GET_ITEM(out_args, i - narg); |
| 48 | } |
| 49 | else { |
| 50 | obj = wheremask_obj; |
| 51 | } |
| 52 | /* |
| 53 | * Have we seen this class before? If so, ignore. |
| 54 | */ |
| 55 | for (j = 0; j < num_override_args; j++) { |
| 56 | new_class = (Py_TYPE(obj) != Py_TYPE(with_override[j])); |
| 57 | if (!new_class) { |
| 58 | break; |
| 59 | } |
| 60 | } |
| 61 | if (new_class) { |
| 62 | /* |
| 63 | * Now see if the object provides an __array_ufunc__. However, we should |
| 64 | * ignore the base ndarray.__ufunc__, so we skip any ndarray as well as |
| 65 | * any ndarray subclass instances that did not override __array_ufunc__. |
| 66 | */ |
| 67 | PyObject *method = PyUFuncOverride_GetNonDefaultArrayUfunc(obj); |
| 68 | if (method == NULL) { |
| 69 | continue; |
| 70 | } |
| 71 | if (method == Py_None) { |
| 72 | PyErr_Format(PyExc_TypeError, |
| 73 | "operand '%.200s' does not support ufuncs " |
| 74 | "(__array_ufunc__=None)", |
| 75 | obj->ob_type->tp_name); |
| 76 | Py_DECREF(method); |
| 77 | goto fail; |
| 78 | } |
| 79 | Py_INCREF(obj); |
| 80 | with_override[num_override_args] = obj; |
| 81 | methods[num_override_args] = method; |
| 82 | ++num_override_args; |
no test coverage detected