Switching on float/double/long
Remi Forax
forax at univ-mlv.fr
Tue Dec 12 21:52:52 UTC 2017
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" <brian.goetz at oracle.com>
> À: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> 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
More information about the amber-spec-observers
mailing list