summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2021-12-08 18:45:51 -0700
committerGitHub <noreply@github.com>2021-12-08 18:45:51 -0700
commitd565c4bf853b6e43c1ff83d72d0df0686cc934cf (patch)
tree114b02ed8bacc14217970ac5ce766903bf569b67 /numpy
parent6ae1a58e508a1f843ec3736488c67ac0bb793c16 (diff)
parent5c7bda86395bbe648fa1e5205f66da21350ba6b0 (diff)
downloadnumpy-d565c4bf853b6e43c1ff83d72d0df0686cc934cf.tar.gz
Merge pull request #20547 from seberg/revert-reduce-stuff
REV: Revert adding a default ufunc promoter
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/umath/dispatching.c24
-rw-r--r--numpy/core/src/umath/ufunc_object.c68
-rw-r--r--numpy/core/tests/test_datetime.py8
3 files changed, 33 insertions, 67 deletions
diff --git a/numpy/core/src/umath/dispatching.c b/numpy/core/src/umath/dispatching.c
index 4c6b09b80..934434370 100644
--- a/numpy/core/src/umath/dispatching.c
+++ b/numpy/core/src/umath/dispatching.c
@@ -592,17 +592,19 @@ legacy_promote_using_legacy_type_resolver(PyUFuncObject *ufunc,
Py_INCREF(operation_DTypes[i]);
Py_DECREF(out_descrs[i]);
}
- if (ufunc->type_resolver == &PyUFunc_SimpleBinaryComparisonTypeResolver) {
- /*
- * In this one case, the deprecation means that we actually override
- * the signature.
- */
- for (int i = 0; i < nargs; i++) {
- if (signature[i] != NULL && signature[i] != operation_DTypes[i]) {
- Py_INCREF(operation_DTypes[i]);
- Py_SETREF(signature[i], operation_DTypes[i]);
- *out_cacheable = 0;
- }
+ /*
+ * The PyUFunc_SimpleBinaryComparisonTypeResolver has a deprecation
+ * warning (ignoring `dtype=`) and cannot be cached.
+ * All datetime ones *should* have a warning, but currently don't,
+ * but ignore all signature passing also. So they can also
+ * not be cached, and they mutate the signature which of course is wrong,
+ * but not doing it would confuse the code later.
+ */
+ for (int i = 0; i < nargs; i++) {
+ if (signature[i] != NULL && signature[i] != operation_DTypes[i]) {
+ Py_INCREF(operation_DTypes[i]);
+ Py_SETREF(signature[i], operation_DTypes[i]);
+ *out_cacheable = 0;
}
}
return 0;
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 9107323b0..1b310b471 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2737,7 +2737,7 @@ reducelike_promote_and_resolve(PyUFuncObject *ufunc,
}
PyArrayMethodObject *ufuncimpl = promote_and_get_ufuncimpl(ufunc,
- ops, signature, operation_DTypes, NPY_FALSE, NPY_FALSE, NPY_TRUE);
+ ops, signature, operation_DTypes, NPY_FALSE, NPY_TRUE, NPY_TRUE);
/* Output can currently get cleared, others XDECREF in case of error */
Py_XDECREF(operation_DTypes[1]);
if (out != NULL) {
@@ -5194,60 +5194,18 @@ PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, voi
return NULL;
}
}
-
- PyObject *promoter = NULL;
- if (ufunc->ntypes == 1) {
- npy_bool all_object = NPY_TRUE;
- for (int i = 0; i < ufunc->nargs; i++) {
- if (ufunc->types[i] != NPY_OBJECT) {
- all_object = NPY_FALSE;
- break;
- }
- }
- if (all_object) {
- promoter = PyCapsule_New(&object_only_ufunc_promoter,
- "numpy._ufunc_promoter", NULL);
- if (promoter == NULL) {
- Py_DECREF(ufunc);
- return NULL;
- }
- }
- }
- if (promoter == NULL && ufunc->nin > 1) {
- promoter = PyCapsule_New(&default_ufunc_promoter,
- "numpy._ufunc_promoter", NULL);
- if (promoter == NULL) {
- Py_DECREF(ufunc);
- return NULL;
- }
- }
- if (promoter != NULL) {
- /* Always install default promoter using the common DType */
- PyObject *dtype_tuple = PyTuple_New(ufunc->nargs);
- if (dtype_tuple == NULL) {
- Py_DECREF(promoter);
- Py_DECREF(ufunc);
- return NULL;
- }
- for (int i = 0; i < ufunc->nargs; i++) {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(dtype_tuple, i, Py_None);
- }
- PyObject *info = PyTuple_Pack(2, dtype_tuple, promoter);
- Py_DECREF(dtype_tuple);
- Py_DECREF(promoter);
- if (info == NULL) {
- Py_DECREF(ufunc);
- return NULL;
- }
-
- int res = PyUFunc_AddLoop((PyUFuncObject *)ufunc, info, 0);
- Py_DECREF(info);
- if (res < 0) {
- Py_DECREF(ufunc);
- return NULL;
- }
- }
+ /*
+ * TODO: I tried adding a default promoter here (either all object for
+ * some special cases, or all homogeneous). Those are reasonable
+ * defaults, but short-cut a deprecated SciPy loop, where the
+ * homogeneous loop `ddd->d` was deprecated, but an inhomogeneous
+ * one `dld->d` should be picked.
+ * The default promoter *is* a reasonable default, but switched that
+ * behaviour.
+ * Another problem appeared due to buggy type-resolution for
+ * datetimes, this meant that `timedelta.sum(dtype="f8")` returned
+ * datetimes (and not floats or error), arguably wrong, but...
+ */
return (PyObject *)ufunc;
}
diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py
index c6a3d4e79..baae77a35 100644
--- a/numpy/core/tests/test_datetime.py
+++ b/numpy/core/tests/test_datetime.py
@@ -2029,11 +2029,17 @@ class TestDateTime:
assert_equal(np.maximum.reduce(a),
np.timedelta64(7, 's'))
+ def test_timedelta_correct_mean(self):
+ # test mainly because it worked only via a bug in that allowed:
+ # `timedelta.sum(dtype="f8")` to ignore the dtype request.
+ a = np.arange(1000, dtype="m8[s]")
+ assert_array_equal(a.mean(), a.sum() / len(a))
+
def test_datetime_no_subtract_reducelike(self):
# subtracting two datetime64 works, but we cannot reduce it, since
# the result of that subtraction will have a different dtype.
arr = np.array(["2021-12-02", "2019-05-12"], dtype="M8[ms]")
- msg = r"ufunc 'subtract' did not contain a loop with signature "
+ msg = r"the resolved dtypes are not compatible"
with pytest.raises(TypeError, match=msg):
np.subtract.reduce(arr)