* Fill in the actual descriptors used for the operation. This function * supports falling back to the legacy `ufunc->type_resolver`. * * We guarantee the array-method that all passed in descriptors are of the * correct DType instance (i.e. a string can just fetch the length, it doesn't * need to "cast" to string first). */
| 4556 | * need to "cast" to string first). |
| 4557 | */ |
| 4558 | static int |
| 4559 | resolve_descriptors(int nop, |
| 4560 | PyUFuncObject *ufunc, PyArrayMethodObject *ufuncimpl, |
| 4561 | PyArrayObject *operands[], PyArray_Descr *dtypes[], |
| 4562 | PyArray_DTypeMeta *signature[], NPY_CASTING casting) |
| 4563 | { |
| 4564 | int retval = -1; |
| 4565 | PyArray_Descr *original_dtypes[NPY_MAXARGS]; |
| 4566 | |
| 4567 | for (int i = 0; i < nop; ++i) { |
| 4568 | if (operands[i] == NULL) { |
| 4569 | original_dtypes[i] = NULL; |
| 4570 | } |
| 4571 | else { |
| 4572 | /* |
| 4573 | * The dtype may mismatch the signature, in which case we need |
| 4574 | * to make it fit before calling the resolution. |
| 4575 | */ |
| 4576 | PyArray_Descr *descr = PyArray_DTYPE(operands[i]); |
| 4577 | original_dtypes[i] = PyArray_CastDescrToDType(descr, signature[i]); |
| 4578 | if (original_dtypes[i] == NULL) { |
| 4579 | nop = i; /* only this much is initialized */ |
| 4580 | goto finish; |
| 4581 | } |
| 4582 | } |
| 4583 | } |
| 4584 | |
| 4585 | NPY_UF_DBG_PRINT("Resolving the descriptors\n"); |
| 4586 | |
| 4587 | if (ufuncimpl->resolve_descriptors != &wrapped_legacy_resolve_descriptors) { |
| 4588 | /* The default: use the `ufuncimpl` as nature intended it */ |
| 4589 | npy_intp view_offset = NPY_MIN_INTP; /* currently ignored */ |
| 4590 | |
| 4591 | NPY_CASTING safety = ufuncimpl->resolve_descriptors(ufuncimpl, |
| 4592 | signature, original_dtypes, dtypes, &view_offset); |
| 4593 | if (safety < 0) { |
| 4594 | goto finish; |
| 4595 | } |
| 4596 | if (NPY_UNLIKELY(PyArray_MinCastSafety(safety, casting) != casting)) { |
| 4597 | /* TODO: Currently impossible to reach (specialized unsafe loop) */ |
| 4598 | PyErr_Format(PyExc_TypeError, |
| 4599 | "The ufunc implementation for %s with the given dtype " |
| 4600 | "signature is not possible under the casting rule %s", |
| 4601 | ufunc_get_name_cstr(ufunc), npy_casting_to_string(casting)); |
| 4602 | goto finish; |
| 4603 | } |
| 4604 | retval = 0; |
| 4605 | } |
| 4606 | else { |
| 4607 | /* |
| 4608 | * Fall-back to legacy resolver using `operands`, used exclusively |
| 4609 | * for datetime64/timedelta64 and custom ufuncs (in pyerfa/astropy). |
| 4610 | */ |
| 4611 | retval = ufunc->type_resolver(ufunc, casting, operands, NULL, dtypes); |
| 4612 | } |
| 4613 | |
| 4614 | finish: |
| 4615 | for (int i = 0; i < nop; i++) { |
no test coverage detected