Skip to content

Fix integer power opcodes for negative exponents - #576

Open
raashish1601 wants to merge 1 commit into
pydata:masterfrom
raashish1601:fix/int-pow-negative-exponent
Open

raashish1601 wants to merge 1 commit into
pydata:masterfrom
raashish1601:fix/int-pow-negative-exponent

Conversation

@raashish1601

Copy link
Copy Markdown

For an integer base ** n where n comes from an array and is negative, the int and long long power opcodes compute 1 / base. Two problems with that:

  • 0 ** -1 divides by zero. That's undefined behaviour in C. With the Windows wheel (numexpr 2.14.2 from PyPI) it kills the process with STATUS_INTEGER_DIVIDE_BY_ZERO; GCC happens to compile 1 / x without a division, so Linux builds return 0.
  • The exponent is ignored, so (-1) ** -2 gives -1 instead of 1.
import numpy as np, numexpr as ne
base = np.array([-1, 0], dtype=np.int32); n = np.array([-2, -1], dtype=np.int32)
ne.evaluate("base ** n")  # Windows: process crashes; Linux: [-1, 0]

With this change a negative exponent gives base for base == ±1 and an odd exponent, 1 for base == ±1 and an even exponent, and 0 otherwise (including 0 ** -n, which keeps the result Linux builds already return, similar to integer division by zero giving 0). The scalar-exponent case is unchanged, since pow_op() already rejects negative integer constants.

Added test_negative_power_array for int32 and int64; it fails on main and passes with this change. Built the extension in a python:3.12 Docker image and ran numexpr.tests.test_numexpr (6043 passed). Also added a line to the release notes.

For a negative exponent the int and long long power opcodes computed
1 / base. That divides by zero for a zero base (undefined behaviour,
which crashes the process with MSVC builds) and ignores the exponent,
so (-1) ** -2 gave -1. Return base for |base| == 1 and odd exponents,
1 for |base| == 1 and even exponents, and 0 otherwise.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant