Skip to content

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

Closed
Closed

Description

@lesteve

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.

Activity

  1. added this to the 1.12.0 release milestone on Apr 5, 2016
  2. lesteve commented on Apr 5, 2016

    @lesteve
    ContributorAuthor

    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.

  3. seberg commented on Apr 5, 2016

    @seberg
    Member

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

  4. reopened this on Apr 5, 2016
  5. lesteve commented on Apr 5, 2016

    @lesteve
    ContributorAuthor

    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.

  6. ewmoore commented on Apr 5, 2016

    @ewmoore
    Contributor
    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.

  7. seberg commented on Apr 5, 2016

    @seberg
    Member

    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.

  8. lesteve commented on Apr 6, 2016

    @lesteve
    ContributorAuthor

    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)
    
  9. njsmith commented on Apr 6, 2016

    @njsmith
    Member

    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.

  10. 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[/+] on Apr 6, 2016
  11. ewmoore commented on Apr 6, 2016

    @ewmoore
    Contributor

    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).

  12. njsmith commented on Apr 6, 2016

    @njsmith
    Member

    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 :-).

  13. deysaumyajit commented on Apr 27, 2016

    @deysaumyajit

    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++

  14. lesteve commented on Apr 27, 2016

    @lesteve
    ContributorAuthor

    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.

  15. 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[/+] on Apr 27, 2016
  16. deysaumyajit commented on Apr 27, 2016

    @deysaumyajit

    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?

  17. ewmoore commented on Apr 28, 2016

    @ewmoore
    Contributor

    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.

  18. added a commit that references this issue on May 3, 2016
    8e023a4
  19. added a commit that references this issue on Oct 7, 2016
    f236760
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions