* Due to the array override, do the actual parameter conversion * only in this step. This function takes the reference objects and * parses them into the desired values. * This function cleans up after itself and NULLs references on error, * however, the caller has to ensure that `out_op[0:nargs]` and `out_whermeask` * are NULL initialized. */
| 944 | * are NULL initialized. |
| 945 | */ |
| 946 | static int |
| 947 | convert_ufunc_arguments(PyUFuncObject *ufunc, |
| 948 | ufunc_full_args full_args, PyArrayObject *out_op[], |
| 949 | PyArray_DTypeMeta *out_op_DTypes[], |
| 950 | npy_bool *force_legacy_promotion, npy_bool *allow_legacy_promotion, |
| 951 | npy_bool *promoting_pyscalars, |
| 952 | PyObject *order_obj, NPY_ORDER *out_order, |
| 953 | PyObject *casting_obj, NPY_CASTING *out_casting, |
| 954 | PyObject *subok_obj, npy_bool *out_subok, |
| 955 | PyObject *where_obj, PyArrayObject **out_wheremask, /* PyArray of bool */ |
| 956 | PyObject *keepdims_obj, int *out_keepdims) |
| 957 | { |
| 958 | int nin = ufunc->nin; |
| 959 | int nout = ufunc->nout; |
| 960 | int nop = ufunc->nargs; |
| 961 | PyObject *obj; |
| 962 | |
| 963 | /* Convert and fill in input arguments */ |
| 964 | npy_bool all_scalar = NPY_TRUE; |
| 965 | npy_bool any_scalar = NPY_FALSE; |
| 966 | *allow_legacy_promotion = NPY_TRUE; |
| 967 | *force_legacy_promotion = NPY_FALSE; |
| 968 | *promoting_pyscalars = NPY_FALSE; |
| 969 | for (int i = 0; i < nin; i++) { |
| 970 | obj = PyTuple_GET_ITEM(full_args.in, i); |
| 971 | |
| 972 | if (PyArray_Check(obj)) { |
| 973 | out_op[i] = (PyArrayObject *)obj; |
| 974 | Py_INCREF(out_op[i]); |
| 975 | } |
| 976 | else { |
| 977 | /* Convert the input to an array and check for special cases */ |
| 978 | out_op[i] = (PyArrayObject *)PyArray_FromAny(obj, NULL, 0, 0, 0, NULL); |
| 979 | if (out_op[i] == NULL) { |
| 980 | goto fail; |
| 981 | } |
| 982 | } |
| 983 | out_op_DTypes[i] = NPY_DTYPE(PyArray_DESCR(out_op[i])); |
| 984 | Py_INCREF(out_op_DTypes[i]); |
| 985 | |
| 986 | if (!NPY_DT_is_legacy(out_op_DTypes[i])) { |
| 987 | *allow_legacy_promotion = NPY_FALSE; |
| 988 | // TODO: A subclass of int, float, complex could reach here and |
| 989 | // it should not be flagged as "weak" if it does. |
| 990 | } |
| 991 | if (PyArray_NDIM(out_op[i]) == 0) { |
| 992 | any_scalar = NPY_TRUE; |
| 993 | } |
| 994 | else { |
| 995 | all_scalar = NPY_FALSE; |
| 996 | continue; |
| 997 | } |
| 998 | |
| 999 | // TODO: Is this equivalent/better by removing the logic which enforces |
| 1000 | // that we always use weak promotion in the core? |
| 1001 | if (npy_promotion_state == NPY_USE_LEGACY_PROMOTION) { |
| 1002 | continue; /* Skip use of special dtypes */ |
| 1003 | } |
no test coverage detected