diff options
-rw-r--r-- | numpy/core/src/multiarray/number.c | 8 | ||||
-rw-r--r-- | numpy/core/src/multiarray/scalartypes.c.src | 8 | ||||
-rw-r--r-- | numpy/core/src/umath/scalarmath.c.src | 37 | ||||
-rw-r--r-- | numpy/core/tests/test_scalarmath.py | 11 |
4 files changed, 52 insertions, 12 deletions
diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index c4e675430..62e8e3884 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -614,10 +614,14 @@ fast_scalar_power(PyArrayObject *a1, PyObject *o2, int inplace) } static PyObject * -array_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo)) +array_power(PyArrayObject *a1, PyObject *o2, PyObject *modulo) { - /* modulo is ignored! */ PyObject *value; + if (modulo != Py_None) { + /* modular exponentiation is not implemented (gh-8804) */ + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } GIVE_UP_IF_HAS_RIGHT_BINOP(a1, o2, "__pow__", "__rpow__", 0, nb_power); value = fast_scalar_power(a1, o2, 0); if (!value) { diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index f85e3b828..bad61e3f0 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -149,11 +149,17 @@ gentype_free(PyObject *v) static PyObject * -gentype_power(PyObject *m1, PyObject *m2, PyObject *NPY_UNUSED(m3)) +gentype_power(PyObject *m1, PyObject *m2, PyObject *modulo) { PyObject *arr, *ret, *arg2; char *msg="unsupported operand type(s) for ** or pow()"; + if (modulo != Py_None) { + /* modular exponentiation is not implemented (gh-8804) */ + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + if (!PyArray_IsScalar(m1, Generic)) { if (PyArray_Check(m1)) { ret = Py_TYPE(m1)->tp_as_number->nb_power(m1,m2, Py_None); diff --git a/numpy/core/src/umath/scalarmath.c.src b/numpy/core/src/umath/scalarmath.c.src index ed6553f69..723ee998a 100644 --- a/numpy/core/src/umath/scalarmath.c.src +++ b/numpy/core/src/umath/scalarmath.c.src @@ -956,7 +956,7 @@ static PyObject * #if @cmplx@ static PyObject * -@name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) +@name@_power(PyObject *a, PyObject *b, PyObject *modulo) { PyObject *ret; @type@ arg1, arg2; @@ -969,13 +969,13 @@ static PyObject * break; case -1: /* can't cast both safely mixed-types? */ - return PyArray_Type.tp_as_number->nb_power(a,b,NULL); + return PyArray_Type.tp_as_number->nb_power(a,b,modulo); case -2: /* use default handling */ if (PyErr_Occurred()) { return NULL; } - return PyGenericArrType_Type.tp_as_number->nb_power(a,b,NULL); + return PyGenericArrType_Type.tp_as_number->nb_power(a,b,modulo); case -3: default: /* @@ -986,6 +986,12 @@ static PyObject * return Py_NotImplemented; } + if (modulo != Py_None) { + /* modular exponentiation is not implemented (gh-8804) */ + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + PyUFunc_clearfperr(); /* @@ -1030,7 +1036,7 @@ static PyObject * #elif @isint@ static PyObject * -@name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) +@name@_power(PyObject *a, PyObject *b, PyObject *modulo) { PyObject *ret; @type@ arg1, arg2, out; @@ -1040,13 +1046,13 @@ static PyObject * break; case -1: /* can't cast both safely mixed-types? */ - return PyArray_Type.tp_as_number->nb_power(a,b,NULL); + return PyArray_Type.tp_as_number->nb_power(a,b,modulo); case -2: /* use default handling */ if (PyErr_Occurred()) { return NULL; } - return PyGenericArrType_Type.tp_as_number->nb_power(a,b,NULL); + return PyGenericArrType_Type.tp_as_number->nb_power(a,b,modulo); case -3: default: /* @@ -1056,6 +1062,13 @@ static PyObject * Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } + + if (modulo != Py_None) { + /* modular exponentiation is not implemented (gh-8804) */ + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + PyUFunc_clearfperr(); /* @@ -1081,7 +1094,7 @@ static PyObject * #else static PyObject * -@name@_power(PyObject *a, PyObject *b, PyObject *NPY_UNUSED(c)) +@name@_power(PyObject *a, PyObject *b, PyObject *modulo) { PyObject *ret; @type@ arg1, arg2; @@ -1094,13 +1107,13 @@ static PyObject * break; case -1: /* can't cast both safely mixed-types? */ - return PyArray_Type.tp_as_number->nb_power(a,b,NULL); + return PyArray_Type.tp_as_number->nb_power(a,b,modulo); case -2: /* use default handling */ if (PyErr_Occurred()) { return NULL; } - return PyGenericArrType_Type.tp_as_number->nb_power(a,b,NULL); + return PyGenericArrType_Type.tp_as_number->nb_power(a,b,modulo); case -3: default: /* @@ -1111,6 +1124,12 @@ static PyObject * return Py_NotImplemented; } + if (modulo != Py_None) { + /* modular exponentiation is not implemented (gh-8804) */ + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + PyUFunc_clearfperr(); /* diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index e43a0b2e0..1cafde5a0 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -177,6 +177,17 @@ class TestPower(TestCase): else: assert_almost_equal(result, 9, err_msg=msg) + def test_modular_power(self): + # modular power is not implemented, so ensure it errors + a = 5 + b = 4 + c = 10 + expected = pow(a, b, c) + for t in (np.int32, np.float32, np.complex64): + # note that 3-operand power only dispatches on the first argument + assert_raises(TypeError, operator.pow, t(a), b, c) + assert_raises(TypeError, operator.pow, np.array(t(a)), b, c) + class TestModulus(TestCase): |