summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/umath/ufunc_object.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index 275172aae..7a40dfa8d 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -2395,6 +2395,8 @@ static int get_ufunc_arguments(PyUFuncObject *self,
PyObject *obj, *context;
char *ufunc_name;
+ int any_flexible = 0, any_object = 0;
+
ufunc_name = self->name ? self->name : "<unnamed ufunc>";
/* Check number of arguments */
@@ -2426,6 +2428,25 @@ static int get_ufunc_arguments(PyUFuncObject *self,
if (out_op[i] == NULL) {
return -1;
}
+ if (!any_flexible &&
+ PyTypeNum_ISFLEXIBLE(PyArray_DESCR(out_op[i])->type_num)) {
+ any_flexible = 1;
+ }
+ if (!any_object &&
+ PyTypeNum_ISOBJECT(PyArray_DESCR(out_op[i])->type_num)) {
+ any_object = 1;
+ }
+ }
+
+ /*
+ * Indicate not implemented if there are flexible objects (structured
+ * type or string) but no object types.
+ *
+ * Not sure - adding this increased to 246 errors, 150 failures.
+ */
+ if (any_flexible && !any_object) {
+ return -2;
+
}
/* Get positional output arguments */
@@ -3107,6 +3128,7 @@ PyUFunc_GenericFunction_Iter(PyUFuncObject *self,
npy_intp nin, nout;
npy_intp i, niter;
char *ufunc_name;
+ int retval = -1;
PyArray_Descr *dtype[NPY_MAXARGS];
@@ -3161,8 +3183,9 @@ PyUFunc_GenericFunction_Iter(PyUFuncObject *self,
}
/* Get all the arguments */
- if (get_ufunc_arguments(self, args, kwds,
- op, &order, &casting, &extobj, &typetup) < 0) {
+ retval = get_ufunc_arguments(self, args, kwds,
+ op, &order, &casting, &extobj, &typetup);
+ if (retval < 0) {
goto fail;
}
@@ -3186,6 +3209,24 @@ PyUFunc_GenericFunction_Iter(PyUFuncObject *self,
goto fail;
}
+ /*
+ * FAIL with NotImplemented if the other object has
+ * the __r<op>__ method and has __array_priority__ as
+ * an attribute (signalling it can handle ndarray's)
+ * and is not already an ndarray or a subtype of the same type.
+ */
+ if (nin == 2 && nout == 1 && dtype[1]->type_num == NPY_OBJECT) {
+ PyObject *_obj = PyTuple_GET_ITEM(args, 1);
+ if (!PyArray_CheckExact(_obj)
+ /* If both are same subtype of object arrays, then proceed */
+ && !(Py_TYPE(_obj) == Py_TYPE(PyTuple_GET_ITEM(args, 0)))
+ && PyObject_HasAttrString(_obj, "__array_priority__")
+ && _has_reflected_op(_obj, ufunc_name)) {
+ retval = -2;
+ goto fail;
+ }
+ }
+
#if 0
printf("input types:\n");
for (i = 0; i < nin; ++i) {
@@ -3250,7 +3291,7 @@ fail:
Py_XDECREF(errobj);
Py_XDECREF(arr_prep_args);
- return -1;
+ return retval;
}
static PyArrayObject *
@@ -5222,8 +5263,8 @@ static struct PyMethodDef ufunc_methods[] = {
{"outer",
(PyCFunction)ufunc_outer,
METH_VARARGS | METH_KEYWORDS, NULL},
- {"f", /* new generic call */
- (PyCFunction)ufunc_generic_call_iter,
+ {"f", /* old generic call */
+ (PyCFunction)ufunc_generic_call,
METH_VARARGS | METH_KEYWORDS, NULL},
{NULL, NULL, 0, NULL} /* sentinel */
};
@@ -5450,7 +5491,7 @@ NPY_NO_EXPORT PyTypeObject PyUFunc_Type = {
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
- (ternaryfunc)ufunc_generic_call, /* tp_call */
+ (ternaryfunc)ufunc_generic_call_iter, /* tp_call */
(reprfunc)ufunc_repr, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */