<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <tt>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.)  <br>
      <br>
      Our resident floating-point expert, Joe Darcy, offers the
      following additional thoughts on the subject:<br>
      <br>
    </tt><tt>-- Begin forwarded message</tt><br>
    <br>
    <tt>
    </tt>
    <div class="moz-text-flowed" style="font-family: -moz-fixed;
      font-size: 14px;" lang="x-unicode">Per a recent request from
      Brian, I've written a few thoughts about switching on
      floating-point values.
      <br>
      <br>
      To address some common misunderstandings of floating-point, while
      it is often recommended to <b class="moz-txt-star"><span
          class="moz-txt-tag">*</span>not<span class="moz-txt-tag">*</span></b>
      compare floating-point values for equality, it is perfectly
      well-defined to do such comparisons, it just might not do what you
      want <span class="moz-smiley-s3" title=";-)"></span>
      <br>
      <br>
      For example, instead of
      <br>
      <br>
          // Infinite loop since sum stored in d never exactly equals
      1.0, doh!
      <br>
          while(d != 1.0)
      <br>
              d += 0.1;
      <br>
      <br>
      use either
      <br>
      <br>
          // Counted loop
      <br>
          for(int i = 0; i < 10; i++)
      <br>
              d += 0.1;
      <br>
      <br>
      or
      <br>
      <br>
          // Stop when numerical threshold is met
      <br>
          while(d <= 1.0)
      <br>
              d += 0.1;
      <br>
      <br>
      depending on the semantics the loop is trying to capture.
      <br>
      <br>
      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<sup class="moz-txt-sup"><span
          style="display:inline-block;width:0;height:0;overflow:hidden">^</span>32</sup>
      possible bit patterns of a float is some floating-point value,
      likewise for the 2<sup class="moz-txt-sup"><span
          style="display:inline-block;width:0;height:0;overflow:hidden">^</span>64</sup>
      possible bit patterns of a double. However, from a Java language
      or JVM perspective, there are not 2<sup class="moz-txt-sup"><span
          style="display:inline-block;width:0;height:0;overflow:hidden">^</span>32</sup>
      or 2<sup class="moz-txt-sup"><span
          style="display:inline-block;width:0;height:0;overflow:hidden">^</span>64</sup>
      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 <b class="moz-txt-star"><span class="moz-txt-tag">*</span>two<span
          class="moz-txt-tag">*</span></b> 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.
      <br>
      <br>
      So we want to:
      <br>
      <br>
          * Allow every distinct finite nonzero floating-point value to
      be  the case of a switch.
      <br>
          * Allow -0.0 and +0.0 to be treated separately.
      <br>
          * Allow -infinity and +infinity to be treated separately.
      <br>
          * Collapse all NaN representation as a single value.
      <br>
      <br>
      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
      <br>
      <br>
          case 1.000000000000000001:
      <br>
          ....
      <br>
          case 0.99999999999999999999
      <br>
          ...
      <br>
      <br>
      would need to be rejected just as
      <br>
      <br>
          case 0:
      <br>
          ....
      <br>
          case 00:
      <br>
      <br>
      is rejected.
      <br>
      <br>
      In terms of JDK 9 structures and operations, the following
      transformation of a float switch has what I think are reasonable
      semantics:
      <br>
      <br>
          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.
      <br>
      <br>
          Instead of switching on float value x, switch on
      floatToIntBits(x).
      <br>
      <br>
      HTH,
      <br>
      <br>
      -Joe
      <br>
      <br>
      <br>
      <br>
    </div>
  </body>
</html>