89
Switching on float/double/long
source link: http://mail.openjdk.java.net/pipermail/amber-spec-observers/2017-December/000239.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Switching on float/double/long
Switching on float/double/long
Brian Goetz
brian.goetz at oracle.com
Mon Dec 11 21:25:34 UTC 2017
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) d += 0.1; use either // Counted loop for(int i = 0; i < 10; i++) d += 0.1; or // Stop when numerical threshold is met while(d <= 1.0) 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
More information about the amber-spec-observers
mailing list
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK