-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
BUG/ENH: Switch to simplified __numpy_ufunc__/binop interaction #6001
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
Conversation
@njsmith - the comments in scalarmath.c.src (https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/scalarmath.c.src#L541)
So, you hit (2) here, though I think what we'd really want is:
I.e., my sense is that the priority case should be separated out from the unknown object type, returning |
FWIW: all polynomial failures seem to be due to division by a And after a bit more investigation, the problem seems to be that in
Which would seem a proper bug on its own... |
For the |
The scipy.sparse checks are done wrong --- you need to check the exact
class names, otherwise you are blocking using numpy_ufunc in the future.
|
Up to you what you prefer. We could have a list of the sparse classes as
|
Ok, indeed, I don't know what I was thinking... Still, best to keep the
special cases to minimum.
|
…attr_string.h This is an ugly kluge, but until we merge multiarray.so and umath.so moving stuff into private/*.h serves as a reasonable workaround.
7e4c14c
to
7ffa5dd
Compare
Okay, largely redid this and it now passes tests (though could probably use a few more). I'm pretty happy with the logic flow now: we now explicitly check whether we are in Unfortunately to do this I had to put a bunch of code into header files in |
de6d3bb
to
878f7e9
Compare
Spoke too soon. Aside from some annoying segfault on 3.2 (doubtless a shallow bug in the 3.2-only unicode handling branch in
This is baffling to me, because (a) as far as I can tell, all the I mean, it's not not even necessarily wrong -- arguably array scalars should return |
For some reason, np.generic.__pow__ felt the need to reimplement Python's full binop dispatch logic. The code has been there since the beginning of (git) history, isn't required to pass any tests, and AFAICT doesn't actually do anything interesting. I suspect it was just split apart from the (much more trivial) implementation of all the other np.generic binop methods because nb_power has a slightly different signature than all the others (it takes an extra argument, which we ignore, but still has to be accepted and passed as appropriate), and then got forgotten when the other implementations were simplified long ago. This commit throws away all that code and makes gentype_power a 2-liner, just like all the other gentype_@name@ methods.
878f7e9
to
35471fc
Compare
35471fc
to
336421e
Compare
As per the discussion at numpygh-5844, and in particular numpy#5844 (comment) this commit switches binop dispatch to mostly defer to ufuncs, except in some specific cases elaborated in a long comment in number.c. The basic strategy is to define a single piece of C code that knows how to handle forward binop overrides, and we put it into private/binop_override.h so that it can be accessed by both the array code in multiarray.so and the scalar code in umath.so.
336421e
to
c16c003
Compare
Okay, I think this is clean and solid. On my machine it now passes both array and scalar tests on at least 2.7, 3.2, and 3.4 -- we'll see what travis says beyond that :-). I think this is worth merging regardless of the details of how #5844 is finally resolved -- aside from being a complete implementation of "option 1", it also provides all the ground-clearing needed to make it easy to implement "option 2" or "option 3", and in the alternative where we decide to temporarily disable |
* dispatch rules where the ndarray binops sometimes return NotImplemented | ||
* rather than always dispatching to ufuncs. | ||
* | ||
* Note that these rules are also implemented by ABCArray, so any changes here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@njsmith This will be your next PR? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh heh right. I should probably remove that comment and then let the ABCArray
PR re-add it.
Any chance I could interest you in putting that one together...? I'm looking at my schedule and beginning to ponder whether it was really wise to plan 3 different major projects for scipy... (the dev meeting + my talk + another short talk for a bof)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... no commitments, but given that I've already signed up to write BackwardCompatibleABCArray
(outside of numpy) I suppose I can give this a try.
@pv: Oh, but I haven't actually narrowed down the scipy.sparse special case any further (mostly because I'm a bit nervous about making an explicit list of scipy.sparse classes, in case I miss one by accident or if any get added in the future). But I could do that if you prefer. |
The code looks good, but this does seem to break backwards compatibility for in-place operations where |
@mhvk: Not sure what you mean -- both before and after this patch, inplace operations look like
and
so I didn't touch any such checks here. And in current master:
|
@njsmith apparently the behavior on master was already broken. On NumPy 1.9.2 this works:
(there may be a lesson here about the hard to understand operator overrides....) |
@shoyer: jinx |
OK, thanks for looking into this; as I noted in #6020, I think it makes most sense not to change the |
I'm fine with not deprecating |
Agreed that really the issues are separate. So then the idea is to follow it up with a PR that fully restores the behaviour of |
☔ The latest upstream changes (presumably #6047) made this pull request unmergeable. Please resolve the merge conflicts. |
Closing. I believe this is now part of #8247. |
[Posting this now for any feedback, though it still needs some work to sort out scalar handling -- CC @pv @mhvk @shoyer @charris]
As per the discussion at gh-5844, and in particular
#5844 (comment)
this commit switches binop dispatch to mostly defer to ufuncs, except
in some specific cases elaborated in a long comment in number.c.
This currently fails on the following code from test_ufunc.py, which
creates an infinite loop and eats memory until killed:
I don't yet really understand what is going on here. As far as I've
tracked it down:
np.float64.add is scalarmath.c.src:@Oper@_@name@
@Oper@_@name@ calls _@name@_convert2_to_ctypes
On -1 or -2 returns, @Oper@@name@ calls one of
PyArray_Type.tp_as_number->nb@Oper@(a, b)
PyGenericArrType_Type.tp_as_number->nb_@oper@(a, b)
The latter is gentype_@name@, which for "add" just calls back to
PyArray_Type.tp_as_number->nb_@name@
so it should be equivalent. For some other cases, things are more
complicated -- in particular gentype_multiply implements sequence
multiplication, which looks suspicious given the definition of
MyThing. Except we crash on float64 + MyThing as well, so that can't
be it.
Actually, I guess the problem must be exactly that we are deferring
to the ufunc; np.add(5, MyThing((3, 3))) also blows up. We shouldn't
be, though, because of the array_priority.
More after I wake up again...