Skip to content

Commit d1b3c86

Browse files
committed
Simplify promoter logic: remove dead code and fix comparison reduction
- quad_ufunc_promoter: Remove dead has_quad/common/PyArray_PromoteDTypeSequence machinery. Since this promoter is only registered for patterns where at least one input is QuadPrecDType, we always promote to QuadPrecDType directly. The old fallback paths were unreachable and had a refcount bug (Py_XDECREF on a borrowed pointer when has_quad was true). - comparison_ufunc_promoter: Rewrite with self-contained logic instead of delegating to quad_ufunc_promoter. Fixes reduction path which incorrectly set accumulator to QuadPrecDType instead of BoolDType (the registered reduce loop expects Bool, Quad, Bool).
1 parent 3549bb9 commit d1b3c86

2 files changed

Lines changed: 28 additions & 55 deletions

File tree

src/csrc/umath/comparison_ops.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,31 @@ NPY_NO_EXPORT int
260260
comparison_ufunc_promoter(PyObject *ufunc_obj, PyArray_DTypeMeta *const op_dtypes[],
261261
PyArray_DTypeMeta *const signature[], PyArray_DTypeMeta *new_op_dtypes[])
262262
{
263-
PyArray_DTypeMeta *new_signature[NPY_MAXARGS];
264-
memcpy(new_signature, signature, 3 * sizeof(PyArray_DTypeMeta *));
265-
new_signature[2] = NULL;
266-
int res = quad_ufunc_promoter(ufunc_obj, op_dtypes, new_signature, new_op_dtypes);
267-
if (res < 0) {
268-
return -1;
263+
// Reduction: accumulator is Bool, element is QuadPrecDType, output is Bool
264+
if (op_dtypes[0] == NULL) {
265+
Py_INCREF(&PyArray_BoolDType);
266+
new_op_dtypes[0] = &PyArray_BoolDType;
267+
Py_INCREF(op_dtypes[1]);
268+
new_op_dtypes[1] = op_dtypes[1];
269+
Py_INCREF(&PyArray_BoolDType);
270+
new_op_dtypes[2] = &PyArray_BoolDType;
271+
return 0;
272+
}
273+
274+
// Normal path: promote both inputs to QuadPrecDType, output is Bool
275+
for (int i = 0; i < 2; i++) {
276+
if (signature[i]) {
277+
Py_INCREF(signature[i]);
278+
new_op_dtypes[i] = signature[i];
279+
}
280+
else {
281+
Py_INCREF(&QuadPrecDType);
282+
new_op_dtypes[i] = &QuadPrecDType;
283+
}
269284
}
285+
270286
Py_INCREF(&PyArray_BoolDType);
271-
Py_XSETREF(new_op_dtypes[2], &PyArray_BoolDType);
287+
new_op_dtypes[2] = &PyArray_BoolDType;
272288
return 0;
273289
}
274290

src/include/umath/promoters.hpp

Lines changed: 5 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,74 +16,31 @@ quad_ufunc_promoter(PyObject *ufunc_obj, PyArray_DTypeMeta *const op_dtypes[],
1616
PyArray_DTypeMeta *const signature[], PyArray_DTypeMeta *new_op_dtypes[])
1717
{
1818
PyUFuncObject *ufunc = (PyUFuncObject *)ufunc_obj;
19-
int nin = ufunc->nin;
2019
int nargs = ufunc->nargs;
21-
PyArray_DTypeMeta *common = NULL;
22-
bool has_quad = false;
2320

2421
// Handle the special case for reductions
2522
if (op_dtypes[0] == NULL) {
26-
assert(nin == 2 && ufunc->nout == 1); /* must be reduction */
23+
assert(ufunc->nin == 2 && ufunc->nout == 1); /* must be reduction */
2724
for (int i = 0; i < 3; i++) {
2825
Py_INCREF(op_dtypes[1]);
2926
new_op_dtypes[i] = op_dtypes[1];
3027
}
3128
return 0;
3229
}
3330

34-
// Check if any input or signature is QuadPrecision
35-
for (int i = 0; i < nin; i++) {
36-
if (op_dtypes[i] == &QuadPrecDType) {
37-
has_quad = true;
38-
}
39-
}
40-
41-
if (has_quad) {
42-
common = &QuadPrecDType;
43-
}
44-
else {
45-
for (int i = nin; i < nargs; i++) {
46-
if (signature[i] != NULL) {
47-
if (common == NULL) {
48-
Py_INCREF(signature[i]);
49-
common = signature[i];
50-
}
51-
else if (common != signature[i]) {
52-
Py_CLEAR(common); // Not homogeneous, unset common
53-
break;
54-
}
55-
}
56-
}
57-
}
58-
// If no common output dtype, use standard promotion for inputs
59-
if (common == NULL) {
60-
common = PyArray_PromoteDTypeSequence(nin, op_dtypes);
61-
if (common == NULL) {
62-
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
63-
PyErr_Clear(); // Do not propagate normal promotion errors
64-
}
65-
66-
return -1;
67-
}
68-
}
69-
70-
// Set all new_op_dtypes to the common dtype
31+
// This promoter is only registered for patterns where at least one
32+
// input is QuadPrecDType, so we always promote all args to QuadPrecDType.
7133
for (int i = 0; i < nargs; i++) {
7234
if (signature[i]) {
73-
// If signature is specified for this argument, use it
7435
Py_INCREF(signature[i]);
7536
new_op_dtypes[i] = signature[i];
7637
}
7738
else {
78-
// Otherwise, use the common dtype
79-
Py_INCREF(common);
80-
81-
new_op_dtypes[i] = common;
39+
Py_INCREF(&QuadPrecDType);
40+
new_op_dtypes[i] = &QuadPrecDType;
8241
}
8342
}
8443

85-
Py_XDECREF(common);
86-
8744
return 0;
8845
}
8946

0 commit comments

Comments
 (0)