-
Notifications
You must be signed in to change notification settings - Fork 53
Type promotion rules #14
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
Thanks @kgryte, this looks pretty good to me. One addition to the prior art may be CuPy. Its type promotion docs bring up a relevant question: do 0-D arrays participate, or are they treated as scalars that cannot cause upcasting? That scalars don't participate should be added explicitly I think. |
Thanks for mentioning CuPy. Added. Re: zero-dimensional arrays. Seems to be some disagreement in this regard, as some array libraries have explicitly avoided copying NumPy's exact type promotion behavior, where the magnitude of the scalar is considered when determining the result data type (e.g., CuPy, PyTorch). IMO, NumPy's behavior is a bit harder to reason about, especially when the scalar value is not known beforehand or is dynamically set and a change in scalar magnitude can result in a different result type. My current stance is that zero-dimensional arrays are treated just like dimensional arrays when promoting types. For example, if a zero-dimensional array has dtype For scalar arguments specifically (e.g., I think this is the most consistent, and least magical, path forward. |
Hmm, I suspect that will be really bad for usability. It's not just in functions, but also in expressions like There's two separate things: NumPy's value-based promotion (which no one wants), and whether scalars participate in type promotion at all (which is a good discussion to have). |
@rgommers Agreed. Maybe three questions then need to be answered:
|
Yes makes sense. I'd say "No, No, Dunno". |
This is definitely the hardest part of this design decision: (a) Treating 0d arrays like scalars is convenient because it allows for converting Python scalars into 0d arrays without any impact on promotion rules. You can write the equivalent of My personal opinion is that (b) is a fatal flaw with special casing 0d arrays, and there are good alternatives to immediately calling (Perhaps not coincidentally, JAX answers these questions "No, No, No") |
Generally, I think we should with v1 of the spec be as non-magical as possible recognizing that library authors are our target and that more usable interfaces should and will be written so that end-users won't have some of the difficulties of expression that Ralf suggests. So I would agree with 1) No and 2) No. For 3) it seems at first glance like 0d arrays should just be treated as arrays and participate in promotion rules, but the numeric Python community as a long history of 0d arrays and scalars being (mostly) interchangeable and it will be quite hard to not have scalar participation in the type promotion and have 0d array participation. So, I lean to "No" on 3) as well. Yes, this breaks symmetry on promotion participation at a place that is usually easy to understand (when arr.ndim == 0), rather than the not often specified places where 0d arrays and scalars are treated as equivalent by a given library. |
I think the wording of (3) is a little confusing because the answer is (possibly?) conditional on the response to (2). E.g., Travis and I both suggested "no" but judging by his language ("will be quite hard to not have scalar participation in the type promotion and have 0d array participation") I think we meant opposite things :) So let's try this again:
My suggestion to these revised questions was "No, no, yes" (all arrays participate in type promotion, matching JAX), but if I interpret Travis's comment correctly he is leaning towards "No, no, no" (only arrays with at least one dimension participate in type promotion)? (To be clear, by "scalars" I mean Python builtin types |
Thanks for rephrasing. I think I agree with your "yes" here. The concern of @teoliphant that I also had I think can be handled with being careful about where one can use scalars. For regular functions, it should be fine to say |
Thanks for clarifying. Yes, I misread the third question. I'm +1 with treating 0-d arrays as arrays and not allowing scalar promotion in function calls themselves -- i.e. keeping the scalar handling rules in the "dunder" methods on any array class. |
Great! Based on feedback, seems there is agreement on (1) not allowing "scalars" to participate in type promotion (e.g., a Python |
This was agreed upon, and the Type Promotion section currently summarizes the 0-D array / scalar issue as:
That seems in agreement with the discussion here and complete, so closing this issue. |
Identified as needed in data-apisgh-14, also came up in data-apisgh-43 and data-apisgh-91.
This issue seeks to come to a consensus on a subset of type promotion rules (i.e., the rules governing the common result type for two array operands during an arithmetic operation) suitable for specification.
As initially discussed in #13, a universal set of type promotion rules can be difficult to standardize due to the needs/constraints of particular runtime environments. However, we should be able to specify a minimal set of type promotion rules which all specification conforming array libraries can, and should, support.
Prior Art
promote_types
andresult_type
APIs and source [1, 2].Proposal
This issue proposes to specify that all specification conforming array libraries must, at minimum, support the following type promotions:
floating-point type promotion table:
where
unsigned integer type promotion table:
where
signed integer type promotion table:
where
mixed unsigned and signed integer type promotion table:
Notes
(i8, f2)
tof2
, while NumPy promotes(i8, f2)
tof8
). The reason for the discrepancy stems from the particular needs/constraints of accelerator devices, and, thus, by omitting specification here, we allow for implementation flexibility and avoid imposing undue burden.i8
andu8
. NumPy and JAX both promote(i8, u8)
tof8
which is explicitly undefined via the aforementioned note regarding conversions between kinds and also raises questions regarding inexact rounding when converting from a 64-bit integer to double-precision floating-point.The text was updated successfully, but these errors were encountered: