summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2018-11-16 18:16:53 +0100
committerGitHub <noreply@github.com>2018-11-16 18:16:53 +0100
commit12b3e3f548556630bc77f4fdcc23dc670b4e6a78 (patch)
tree106e8b52bf7d0e67315ada36c9a7ea78e852d7b3
parent7c938b42a797111d6fc1d4442ee93e6839f3dee4 (diff)
parent831e311422ecf574669f06a25aa02a567a8ff243 (diff)
downloadcython-12b3e3f548556630bc77f4fdcc23dc670b4e6a78.tar.gz
Merge pull request #2709 from serge-sans-paille/fix/pythran-power
Fix/pythran power
-rw-r--r--Cython/Compiler/ExprNodes.py19
-rw-r--r--Cython/Compiler/Pythran.py9
-rw-r--r--tests/run/numpy_pythran_unit.pyx10
3 files changed, 30 insertions, 8 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index 2c7e025b8..b60d405f1 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -11115,12 +11115,19 @@ class BinopNode(ExprNode):
if self.type.is_pythran_expr:
code.putln("// Pythran binop")
code.putln("__Pyx_call_destructor(%s);" % self.result())
- code.putln("new (&%s) decltype(%s){%s %s %s};" % (
- self.result(),
- self.result(),
- self.operand1.pythran_result(),
- self.operator,
- self.operand2.pythran_result()))
+ if self.operator == '**':
+ code.putln("new (&%s) decltype(%s){pythonic::numpy::functor::power{}(%s, %s)};" % (
+ self.result(),
+ self.result(),
+ self.operand1.pythran_result(),
+ self.operand2.pythran_result()))
+ else:
+ code.putln("new (&%s) decltype(%s){%s %s %s};" % (
+ self.result(),
+ self.result(),
+ self.operand1.pythran_result(),
+ self.operator,
+ self.operand2.pythran_result()))
elif self.operand1.type.is_pyobject:
function = self.py_operation_function(code)
if self.operator == '**':
diff --git a/Cython/Compiler/Pythran.py b/Cython/Compiler/Pythran.py
index 056985cd1..fc8195696 100644
--- a/Cython/Compiler/Pythran.py
+++ b/Cython/Compiler/Pythran.py
@@ -60,8 +60,12 @@ def type_remove_ref(ty):
def pythran_binop_type(op, tA, tB):
- return "decltype(std::declval<%s>() %s std::declval<%s>())" % (
- pythran_type(tA), op, pythran_type(tB))
+ if op == '**':
+ return 'decltype(pythonic::numpy::functor::power{}(std::declval<%s>(), std::declval<%s>()))' % (
+ pythran_type(tA), pythran_type(tB))
+ else:
+ return "decltype(std::declval<%s>() %s std::declval<%s>())" % (
+ pythran_type(tA), op, pythran_type(tB))
def pythran_unaryop_type(op, type_):
@@ -209,6 +213,7 @@ def include_pythran_generic(env):
env.add_include_file("pythonic/python/core.hpp")
env.add_include_file("pythonic/types/bool.hpp")
env.add_include_file("pythonic/types/ndarray.hpp")
+ env.add_include_file("pythonic/numpy/power.hpp")
env.add_include_file("<new>") # for placement new
for i in (8, 16, 32, 64):
diff --git a/tests/run/numpy_pythran_unit.pyx b/tests/run/numpy_pythran_unit.pyx
index 3992233b0..4637e66c6 100644
--- a/tests/run/numpy_pythran_unit.pyx
+++ b/tests/run/numpy_pythran_unit.pyx
@@ -13,3 +13,13 @@ def trigo(np.ndarray[double, ndim=1] angles):
array([ 1., -1., 1.])
"""
return np.cos(angles)
+
+def power(np.ndarray[double, ndim=1] values):
+
+ """
+ >>> a = np.array([0., 1., 2.])
+ >>> res = power(a)
+ >>> res[0], res[1], res[2]
+ (0.0, 1.0, 8.0)
+ """
+ return values ** 3