8000 BUG: __array_priority__ > 0 in float subclass causes comparison with np.float64 to fail · Issue #6133 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: __array_priority__ > 0 in float subclass causes comparison with np.float64 to fail #6133

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
DanielSank opened this issue Jul 29, 2015 · 5 comments

Comments

@DanielSank
Copy link
DanielSank commented Jul 29, 2015

Consider a subclass of float:

class Bar(float):
    __array_priority__ = 2

Now we try to compare an instance of Bar with a numpy float64:

import numpy as np
x = np.float64(1)
y = Bar(2.0)
x < y
False

Puzzled, we try the following

import numpy as np

def make_class(x):
    """Get a float subclass with adjustable __array_priority"""
    class Bar(float):
        __array_priority__ = x

    return Bar


def test(priorities):
    """Check float comparison for various __array_priority__ values"""
    results = []
    for priority in priorities:
        x = np.float64(1)
        Bar = make_class(priority)
        y = Bar(2.0)
        results.append(x < y)
    for p, v in zip(priorities, results):
        print("{} {}".format(p, v))

Running test over a few choice values we find (note that the __array_priority__ of np.float64 is -1000000.0)

__array_priority__   |     x < y
--------------------------------------------------
-10000000            |     True
-1000001.0           |     True
-1000000.0           |     True (same __array_priority__ as float64)
-999999.0            |     True
-1                   |     True
0                    |     True
0.3                  |     False
1                    |     False
2                    |     False

As you can see, if __array_priority__ is greater than 0, the comparison fails.
Whether our custom __array_priority__ is greater or less than np.float64's __array_priority__ doesn't matter.

Some of my colleagues tried this on their machines and we found that this problem only happens with python 2.7.6 (64 bit) and numpy 1.9.2. Using either that python version or that numpy version alone does not reproduce the bug. It only happens when both of those versions are used together.

Here is a table of python and numpy versions and whether or not this bug shows up

python            | numpy | x < y (__array_priority__ = 15)
------------------|-------|--------------------------------
2.7.9 (32 bit)    | 1.8.1 | True
2.7.10 (64 bit)   | 1.8.1 | True
2.7.6 (64 bit)    | 1.8.2 | True
2.7.6 (64 bit)    | 1.8.2 | True
2.7.9 (64 bit)    | 1.9.2 | True
2.7.6 (64 bit)    | 1.9.2 | False   (three confirmations)

Also posted to Stackoverflow.


Summary 2019-05-03 by @seberg

This issue still seems present in the 1.16.x branch (python 2). Since it is python 2 only, we can probably close it at some point. Although, I did not follow whether there is some additional underlying problem.

@DanielSank
Copy link
Author

Seems like this could be related to #4766.

8000

@DanielSank DanielSank changed the title __array_priority__ > 0 in float subclass causes comparison with np.float64 to fail BUG: __array_priority__ > 0 in float subclass causes comparison with np.float64 to fail Jul 30, 2015
@DanielSank
Copy link
Author

Some more information:

x = np.float64(1)
c = make_class(1)
np.generic.__lt__(x, c(2))
>>> False
import numpy.core.umath as umath
umath.less(x, c(2))
>>> True

@btchiaro
Copy link

This error is also present with 2.7.6 (64 bit) and numpy 1.9.1

@ejeffrey
Copy link

I tracked this down a bit. The problem here is that in numpy 1.9.3, numpy converts x to an np.ndarray before passing it to y.__gt__. y is just a python float, and its __gt__ method doesn't know how to compare to an array so it returns NotImplemented. numpy then does something and gets the wrong answer, but I think it is a little unfair to blame numpy for that: you explicitly indicated that class Bar should be preferred over normal arrays for comparison operators, but it can't actually handle array inputs.

This can be solved by changing this to class Bar(np.float64), which is a subclass of float, but actually implements the array API. It seems to me that numpy should be raising a TypeError here since the higher priority type is saying the comparison is not possible.

numpy 1.8.2 does not convert the input to an array before calling the __gt__ method, so it works properly.

y > x works properly because neither x nor y is a subclass of the other, so the python interpreter directly calls y.__gt__ first without giving numpy a chance to convert x to an array.

@mattip
Copy link
Member
mattip commented May 30, 2019

Closing, the code at the beginning of the issue now returns True. Not clear when the behaviour changed. Please reopen if there is more to do here.

@mattip mattip closed this as completed May 30, 2019
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

No branches or pull requests

4 participants
0