-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
BUG: Inconsistent type resolution for 0d arrays #10322
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
Comments
Yeah, this stuff is pretty annoying... But I think we need to do a major release (hehe, we can do those anyway ;)) to change it another time. I suppose we could try to aim for 0d arrays be interpreted as arrays here in principle. In practice you need to also fix the ufunc machinery to actually also signal the scalar when it was one, I am sure. Also as long as 0d arrays are second class citizens compared to scalars, I do not really see this improving much personally. My personal opinion is still that we should aim for (in the very long run) 0d arrays and scalars (not mutable normally) and things like |
Duplicate of #9194. It is probably worth noting that one can avoid the problem by also passing a It also worth noting that the solution is not that obvious. E.g., the following would, generally be the expected result:
At least, I think we'd get even more bug reports if the following was the default!
|
Right, but I'd argue that's because it uses the np.equal(np.arange(0., 0.3, 0.1, dtype=np.float32), np.float64(0.1))
# array([False, False, False], dtype=bool) |
Hehe, true, but equality with floats is a tricky beast in any case and nobody is suggesting to change it for the python scalar case I believe, possibly for Which both are of course a bit annoying since it breaks the "casting everything first with |
@mhvk: I've leave it to you to decide whether to close this or the old one |
Closed #9194, so we can discuss in one place. It does seem to me array scalars should always be treated like arrays. My ideal future would have gotten rid of numpy scalars altogether - use array scalars mostly and python numbers when needed - but perhaps I am missing what they can be useful for. |
Fixes numpy#8123, closes numpy#9189, fixes numpy#10319 This is a workaround to numpy#10322, not a fix for it. Adds tests for cases where bounds are more precise than the data, which led to inconsistencies in the optimized path.
Fixes numpy#8123, closes numpy#9189, fixes numpy#10319 This is a workaround to numpy#10322, not a fix for it. Adds tests for cases where bounds are more precise than the data, which led to inconsistencies in the optimized path.
So my current though was that all examples here would be "fixed", but the Python operators might stay unmodified:
would actually return |
We had discussed this a bit (two weeks ago). I think we had some consensus, that we should probably just do it (but it will probably need testing). By now, I am almost convinced that simply changing our "casting/promotion" rules to fix this everywhere (also in normal ufunc calls), might be the best thing. When scalars are involved, that would usually lead to higher precision (less scary), when Python scalars are involved, errors/warning on conversions should notify users of any changes (so this is also unlikely). The worst thing is probably:
Which previously would give float64, but with a change would give float32... I tried this a bit actually. SciPy doesn't really notice (in two tests or so it might, aside from the Compared to that, warning on future precision change is pretty darn noisy (largely due to this issue). |
For anyone else coming to this issue trying to understand what is happening, the example in the OP is a bit confusing, because it demonstrates the issue indirectly via a function that returns a bool. It's easier to see via a function that directly returns the promoted value, like >>> add(array([1.0], dtype=float32), array([1.0], dtype=float64)).dtype
dtype('float64')
>>> add(array(1.0, dtype=float32), array(1.0, dtype=float64)).dtype
dtype('float64')
>>> add(array(1.0, dtype=float32), array([1.0], dtype=float64)).dtype
dtype('float64')
>>> add(array([1.0], dtype=float32), array(1.0, dtype=float64)).dtype
dtype('float32') Also, if the resulting value does not fit in float32, the result is upcast (value-based casting) >>> add(array([1.0], dtype=float32), array(3.4e+38, dtype=float64)).dtype
dtype('float64') Finally, the issue only concerns 0-d arrays, not scalar objects >>> add(float32(1.0), float64(1.0)).dtype
dtype('float64')
>>> add(float32(1.0), array([1.0], dtype=float64)).dtype
dtype('float64')
>>> add(array([1.0]), float64(1.0)).dtype
dtype('float64')
>>> add(array([1.0], dtype=float32), float64(3.4e+38)).dtype
dtype('float64') |
Just to make it easier to find again, NEP 50 is the current attempt to fix these inconsistencies. (And is fairly far along, although it is still possible to modify details.) |
Closing, weak promotion/NEP 50 should make these consistent. |
Uh oh!
There was an error while loading. Please reload this page.
Using direct ufunc calls below to eliminate operator overloading from the test case:
Caused by
result_type
having some unusual rules:This seems wrong to me, but appears to be deliberate.
It seems the goal here is to interpret python scalars as loosely-typed (in the presence of arrays). This handles thing like:
float64
andint_
if they'd fitHowever, the method is too greedy, and also (in the presence of arrays) discards type information from:
np.number
instances with an explicit type, likenp.int64(1)
andnp.float32(1)
ndarray
instances, by decaying them to their scalarsThe problem is that
PyArray_ResultType
(and the ufunc type resolver) has lost the information about where it's array arguments came from, and whether their types are explicit or implicit.The text was updated successfully, but these errors were encountered: