summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorseberg <sebastian@sipsolutions.net>2015-06-13 13:05:34 +0200
committerseberg <sebastian@sipsolutions.net>2015-06-13 13:05:34 +0200
commit88937f8f1d61d889e6923de7e15b63e40fa9a8ee (patch)
treef98a6e0b24e240ff118160eee5951f30578e5a6a
parent1fe98ff582d57c576d95316422a113e681e6773b (diff)
parentf60c553e6c92447d71fc960faf81bdeb9c54bbd6 (diff)
downloadnumpy-88937f8f1d61d889e6923de7e15b63e40fa9a8ee.tar.gz
Merge pull request #5963 from charris/rubustify-tuple-loop-search
Rubustify tuple loop search
-rw-r--r--numpy/core/src/umath/ufunc_type_resolution.c33
-rw-r--r--numpy/core/tests/test_ufunc.py10
2 files changed, 23 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;
}
diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py
index 699a1b2ea..b9412684d 100644
--- a/numpy/core/tests/test_ufunc.py
+++ b/numpy/core/tests/test_ufunc.py
@@ -342,6 +342,16 @@ class TestUfunc(TestCase):
np.add(a, 0.5, sig=('i4', 'i4', 'i4'), out=b, casting='unsafe')
assert_equal(b, [0, 0, 1])
+ def test_true_divide(self):
+ # True_divide has a non uniform signature, see #3484.
+ # This also tests type_tuple_type_resolver.
+ a = np.full(5, 12.5)
+ b = np.full(5, 10.0)
+ tgt = np.full(5, 1.25)
+ assert_almost_equal(np.true_divide(a, b, dtype=np.float64), tgt)
+ assert_almost_equal(np.true_divide(a, b, dtype=np.float32), tgt)
+ assert_raises(TypeError, np.true_divide, a, b, dtype=np.int)
+
def test_sum_stability(self):
a = np.ones(500, dtype=np.float32)
assert_almost_equal((a / 10.).sum() - a.size / 10., 0, 4)