Skip to content

Commit 1f8105a

Browse files
committed
BUG,MAINT: New style DTypes should never use legacy promotion
Also modify the signatures to prefer npy_bool over ints
1 parent c10abf5 commit 1f8105a

File tree

3 files changed

+32
-26
lines changed

3 files changed

+32
-26
lines changed

numpy/core/src/umath/dispatching.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@
5252

5353

5454
/* forward declaration */
55-
static PyObject *
55+
static NPY_INLINE PyObject *
5656
promote_and_get_info_and_ufuncimpl(PyUFuncObject *ufunc,
57-
PyArrayObject *const ops[], PyArray_DTypeMeta *signature[],
58-
PyArray_DTypeMeta *op_dtypes[], int do_legacy_fallback, int cache);
57+
PyArrayObject *const ops[],
58+
PyArray_DTypeMeta *signature[],
59+
PyArray_DTypeMeta *op_dtypes[],
60+
npy_bool allow_legacy_promotion, npy_bool cache);
5961

6062

6163
/**
@@ -512,8 +514,10 @@ add_and_return_legacy_wrapping_ufunc_loop(PyUFuncObject *ufunc,
512514
*/
513515
static NPY_INLINE PyObject *
514516
promote_and_get_info_and_ufuncimpl(PyUFuncObject *ufunc,
515-
PyArrayObject *const ops[], PyArray_DTypeMeta *signature[],
516-
PyArray_DTypeMeta *op_dtypes[], int do_legacy_fallback, int cache)
517+
PyArrayObject *const ops[],
518+
PyArray_DTypeMeta *signature[],
519+
PyArray_DTypeMeta *op_dtypes[],
520+
npy_bool allow_legacy_promotion, npy_bool cache)
517521
{
518522
/*
519523
* Fetch the dispatching info which consists of the implementation and
@@ -576,7 +580,7 @@ promote_and_get_info_and_ufuncimpl(PyUFuncObject *ufunc,
576580
* However, we need to give the legacy implementation a chance here.
577581
* (it will modify `op_dtypes`).
578582
*/
579-
if (!do_legacy_fallback || ufunc->type_resolver == NULL ||
583+
if (!allow_legacy_promotion || ufunc->type_resolver == NULL ||
580584
(ufunc->ntypes == 0 && ufunc->userloops == NULL)) {
581585
/* Already tried or not a "legacy" ufunc (no loop found, return) */
582586
return NULL;
@@ -589,7 +593,7 @@ promote_and_get_info_and_ufuncimpl(PyUFuncObject *ufunc,
589593
return NULL;
590594
}
591595
info = promote_and_get_info_and_ufuncimpl(ufunc,
592-
ops, signature, new_op_dtypes, 0, cacheable);
596+
ops, signature, new_op_dtypes, NPY_FALSE, cacheable);
593597
for (int i = 0; i < ufunc->nargs; i++) {
594598
Py_XDECREF(new_op_dtypes);
595599
}
@@ -619,8 +623,11 @@ promote_and_get_info_and_ufuncimpl(PyUFuncObject *ufunc,
619623
*/
620624
NPY_NO_EXPORT PyArrayMethodObject *
621625
promote_and_get_ufuncimpl(PyUFuncObject *ufunc,
622-
PyArrayObject *const ops[], PyArray_DTypeMeta *signature[],
623-
PyArray_DTypeMeta *op_dtypes[], int force_legacy_promotion)
626+
PyArrayObject *const ops[],
627+
PyArray_DTypeMeta *signature[],
628+
PyArray_DTypeMeta *op_dtypes[],
629+
npy_bool force_legacy_promotion,
630+
npy_bool allow_legacy_promotion)
624631
{
625632
int nargs = ufunc->nargs;
626633

@@ -654,7 +661,7 @@ promote_and_get_ufuncimpl(PyUFuncObject *ufunc,
654661
}
655662

656663
PyObject *info = promote_and_get_info_and_ufuncimpl(ufunc,
657-
ops, signature, op_dtypes, 1, 1);
664+
ops, signature, op_dtypes, allow_legacy_promotion, NPY_TRUE);
658665

659666
if (info == NULL) {
660667
if (!PyErr_Occurred()) {

numpy/core/src/umath/dispatching.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,16 @@
77
#include "array_method.h"
88

99

10-
typedef int promoter_function(PyUFuncObject *ufunc,
11-
PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[],
12-
PyArray_DTypeMeta *new_op_dtypes[]);
13-
1410
NPY_NO_EXPORT PyArrayMethodObject *
1511
promote_and_get_ufuncimpl(PyUFuncObject *ufunc,
16-
PyArrayObject *const ops[], PyArray_DTypeMeta *signature[],
17-
PyArray_DTypeMeta *op_dtypes[], int force_legacy_promotion);
12+
PyArrayObject *const ops[],
13+
PyArray_DTypeMeta *signature[],
14+
PyArray_DTypeMeta *op_dtypes[],
15+
npy_bool force_legacy_promotion,
16+
npy_bool allow_legacy_promotion);
1817

1918
NPY_NO_EXPORT PyObject *
2019
add_and_return_legacy_wrapping_ufunc_loop(PyUFuncObject *ufunc,
2120
PyArray_DTypeMeta *operation_dtypes[], int ignore_duplicate);
2221

23-
NPY_NO_EXPORT int
24-
install_logical_ufunc_promoter(PyObject *ufunc);
25-
2622
#endif /*_NPY_DISPATCHING_H */

numpy/core/src/umath/ufunc_object.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,8 @@ _wheremask_converter(PyObject *obj, PyArrayObject **wheremask)
922922
static int
923923
convert_ufunc_arguments(PyUFuncObject *ufunc,
924924
ufunc_full_args full_args, PyArrayObject *out_op[],
925-
PyArray_DTypeMeta *out_op_DTypes[], int *force_legacy_promotion,
925+
PyArray_DTypeMeta *out_op_DTypes[],
926+
npy_bool *force_legacy_promotion, npy_bool *allow_legacy_promotion,
926927
PyObject *order_obj, NPY_ORDER *out_order,
927928
PyObject *casting_obj, NPY_CASTING *out_casting,
928929
PyObject *subok_obj, npy_bool *out_subok,
@@ -937,7 +938,8 @@ convert_ufunc_arguments(PyUFuncObject *ufunc,
937938
/* Convert and fill in input arguments */
938939
npy_bool all_scalar = NPY_TRUE;
939940
npy_bool any_scalar = NPY_FALSE;
940-
npy_bool all_legacy = NPY_TRUE;
941+
*allow_legacy_promotion = NPY_TRUE;
942+
*force_legacy_promotion = NPY_FALSE;
941943
for (int i = 0; i < nin; i++) {
942944
obj = PyTuple_GET_ITEM(full_args.in, i);
943945

@@ -956,7 +958,7 @@ convert_ufunc_arguments(PyUFuncObject *ufunc,
956958
Py_INCREF(out_op_DTypes[i]);
957959

958960
if (!out_op_DTypes[i]->legacy) {
959-
all_legacy = NPY_FALSE;
961+
*allow_legacy_promotion = NPY_FALSE;
960962
}
961963
if (PyArray_NDIM(out_op[i]) == 0) {
962964
any_scalar = NPY_TRUE;
@@ -977,7 +979,7 @@ convert_ufunc_arguments(PyUFuncObject *ufunc,
977979
* happen inside the Python operators.
978980
*/
979981
}
980-
if (all_legacy && (!all_scalar && any_scalar)) {
982+
if (*allow_legacy_promotion && (!all_scalar && any_scalar)) {
981983
*force_legacy_promotion = should_use_min_scalar(nin, out_op, 0, NULL);
982984
/*
983985
* TODO: if this is False, we end up in a "very slow" path that should
@@ -4824,11 +4826,12 @@ ufunc_generic_fastcall(PyUFuncObject *ufunc,
48244826
NPY_CASTING casting = NPY_DEFAULT_ASSIGN_CASTING;
48254827
npy_bool subok = NPY_TRUE;
48264828
int keepdims = -1; /* We need to know if it was passed */
4827-
int force_legacy_promotion = 0;
4829+
npy_bool force_legacy_promotion;
4830+
npy_bool allow_legacy_promotion;
48284831
if (convert_ufunc_arguments(ufunc,
48294832
/* extract operand related information: */
48304833
full_args, operands,
4831-
operand_DTypes, &force_legacy_promotion,
4834+
operand_DTypes, &force_legacy_promotion, &allow_legacy_promotion,
48324835
/* extract general information: */
48334836
order_obj, &order,
48344837
casting_obj, &casting,
@@ -4848,7 +4851,7 @@ ufunc_generic_fastcall(PyUFuncObject *ufunc,
48484851
*/
48494852
PyArrayMethodObject *ufuncimpl = promote_and_get_ufuncimpl(ufunc,
48504853
operands, signature,
4851-
operand_DTypes, force_legacy_promotion);
4854+
operand_DTypes, force_legacy_promotion, allow_legacy_promotion);
48524855
if (ufuncimpl == NULL) {
48534856
goto fail;
48544857
}

0 commit comments

Comments
 (0)