* The central entry-point for the promotion and dispatching machinery. * * It currently may work with the operands (although it would be possible to * only work with DType (classes/types). This is because it has to ensure * that legacy (value-based promotion) is used when necessary. * * NOTE: The machinery here currently ignores output arguments unless * they are part of the signatur
| 902 | * when necessary, but push down the handling so it can be cached. |
| 903 | */ |
| 904 | NPY_NO_EXPORT PyArrayMethodObject * |
| 905 | promote_and_get_ufuncimpl(PyUFuncObject *ufunc, |
| 906 | PyArrayObject *const ops[], |
| 907 | PyArray_DTypeMeta *signature[], |
| 908 | PyArray_DTypeMeta *op_dtypes[], |
| 909 | npy_bool force_legacy_promotion, |
| 910 | npy_bool allow_legacy_promotion, |
| 911 | npy_bool promoting_pyscalars, |
| 912 | npy_bool ensure_reduce_compatible) |
| 913 | { |
| 914 | int nin = ufunc->nin, nargs = ufunc->nargs; |
| 915 | |
| 916 | /* |
| 917 | * Get the actual DTypes we operate with by setting op_dtypes[i] from |
| 918 | * signature[i]. |
| 919 | */ |
| 920 | for (int i = 0; i < nargs; i++) { |
| 921 | if (signature[i] != NULL) { |
| 922 | /* |
| 923 | * ignore the operand input, we cannot overwrite signature yet |
| 924 | * since it is fixed (cannot be promoted!) |
| 925 | */ |
| 926 | Py_INCREF(signature[i]); |
| 927 | Py_XSETREF(op_dtypes[i], signature[i]); |
| 928 | assert(i >= ufunc->nin || !NPY_DT_is_abstract(signature[i])); |
| 929 | } |
| 930 | else if (i >= nin) { |
| 931 | /* |
| 932 | * We currently just ignore outputs if not in signature, this will |
| 933 | * always give the/a correct result (limits registering specialized |
| 934 | * loops which include the cast). |
| 935 | * (See also comment in resolve_implementation_info.) |
| 936 | */ |
| 937 | Py_CLEAR(op_dtypes[i]); |
| 938 | } |
| 939 | } |
| 940 | |
| 941 | if (force_legacy_promotion |
| 942 | && npy_promotion_state == NPY_USE_LEGACY_PROMOTION) { |
| 943 | /* |
| 944 | * We must use legacy promotion for value-based logic. Call the old |
| 945 | * resolver once up-front to get the "actual" loop dtypes. |
| 946 | * After this (additional) promotion, we can even use normal caching. |
| 947 | */ |
| 948 | int cacheable = 1; /* unused, as we modify the original `op_dtypes` */ |
| 949 | if (legacy_promote_using_legacy_type_resolver(ufunc, |
| 950 | ops, signature, op_dtypes, &cacheable, NPY_FALSE) < 0) { |
| 951 | goto handle_error; |
| 952 | } |
| 953 | } |
| 954 | |
| 955 | /* Pause warnings and always use "new" path */ |
| 956 | int old_promotion_state = npy_promotion_state; |
| 957 | npy_promotion_state = NPY_USE_WEAK_PROMOTION; |
| 958 | PyObject *info = promote_and_get_info_and_ufuncimpl(ufunc, |
| 959 | ops, signature, op_dtypes, allow_legacy_promotion); |
| 960 | npy_promotion_state = old_promotion_state; |
| 961 |
no test coverage detected