diff options
author | Eric Moore <ewm@redtetrahedron.org> | 2016-04-01 14:55:02 -0400 |
---|---|---|
committer | Eric Moore <ewm@redtetrahedron.org> | 2016-03-31 23:58:36 -0400 |
commit | e7ddb392728260801a8ae39ef36b0bbf3abe5604 (patch) | |
tree | cb51699ae47e56871dee8a553fbe2430fd0a8ca9 | |
parent | 2af06c804931aae4b30bb3349bc60271b0b65381 (diff) | |
download | numpy-e7ddb392728260801a8ae39ef36b0bbf3abe5604.tar.gz |
BUG: don't use pow for integer power ufunc loops.
Fixes gh-7405.
-rw-r--r-- | numpy/core/src/umath/loops.c.src | 26 | ||||
-rw-r--r-- | numpy/core/tests/test_umath.py | 5 |
2 files changed, 28 insertions, 3 deletions
diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index 0d9806f5d..a829e4104 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -913,9 +913,29 @@ NPY_NO_EXPORT void @TYPE@_power(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { BINARY_LOOP { - const @ftype@ in1 = (@ftype@)*(@type@ *)ip1; - const @ftype@ in2 = (@ftype@)*(@type@ *)ip2; - *((@type@ *)op1) = (@type@) pow(in1, in2); + @type@ in1 = *(@type@ *)ip1; + @type@ in2 = *(@type@ *)ip2; + @type@ out; + + if (in2 < 0 || in1 == 0) { + *((@type@ *)op1) = 0; + continue; + } + if (in2 == 0) { + *((@type@ *)op1) = 1; + continue; + } + + out = in2 & 1 ? in1 : 1; + in2 >>= 1; + while (in2 > 0) { + in1 *= in1; + if (in2 & 1) { + out *= in1; + } + in2 >>= 1; + } + *((@type@ *) op1) = out; } } diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index f0f664a6f..d3d89f086 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -425,6 +425,11 @@ class TestPower(TestCase): res = x ** np.array([[[2]]]) assert_equal(res.shape, (1, 1, 3)) + def test_integer_power(self): + a = np.array([15, 15], 'i8') + b = a ** a + assert_equal(b, [437893890380859375, 437893890380859375]) + class TestLog2(TestCase): def test_log2_values(self): |