8000 np.power(0, -1) behaviour · Issue #7510 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

np.power(0, -1) behaviour #7510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lesteve opened this issue Apr 5, 2016 · 13 comments
Closed

np.power(0, -1) behaviour #7510

lesteve opened this issue Apr 5, 2016 · 13 comments

Comments

@lesteve
Copy link
Contributor
lesteve commented Apr 5, 2016

This gives 1 as expected in numpy 1.11 but 0 in master. The problem happens only for ints. For floats it works fine, for example np.power(0.0, 0) is 1 in master.

git bisect tells me this is the commit e7ddb39 where things started to go wrong.

ping @ewmoore, @jaimefrio.

@lesteve
Copy link
Contributor Author
lesteve commented Apr 5, 2016

I'll open a PR to fix the np.power(0, 0) case but it looks like np.power(0, -1) has changed behaviour between 1.11 and master and I am not quite sure what it should return.

@seberg
Copy link
Member
seberg commented Apr 5, 2016

Reopening, just in case we need to revisit the power(0, -1) case.

@seberg seberg reopened this Apr 5, 2016
@lesteve
Copy link
Contributor Author
lesteve commented Apr 5, 2016

Just for completeness np.power(0, -1) returns np.iinfo('int64').min i.e. -9223372036854775808 in 1.11 and 0 in master. Not sure whether there is something consensual to return in this case.

@ewmoore
Copy link
Contributor
ewmoore commented Apr 5, 2016
In [18]: inttypes = ['i1', 'i2', 'i4', 'i8', 'u1', 'u2', 'u4', 'u8']

In [19]: for dt in inttypes:
   ....:     a = np.array([0,0,0], dt)
   ....:     b = np.array([0, -1, -2], dt)
   ....:     c = a**b
   ....:     print(repr(c))
   ....:
/home/ewm/.pyenv/numpy-1.11-scipy-0.17-py35/bin/ipython:4: RuntimeWarning: divide by zero encountered in power
  import re
/home/ewm/.pyenv/numpy-1.11-scipy-0.17-py35/bin/ipython:4: RuntimeWarning: invalid value encountered in power
  import re
array([1, 0, 0], dtype=int8)
array([1, 0, 0], dtype=int16)
array([          1, -2147483648, -2147483648], dtype=int32)
array([                   1, -9223372036854775808, -9223372036854775808])
array([1, 0, 0], dtype=uint8)
array([1, 0, 0], dtype=uint16)
array([1, 0, 0], dtype=uint32)
array([1, 0, 0], dtype=uint64)

So for 8 and 16 bit signed integers we returned 0. For all other integer types we returned the minimum value. I guess we'd like to make this consistently return the minimum value then? AFAICT these return values where just happy accidents in the past since there wasn't any code that explicitly chose these values.

@seberg
Copy link
Member
seberg commented Apr 5, 2016

Those return values mostly came from how np.nan is cast to int probably. It is a bit tricky, since we may not want to raise an error, nor am I sure we can raise an error easily. Another thing to check is whether the warning existed/still does exist? Though my guess is that warning is even configurable to error.

I doubt there is a simple clear "right" here, except maybe that it could be nice to give a warning.

@lesteve
Copy link
Contributor Author
lesteve commented Apr 6, 2016

Just for completeness in master np.power(some_int, -1) always return 0.

Reusing the same snippet as posted by @ewmoore:

import numpy as np

inttypes = ['i1', 'i2', 'i4', 'i8', 'u1', 'u2', 'u4', 'u8']

for dt in inttypes:
    a = np.array([0,0,0], dt)
    b = np.array([0, -1, -2], dt)
    c = a**b
    print(repr(c))

Output:

array([1, 0, 0], dtype=int8)
array([1, 0, 0], dtype=int16)
array([1, 0, 0], dtype=int32)
array([1, 0, 0])
array([1, 0, 0], dtype=uint8)
array([1, 0, 0], dtype=uint16)
array([1, 0, 0], dtype=uint32)
array([1, 0, 0], dtype=uint64)

@njsmith
Copy link
Member
njsmith commented Apr 6, 2016

Why not raise an error? I understand the idea that errors are not so nice because they interrupt vectorised calculation flows, but surely silently returning nonsense is worse, and with ints there is no nan available so those are our only two options.

@lesteve lesteve changed the title Regression: np.power(0, 0) is 0 instead of 1 in master Regression: np.power(0, 0) is 0 instead of 1 in master and np.power(0, -1) behaviour Apr 6, 2016
@ewmoore
Copy link
8000
Contributor
ewmoore commented Apr 6, 2016

Surely then calling np.floor_divide to divide by 0 should also be an error and not raise a RuntimeWarning?

In [9]: np.floor_divide(np.arange(10), np.zeros(10, int))
/home/ewm/.pyenv/numpy-1.11-scipy-0.17-py35/bin/ipython:1: RuntimeWarning: divide by zero encountered in floor_divide
  #!/home/ewm/.pyenv/numpy-1.11-scipy-0.17-py35/bin/python3
Out[9]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

I think we should 1) ensure that the appropriate RuntimeWarning is emitted if we try to raise an integer to a negative power and 2) return either the minimum value or 0. I lean towards returning the minimum value since that's apparently what 32 and 64 bit integers have been doing (on 64-bin linux and windows at least).

@njsmith
Copy link
Member
njsmith commented Apr 6, 2016

Yeah, we don't really have any coherent policy for how to handle exceptional conditions in integer calculations right now. Sometimes we check for overflow, sometimes not... It's a mess.

We can split this into the short term and long term discussions: If current master is causing regressions then fine, that's some argument for at least reverting to the same odd behavior as 1.11-and-earlier while continuing the ongoing discussion about integer error conditions. But in that longer discussion, if the best answer to "why shouldn't we raise an error?" is "well this other operation also returns nonsensical results" then I don't find that very compelling :-).

@deysaumyajit
Copy link
deysaumyajit commented Apr 27, 2016

Just to clarify, in the present 'master' branch in the forked repository, np.power(0,0) gives 1. Is this issue solved or am I running a wrong version of numpy. My version of numpy is 1.12.0.dev0-1b6831b as shown on running pip list

Upd : np.power(0,-1) gives 0 instead of "inf" or something of this sort that is given on doing pow(0,-1) on C++

@lesteve
Copy link
Contributor Author
lesteve commented Apr 27, 2016

Just to clarify, in the present 'master' branch in the forked repository, np.power(0,0) gives 1. Is this issue solved or am I running a wrong version of numpy.

np.power(0, 0) returns 1 in master since #7511 has been merged.

Upd : np.power(0,-1) gives 0 instead of "inf" or something of this sort that is given on doing pow(0,-1) on C++

This issue is still in master. The consensus seems to be to raise an error for integer type arrays.

I updated the title to make it more clear that only the np.power(0, -1) issue remains.

@lesteve lesteve changed the title Regression: np.power(0, 0) is 0 instead of 1 in master and np.power(0, -1) behaviour np.power(0, -1) behaviour Apr 27, 2016
@deysaumyajit
Copy link

I want to take this up as this seems to be an easy fix and could be my first open source contribution. Could I get some help as to what files to look into to fix this?

@ewmoore
Copy link
Contributor
ewmoore commented Apr 28, 2016

Look at numpy/core/src/umath/loops.c.src. You'll need to use the NPY_ALLOW_C_API macros to reacquire the GIL before raising the error. There is an example of doing this in loops.c.src on line 1153.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants
0