While we could do that, use bits representation for float and double, this is typically the kind of things that a user can also do with a record (a value type record ?) and a deconstructor, so in my opinion, we should not rush to implement this kind of switch given that we will soon provide a general mechanism to implement them outside of the JDK.
Rémi > De: "Brian Goetz" <[email protected]> > À: "amber-spec-experts" <[email protected]> > Envoyé: Lundi 11 Décembre 2017 22:25:34 > Objet: Switching on float/double/long > A target of opportunity for the new switch JEP is to fill out the set of types > that traditional switches can operate on -- specifically float, double, and > long. The reason that we don't support these now is mostly an accident of > history; the `tableswitch` and `lookupswitch` opcodes are int-based, so the > compiler doesn't have a convenient target for translating these. As you've > seen > from the recent notes on switch translation, we're working towards using indy > more broadly as a translation target for most switch constructs. This makes it > far easier to bust the limitations on switch argument types, and so this has > been listed as a target of opportunity in the JEP (for both statement and > expression switches.) > Our resident floating-point expert, Joe Darcy, offers the following additional > thoughts on the subject: > -- Begin forwarded message > Per a recent request from Brian, I've written a few thoughts about switching > on > floating-point values. > To address some common misunderstandings of floating-point, while it is often > recommended to * not * compare floating-point values for equality, it is > perfectly well-defined to do such comparisons, it just might not do what you > want > For example, instead of > // Infinite loop since sum stored in d never exactly equals 1.0, doh! > while(d != 1.0)\u000B > d += 0.1; > use either > // Counted loop > for(int i = 0; i < 10; i++)\u000B > d += 0.1; > or > // Stop when numerical threshold is met > while(d <= 1.0)\u000B > d += 0.1; > depending on the semantics the loop is trying to capture. > I've attached a slide from my JVMLS talk this year to help illustrate the > semantic modeling going in in IEEE 754 floating-point. Each of the 2 ^ 32 > possible bit patterns of a float is some floating-point value, likewise for > the > 2 ^ 64 possible bit patterns of a double. However, from a Java language or JVM > perspective, there are not 2 ^ 32 or 2 ^ 64 distinct values we need or want to > distinguish in most cases. In particular, we almost always want to treat all > bit patterns which encode a NaN as a single conceptual NaN. Another wrinkle > concerns zero: IEEE 754 has both a positive zero and a negative zero. Why are > there * two * zeros? Because there are two infinities. The signed infinities > and distinguished by divide (1.0/0.0 => +infinity, 1.0/-0.0 => -infinity) and > by various library functions. > So we want to: > * Allow every distinct finite nonzero floating-point value to be the case of a > switch. > * Allow -0.0 and +0.0 to be treated separately. > * Allow -infinity and +infinity to be treated separately. > * Collapse all NaN representation as a single value. > For the "Rounding" mapping in the diagram which goes from the extended real > numbers to floating-point data, there is a nonempty segment of the real number > line which maps to a given representable floating-point number. For example, > besides the string "1.0" mapping exactly to the reprentable floating-point > value 1.0, there is a region slightly small than 1 (0.99999999999999999999...) > which will round up to 1.0 and a region slightly larger than 1 > (1.000000000000000001...) which will round down to 1 from decimal -> binary > conversion. This would need to be factored into any distinctiveness > requirements for the different arms of the switch. In other words > case 1.000000000000000001: > .... > case 0.99999999999999999999 > ... > would need to be rejected just as > case 0: > .... > case 00: > is rejected. > In terms of JDK 9 structures and operations, the following transformation of a > float switch has what I think are reasonable semantics: > Replace each float case label y in the source with an int label resulting from > floatToIntBits(y). Note that floatToIntBits is used for the mapping rather > than > floatToRawIntBits since we want NaNs to be grouped together. > Instead of switching on float value x, switch on floatToIntBits(x). > HTH, > -Joe
