Skip to content
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

BUG/DEP: Make ufunclike functions more ufunc-like #8996

Merged
merged 2 commits into from
Apr 28, 2017

Conversation

eric-wieser
Copy link
Member

@eric-wieser eric-wieser commented Apr 26, 2017

This fixes #8993 and #8995

@eric-wieser eric-wieser force-pushed the fix-ufunclike branch 2 times, most recently from 6618d12 to 3a1e139 Compare April 26, 2017 18:30
@eric-wieser eric-wieser changed the title Fix ufunclike issues BUG/DEP: Make ufunclike functions more ufunc-like Apr 26, 2017
assert_warns(DeprecationWarning, ufl.fix, [1, 2], y=nx.empty(2))
assert_warns(DeprecationWarning, ufl.isposinf, [1, 2], y=nx.empty(2))
assert_warns(DeprecationWarning, ufl.isneginf, [1, 2], y=nx.empty(2))
def test_scalar(self):
Copy link
Member

@charris charris Apr 26, 2017

Choose a reason for hiding this comment

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

@need a blank line between functions.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, bad rebase...

Copy link
Member Author

Choose a reason for hiding this comment

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

(fixed)

y = nx.empty(x.shape, dtype=nx.bool_)
nx.logical_and(nx.isinf(x), nx.signbit(x), y)
return y
return nx.logical_and(nx.isinf(x), nx.signbit(x), out)
Copy link
Member Author

Choose a reason for hiding this comment

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

For a little more efficiency, we could change this to:

nx.logical_and(nx.isinf(x, out), nx.signbit(x), out)

But that seemed out of scope for the bugfix/deprecation

@eric-wieser
Copy link
Member Author

eric-wieser commented Apr 26, 2017

Ugh, this was much messier than intended - turns out that #8994 is a much bigger stumbling block to making things work right than expected.

warnings.warn(
"The name of the out argument to {} has changed from `y` to "
"`out`, to match other ufuncs.".format(f.__name__),
DeprecationWarning, stacklevel=3)
Copy link
Member Author

Choose a reason for hiding this comment

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

Previous commit forgot to specify a stacklevel

@eric-wieser eric-wieser requested a review from mhvk April 26, 2017 20:38
@eric-wieser
Copy link
Member Author

(Since there's some subclass trickery going on here, and you've had opinions on np.where before)

Copy link
Contributor

@mhvk mhvk left a comment

Choose a reason for hiding this comment

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

Looks good except for the one comment; I don't think we should introduce a new where here.

Separately, I see now really good use for my plans to get chained ufuncs to work...

return y

def isposinf(x, y=None):
return _where(nx.greater_equal(x, 0), nx.floor(x), nx.ceil(x), out)
Copy link
Contributor

Choose a reason for hiding this comment

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

The version of where you have above is not subclass-safe, at least not for Quantity (where, in general, the two arrays might have different units). For this particular function, it might nevertheless work, but I would suggest not introducing a new function. Instead, perhaps the following (I checked it passes all tests):

    out = nx.asanyarray(nx.floor(x, out=out))
    out = nx.ceil(x, out=out, where=(x < 0))
    return out if out.shape else out[()]

Copy link
Member Author

Choose a reason for hiding this comment

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

This should be out if type(out) != np.ndarray or out.shape else out[()], I think.

Copy link
Contributor

Choose a reason for hiding this comment

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

It should be whatever is closest to what a ufunc does; any subclasses should be able to deal with out[()]... (I guess the alternative would be to separate out the non-array case, but that seems overkill)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, ufuncs only unpack scalars on the base classes, presumably as subclasses might lose metadata

Copy link
Member Author

Choose a reason for hiding this comment

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

Alright, fixed I think - it was a little bit messier than that

Copy link
Member Author

Choose a reason for hiding this comment

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

And one more time, with tests for the cases that your suggestion didn't cover

No need to reinvent the wheel here - the ufunc machinery will handle the out arguments

Fixes numpy#8993
@mhvk
Copy link
Contributor

mhvk commented Apr 26, 2017

Looks all OK now!

@eric-wieser
Copy link
Member Author

Could probably add the where kwarg now if I really felt like it, but that's probably never going to be used anyway

@mhvk
Copy link
Contributor

mhvk commented Apr 27, 2017

I'm happy with this. @charris - do you want to have another look, or is this ready to go in?

@charris
Copy link
Member

charris commented Apr 27, 2017

@mhvk I didn't really review, just glanced over it and thought it was generally good. Put it in if you like it.

@mhvk mhvk merged commit d5657b9 into numpy:master Apr 28, 2017
@mhvk
Copy link
Contributor

mhvk commented Apr 28, 2017

OK, merged! Thanks, @eric-wieser!

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.

BUG: Applying np.fix on scalar returns 0-D array
3 participants