Skip to content

Conversation

@eric-wieser
Copy link
Member

@eric-wieser eric-wieser commented Jan 25, 2018

We still parse the out argument 3 times in every ufunc call (PyUFunc_Gener*Function, get_ufunc_arguments, ufunc_generic_call), but at least we now do it the same way each time. Actually reusing the result can wait for a maintenance PR.


Fixes gh-10450.

The previous behavior for ufunc(in1, in2, out_arr) is now applied to all calling conventions for out - namely, the arg tuple passed into __array_wrap__ and __array_prepare__ is (in1, ..., inN, out1, ..., outN). This tuple will contain None for absent out argument, which is consistent with what already happened for ufunc(..., None).

This breaks one test that asserts the length of the args tuple is 2 for np.minimum(x, y).
However, I'd argue that test was broken anyway, and it has been expanded to cover all cases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this has changed. I think one should continue to suppress all-None outputs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All none outputs were not suppressed before when none was passed explicitly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But here you do not pass in None!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but it's important that passing the documented default behave the same as not passing it, whatever that behavior may be. I could get behind stripping all-none outputs too though - it just means users are far less likely to implement some-none outputs correctly

numpy/ma/core.py Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, this is my worry: if even in numpy, we need this fix for __array_wrap__, we are likely going to break other classes as well. Do any tests break if we remove the output arguments in __array_prepare__?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember that this part of the patch stands alone as a bug fix for np.add(a, b, c) currently inheriting the mask of c.

Any classes that we break are necessarily already broken in some calling convention in 1.14.

Omitting output arguments is possibly safest simply since passing them in the first place is uncommon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, I forgot that __array_wrap__ does get them if put as a positional argument. I wonder if it makes more sense to do this fix in a separate PR, so we can disentangle it from the larger reworking (which could them remove this again if we go for no outputs at all).

Copy link
Member Author

@eric-wieser eric-wieser Jan 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this seems like an uncontroversial fix - i'll make a separate patch for these lines (#10479)

@eric-wieser eric-wieser changed the title BUG: Always treat output arguments the same way to ufunc.__call__ BUG: Always include outputs in the arg tuple passed to __array_wrap__/__array_prepare__ Jan 26, 2018
@eric-wieser eric-wieser changed the base branch from master to maintenance/1.14.x January 26, 2018 07:18
@eric-wieser eric-wieser changed the base branch from maintenance/1.14.x to master January 26, 2018 07:19
@eric-wieser
Copy link
Member Author

^ that was a hack to make github register the first commit is already merged

Fixes numpygh-10450.

The previous behavior for `ufunc(..., out=arr)` is now applied to all calling conventions for `out` - namely, the arg tuple passed into `__array_wrap__` and `__array_prepare__` is `(in1, ..., inN, out1, ..., outN)`. This tuple will contain `None` for absent `out` argument, which is consistent with what already happened for `ufunc(..., out=None)`.

This breaks one test that asserts the length of the args tuple is `2` for np.minimum(x, y).
However, I'd argue that test was broken anyway, and it has been expanded to cover all cases.
@eric-wieser
Copy link
Member Author

#10919 replaces this PR.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants