summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2015-06-12 13:33:40 -0600
committerCharles Harris <charlesr.harris@gmail.com>2015-06-12 15:20:19 -0600
commit8f172ddbb90357e80bafa2cd7df4b307ce15600b (patch)
tree584fe3bc99eba768060257657a22a1ebc6369a1f
parent30d755d8737505717d54ed32501261bb94130a7f (diff)
downloadnumpy-8f172ddbb90357e80bafa2cd7df4b307ce15600b.tar.gz
BUG: Make type_tuple_type_resolver more robust.
When a loop match fails on account of casting, continue searching the loops until success or all loops have been examined. The failure to do this was causing true_divide to fail with float inputs and dtype=float because the first loop found was (int8, int8, float64), leading to a casting error as float cannot be safely cast to int8. Versions of numpy previous to 1.10 will still fail silently if this is backported as the casting rules were less strict, so that would also need fixing. Closes #3484.
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c33
1 files changed, 13 insertions, 20 deletions
diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c
index fe2e8cac3..601ffadbf 100644
--- a/numpy/core/src/umath/ufunc_type_resolution.c
+++ b/numpy/core/src/umath/ufunc_type_resolution.c
@@ -2106,7 +2106,6 @@ type_tuple_type_resolver(PyUFuncObject *self,
for (i = 0; i < self->ntypes; ++i) {
char *orig_types = self->types + i*self->nargs;
- int matched = 1;
/* Copy the types into an int array for matching */
for (j = 0; j < nop; ++j) {
@@ -2116,17 +2115,17 @@ type_tuple_type_resolver(PyUFuncObject *self,
if (n_specified == nop) {
for (j = 0; j < nop; ++j) {
if (types[j] != specified_types[j] &&
- specified_types[j] != NPY_NOTYPE) {
- matched = 0;
+ specified_types[j] != NPY_NOTYPE) {
break;
}
}
- } else {
- if (types[nin] != specified_types[0]) {
- matched = 0;
+ if (j < nop) {
+ /* no match */
+ continue;
}
}
- if (!matched) {
+ else if (types[nin] != specified_types[0]) {
+ /* no match */
continue;
}
@@ -2136,29 +2135,23 @@ type_tuple_type_resolver(PyUFuncObject *self,
types, NULL,
&no_castable_output, &err_src_typecode,
&err_dst_typecode)) {
- /* Error */
case -1:
+ /* Error */
return -1;
- /* It worked */
+ case 0:
+ /* Cannot cast inputs */
+ continue;
case 1:
+ /* Success */
set_ufunc_loop_data_types(self, op, out_dtype, types, NULL);
return 0;
- /* Didn't work */
- case 0:
- PyErr_Format(PyExc_TypeError,
- "found a loop for ufunc '%s' "
- "matching the type-tuple, "
- "but the inputs and/or outputs could not be "
- "cast according to the casting rule",
- ufunc_name);
- return -1;
}
}
/* If no function was found, throw an error */
PyErr_Format(PyExc_TypeError,
- "No loop matching the specified signature was found "
- "for ufunc %s", ufunc_name);
+ "No loop matching the specified signature and casting\n"
+ "was found for ufunc %s", ufunc_name);
return -1;
}