-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
MAINT: Removed duplicated code around ufunc->identity
#8952
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
numpy/core/src/umath/reduction.h
Outdated
@@ -147,7 +147,7 @@ PyUFunc_ReduceWrapper(PyArrayObject *operand, PyArrayObject *out, | |||
npy_bool *axis_flags, int reorderable, | |||
int keepdims, | |||
int subok, | |||
PyArray_AssignReduceIdentityFunc *assign_identity, | |||
PyObject *assign_identity, |
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 stopped being public API in 3626d0c, despite the name suggesting it is - so this change is fine
switch(ufunc->identity) { | ||
case PyUFunc_One: | ||
*reorderable = 1; | ||
return PyInt_FromLong(1); |
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 used to be True
when used internally, and 1
when viewed externally.
The upshot is that this fixes #8860.
Ideally, we'd use True
for functions like logical_or
, and 1
for functions like add
|
||
case PyUFunc_MinusOne: | ||
*reorderable = 1; | ||
return PyInt_FromLong(-1); |
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.
Previously, we cached these values in a static variable. Is this something we should keep doing?
numpy/core/src/umath/ufunc_object.c
Outdated
|
||
default: | ||
PyErr_Format(PyExc_ValueError, "ufunc has an invalid identity"); | ||
return NULL; |
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.
Could include the ufunc name in the error message, but really we should merge
#8876 before that to pick the right name.
} | ||
PyArray_FillWithScalar(op[i], identity); |
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.
assign_identity
was never anything but this operation
"ufunc %s has an invalid identity for reduction", | ||
ufunc_name); | ||
return NULL; | ||
if (_get_bufsize_errmask(NULL, "reduce", &buffersize, &errormask) < 0) { |
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.
Moving this check to occur first makes cleanup a little easier.
Py_DECREF(identity); | ||
identity = Py_None; | ||
Py_INCREF(identity); | ||
} |
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 don't think this behaviour is justified, but this is a maintenance commit, so for now, we should leave it in
7dded6e
to
802e447
Compare
It would seem a function to assign the identity is not in itself a crazy idea, as it allows one to calculate it based on |
I think you're confusing "assign" and "calculate" here. A function to calculate the identity from the |
Yes, I meant it in the calculate sense, and wondered whether that was ever intended since the function was passed |
You're correct, I overlooked this. AFAICT, these pointers are for implementing loop-specific behaviour, so would match the "different identity for different dtype" cases. If we do want this in future, I think it should be performed at a higher level - as a The only situation I can construct where loop-specific identities would be useful is if For all the numeric types, casting is sufficient to produce the different values |
I think you're right it would mostly be useful to make things dtype-dependent (including perhaps structured arrays). In any case, it seems the code as is doesn't really allow that, and the current PR does not preclude adding that later. |
@mhvk: Any more comments? Does this look ready to merge to you? |
I'm still on an observing run, and while this all looks OK, I haven't really thought more about it, so it may be good to have someone else have a look. |
☔ The latest upstream changes (presumably #8876) made this pull request unmergeable. Please resolve the merge conflicts. |
5192858
to
81b5d9e
Compare
Any chance someone could take a look at this? |
Needs rebase. |
Relatedly, what happened to @homu? |
81b5d9e
to
fb2f67c
Compare
Man, kdiff3 was awful for rebasing that. Sorted now. |
e2fed71
to
551a12d
Compare
There didn't seem to be any value to a `assign_identity` function - all we actually care about is the value to assign. This also fixes numpy#8860 as a side-effect, and paves the way for: * easily adding more values (numpy#7702) * using the identity in more places (numpy#834)
551a12d
to
31fd25d
Compare
@charris: Does this one look ready? |
@charris: Ping |
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 does all look OK, so unless @charris or @jaimefrio objects in the next day or so, I'll merge.
Just to be sure, am I correct to assume that given NPY_NOEXPORT
, we do not have to worry about anyone using this directly?
You can see it was removed from the API in this commit |
@mhvk: looks like there are no objections |
OK, merged! |
There didn't seem to be any value to a
assign_identity
function - all weactually care about is the value to assign.
This paves the way for:
This also fixes #8860 as a side-effect, but introduces a different problem elsewhere:
np.add.reduce(np.array([], object))
- previouslyFalse
, now0
(good)np.logical_or.reduce(np.array([], object))
- previouslyFalse
, now0
(not so good)The latter of these is fixed by #8955 which can be merged after this PR.
This seems to be better behaviour, since at least
0
is whatnp.logical_or.identity
returns. In a future commit, I think we should distinguish betweenTrue
and1
in the identity, but I don't want to change too much at once, so I'm leaving that for another PR