From 7e0cd9a45dd81a84cfbcfbe957ae69c5d9ebce76 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 26 Dec 2013 22:21:16 +0100 Subject: [PATCH] BUG: Only convert 0d arrays to scalars in power Operations such as `x**array([2])` would convert the 2 into an integer and loose the dimension information, because the array (at this time, it is deprecated), supports `__index__` even though it is not 0-d. This fixes it, by not trying the index machinery when it was an array, since it is unnecessary. Closes gh-4145 --- numpy/core/src/multiarray/number.c | 47 ++++++++++++++++++------------ numpy/core/tests/test_umath.py | 13 ++++++--- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index a00f6729c6ac..926db27e8c30 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -391,32 +391,41 @@ is_scalar_with_conversion(PyObject *o2, double* out_exponent) *out_exponent = PyFloat_AsDouble(o2); return NPY_FLOAT_SCALAR; } - if ((PyArray_IsZeroDim(o2) && - ((PyArray_ISINTEGER((PyArrayObject *)o2) || - (optimize_fpexps && PyArray_ISFLOAT((PyArrayObject *)o2))))) || - PyArray_IsScalar(o2, Integer) || - (optimize_fpexps && PyArray_IsScalar(o2, Floating))) { - temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); - if (temp != NULL) { + if (PyArray_Check(o2)) { + if ((PyArray_NDIM(o2) == 0) && + ((PyArray_ISINTEGER((PyArrayObject *)o2) || + (optimize_fpexps && PyArray_ISFLOAT((PyArrayObject *)o2))))) { + temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); + if (temp == NULL) { + return NPY_NOSCALAR; + } *out_exponent = PyFloat_AsDouble(o2); Py_DECREF(temp); - if (PyArray_IsZeroDim(o2)) { - if (PyArray_ISINTEGER((PyArrayObject *)o2)) { - return NPY_INTPOS_SCALAR; - } - else { /* ISFLOAT */ - return NPY_FLOAT_SCALAR; - } + if (PyArray_ISINTEGER((PyArrayObject *)o2)) { + return NPY_INTPOS_SCALAR; } - else if (PyArray_IsScalar(o2, Integer)) { - return NPY_INTPOS_SCALAR; - } - else { /* IsScalar(o2, Floating) */ + else { /* ISFLOAT */ return NPY_FLOAT_SCALAR; } } } - if (PyIndex_Check(o2)) { + else if (PyArray_IsScalar(o2, Integer) || + (optimize_fpexps && PyArray_IsScalar(o2, Floating))) { + temp = Py_TYPE(o2)->tp_as_number->nb_float(o2); + if (temp == NULL) { + return NPY_NOSCALAR; + } + *out_exponent = PyFloat_AsDouble(o2); + Py_DECREF(temp); + + if (PyArray_IsScalar(o2, Integer)) { + return NPY_INTPOS_SCALAR; + } + else { /* IsScalar(o2, Floating) */ + return NPY_FLOAT_SCALAR; + } + } + else if (PyIndex_Check(o2)) { PyObject* value = PyNumber_Index(o2); Py_ssize_t val; if (value==NULL) { diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index 6db95e9a6dff..d5736e077132 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -175,6 +175,11 @@ def test_fast_power(self): x = np.array([1, 2, 3], np.int16) assert_((x**2.00001).dtype is (x**2.0).dtype) + # Check that the fast path ignores 1-element not 0-d arrays + res = x ** np.array([[[2]]]) + assert_equal(res.shape, (1, 1, 3)) + + class TestLog2(TestCase): def test_log2_values(self) : x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] @@ -900,9 +905,9 @@ def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): assert_equal(res1[4], (a, b)) assert_equal(res0[5], {}) assert_equal(res1[5], {}) - + def test_ufunc_override_mro(self): - + # Some multi arg functions for testing. def tres_mul(a, b, c): return a * b * c @@ -929,7 +934,7 @@ def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): class C(object): def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): return NotImplemented - + class CSub(object): def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): return NotImplemented @@ -961,7 +966,7 @@ def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): assert_equal(three_mul_ufunc(a, 1, 2), "A") assert_equal(three_mul_ufunc(1, a, 2), "A") assert_equal(three_mul_ufunc(1, 2, a), "A") - + assert_equal(three_mul_ufunc(a, a, 6), "A") assert_equal(three_mul_ufunc(a, 2, a), "A") assert_equal(three_mul_ufunc(a, 2, b), "A")