-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
ENH: add np.positive ufunc #8967
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
For now, it might be better to skip trying to fix up |
numpy/core/src/umath/loops.c.src
Outdated
@@ -874,6 +874,14 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void | |||
|
|||
#if @CHK@ | |||
NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void | |||
@TYPE@_positive@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) | |||
{ | |||
UNARY_LOOP_FAST(@type@, @type@, *out = in); |
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.
Can we do *out = +in
here (and below), for clarity?
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.
Done.
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.
Then you haven't pushed!
numpy/core/src/umath/loops.c.src
Outdated
UNARY_LOOP { | ||
const npy_half in1 = *(npy_half *)ip1; | ||
*((npy_half *)op1) = in1; | ||
} |
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.
I realize that you're just copying negative
here - but what's the heuristic for when to use UNARY_LOOP_FAST
and when to just use UNARY_LOOP
? @juliantaylor, I suspect you can shed some light 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.
you use UNARY_LOOP_FAST
in cases where compiler vectorization is profitable.
It involves several copies of the loop so it is just bloat in cases where no vectorization can be done like in the negative half case.
You could use a fast loop for positive here (though it is hardly worth the extra generated code)
In general you could use a memcpy special case instead of the fast loop here too, like the logical_not in gh-8924. Some compilers might not be able to do that for you.
numpy/core/src/multiarray/number.c
Outdated
@@ -1128,7 +1139,7 @@ NPY_NO_EXPORT PyNumberMethods array_as_number = { | |||
(binaryfunc)array_divmod, /*nb_divmod*/ | |||
(ternaryfunc)array_power, /*nb_power*/ | |||
(unaryfunc)array_negative, /*nb_neg*/ | |||
(unaryfunc)_array_copy_nice, /*nb_pos*/ |
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.
this function can be removed now
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.
With some regret, I decided to undo this change, because of the potential for a backwards compatibility break (we're pretty paranoid about those).
Any further concerns here? Note that I rolled back the changes to |
Ah, but needs a release note |
Proposal - can all the |
@shoyer Needs a rebase and release note. |
☔ The latest upstream changes (presumably #8885) made this pull request unmergeable. Please resolve the merge conflicts. |
This is a good idea, but it turned out to be easier said that done:
So I just stuck with separate definitions.
Done and done. |
Thanks @shoyer! |
I'm puzzled, this one function does not seem to work well with
I think it is due to
(will try to investigate later, but have to run now; if someone else understands what is happening, do go ahead and fix...) |
@shoyer deliberately did not connect up |
OK, rereading the comments I see that is the case. I guess I'll have to keep |
@mhvk if you think it would be OK from a compatibility perspective, we could switch |
Probably being careful is good, but should we at least add the deprecation warning? Also, maybe just pass on to |
@mhvk Those both sound like fine ideas to me. |
@shoyer - would you be able to do it? Or have an idea what I should do beyond what I tried (#8967 (comment)) |
@mhvk I'm not sure I'll have time to get to this before the branch for 1.13. Probably, the desired behavior is something like:
(This may be a little tricky, though, because it will need to be done in C.) For your ndarray subclass, you could overwrite |
The override is indeed what I do for |
I created #9081 so we don't forget about this. |
xref #8932
The strategy here was to search for every use of "negative" in NumPy's C code, so I quite possibly missed something. But it builds, and seems to work.
Still needs full test coverage. The existing test coverage for ufuncs like absolute and negative is rather sparse, but that's no excuse for new code.
Questions to resolve:
+np.array('foo')
? How do we even detect these cases? I guess we can check for dtypes that are no longer valid (e.g., strings), but there's no way to know if unary+
is a valid on an dtype=object array without trying it on each of the scalars.+
on a boolean array be valid? I guess the answer is no, given that-x
raises for boolean arrays and based on the principle that+x
should only be valid when-x
is. This strengths the case for a deprecation cycle for the behavior ofndarray.__pos__
, given that we went through such a deprecation cycle for negative on booleans (DEP: Handle expired deprecations. #8297).