10000 BUG: don't use pow for integer power ufunc loops. · numpy/numpy@e7ddb39 · GitHub
[go: up one dir, main page]

Skip to content

Commit e7ddb39

Browse files
committed
BUG: don't use pow for integer power ufunc loops.
Fixes gh-7405.
1 parent 2af06c8 commit e7ddb39

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

numpy/core/src/umath/loops.c.src

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -913,9 +913,29 @@ NPY_NO_EXPORT void
913913
@TYPE@_power(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
914914
{
915915
BINARY_LOOP {
916-
const @ftype@ in1 = (@ftype@)*(@type@ *)ip1;
917-
const @ftype@ in2 = (@ftype@)*(@type@ *)ip2;
918-
*((@type@ *)op1) = (@type@) pow(in1, in2);
916+
@type@ in1 = *(@type@ *)ip1;
917+
@type@ in2 = *(@type@ *)ip2;
918+
@type@ out;
919+
920+
if (in2 < 0 || in1 == 0) {
921+
*((@type@ *)op1) = 0;
922+
continue;
923+
}
924+
if (in2 == 0) {
925+
*((@type@ *)op1) = 1;
926+
continue;
927+
}
928+
929+
out = in2 & 1 ? in1 : 1;
930+
in2 >>= 1;
931+
while (in2 > 0) {
932+
in1 *= in1;
933+
if (in2 & 1) {
934+
out *= in1;
935+
}
936+
in2 >>= 1;
937+
}
938+
*((@type@ *) op1) = out;
919939
}
920940
}
921941

numpy/core/tests/test_umath.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,11 @@ def test_fast_power(self):
425425
res = x ** np.array([[[2]]])
426426
assert_equal(res.shape, (1, 1, 3))
427427

428+
def test_integer_power(self):
429+
a = np.array([15, 15], 'i8')
430+
b = a ** a
431+
assert_equal(b, [437893890380859375, 437893890380859375])
432+
428433

429434
class TestLog2(TestCase):
430435
def test_log2_values(self):

0 commit comments

Comments
 (0)
0