-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
BUG: take
casting logic with an out=
argument
#4246
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
*/ | ||
if (PyArray_CanCastTypeTo(dtype, out_dt, NPY_SAFE_CASTING)) { | ||
flags |= NPY_ARRAY_FORCECAST; | ||
} else { |
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.
PEP7
}
else {
The logic of this function is strange, the |
When it receives an `out` argument, `np.take` converts the `out` array to the dtype of the array being taken from. This results in wrong TypeErrors being raised when `out` has a larger dtype than the array (and not being raised when it has a smaller dtype, even though they should). This PR sets NPY_ARRAY_FORCECAST and makes an explicit casting check, raising an error if it fails. The tests added check the logic for conversion between all pairs of ints and floats only.
I have simplified things as much as possible following your suggestions. The comment in the code is still kind of long and unclear. Perhaps it is better to remove it completely and let the code speak for itself? |
* is needed, as the constructor of obj would check the opposite | ||
* casting, were it not disabled by the NPY_ARRAY_FORCECAST flag. | ||
*/ | ||
if (PyArray_CanCastTypeTo(dtype, PyArray_DESCR(out), |
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'm thinking this check is incorrect. It was previously allowed to cast, say, float64
to int8
, and ufuncs also allow such casting. The forcecast going the other way should be the only change needed as it provides a type compatible work array, which is then copied back on success or discarded on failure. The test could check that out
remains unchanged when the mode is raise
and an indexing error occurs.
This looks much cleaner, but I don't think it is quite correct yet. |
I just did a little bit of archeology, and we had this same conversation a little over a year ago: http://mail.scipy.org/pipermail/numpy-discussion/2013-February/065441.html It is indeed true that ufuncs will allow any type of casting to |
When simply forcing the cast it raises a different error:
Apparently it is expected that Since |
Only half true I believe, isn't that behaviour in ufuncs is deprecated I believe. |
@seberg Hmm, need to check that. I'm concerned about changing functions in the API even if it looks like this function isn't much used ;) Currently, the function only works if the output precision is <= input precision, with this PR it is >= instead. |
Wasn't arguing about just using forced casting here. I think it should be good. Could or could not add deprecations on top of that then, just like the ufuncs have right now. Or similar to them anyway. |
The forced cast without type checking raises that error in I haven't been able to find "Ticket #789, changeset 5217" to see if there is a deeper reason for that test, any clue? |
Well, that test tests a segfault bug (see gh-1387), so there is no need to see it as someone wanted to fix behaviour there. We are not awfully consistent about what we allow with the out argument anyway. Some allow forced casting, some want exact matching, and for ufuncs there is a plan to make it safe... |
Looking at scipy, the |
Actually, |
There is |
Maybe time to take another look at this. |
☔ The latest upstream changes (presumably #6047) made this pull request unmergeable. Please resolve the merge conflicts. |
@jaimefrio this seems to still requires some work. Unless you comment/wish to continue, I would probably:
in a few weeks. Of course the PR can be reactivated at any time. (tag:PR-possibly-close) In general this seems like a fairly straight forward task, although likely requiring some form of Deprecation. |
This has been stale from the point when @seberg last responded. Closing for now. Feel free to reopen @jaimefrio if you still wish to pursue this task. |
I think we should create an issue to continue tracking this behavior |
sure @eric-wieser, will do. |
When it receives an
out
argument,np.take
converts theout
array tothe dtype of the array being taken from. This results in wrong
TypeError
sbeing raised when
out
has a larger dtype than the array (and not beingraised when it has a smaller dtype, even though they should):
This PR makes an explicit casting check, then either sets
NPY_ARRAY_FORCECAST
or explicitly raises the error.
The tests added check the logic for conversion between all pairs of ints and
floats only.