static short toFloat16(float f) {
    int bits = Float.floatToRawIntBits(f);
    int s = (bits >>> FP32_SIGN_SHIFT);
    int e = (bits >>> FP32_EXPONENT_SHIFT) & FP32_SHIFTED_EXPONENT_MASK;
    int m = (bits) & FP32_SIGNIFICAND_MASK;
    int outE = 0;
    int outM = 0;
    if (e == 0xff) { // Infinite or NaN
      outE = 0x1f;
      outM = m != 0 ? 0x200 : 0;
    } else {
      e = e - FP32_EXPONENT_BIAS + EXPONENT_BIAS;
      if (e >= 0x1f) { // Overflow
        outE = 0x1f;
      } else if (e <= 0) { // Underflow
        if (e < -10) {
          // The absolute fp32 value is less than MIN_VALUE, flush to +/-0
        } else {
          // The fp32 value is a normalized float less than MIN_NORMAL,
          // we convert to a denorm fp16
          m = m | 0x800000;
          int shift = 14 - e;
          outM = m >> shift;
          int lowm = m & ((1 << shift) - 1);
          int hway = 1 << (shift - 1);
          // if above halfway or exactly halfway and outM is odd
          if (lowm + (outM & 1) > hway) {
            // Round to nearest even
            // Can overflow into exponent bit, which surprisingly is OK.
            // This increment relies on the +outM in the return statement below
            outM++;
          }
        }
      } else {
        outE = e;
        outM = m >> 13;
        // if above halfway or exactly halfway and outM is odd
        if ((m & 0x1fff) + (outM & 0x1) > 0x1000) {
          // Round to nearest even
          // Can overflow into exponent bit, which surprisingly is OK.
          // This increment relies on the +outM in the return statement below
          outM++;
        }
      }
    }
    // The outM is added here as the +1 increments for outM above can
    // cause an overflow in the exponent bit which is OK.
    return (short) ((s << SIGN_SHIFT) | (outE << EXPONENT_SHIFT) + outM);
  }
@Test
  public void testFloatToFloat16() {
    // Zeroes, NaN and infinities
    assertEquals(POSITIVE_ZERO, Float16.toFloat16(0.0f));
    assertEquals(NEGATIVE_ZERO, Float16.toFloat16(-0.0f));
    assertEquals(NaN, Float16.toFloat16(Float.NaN));
    assertEquals(POSITIVE_INFINITY, Float16.toFloat16(Float.POSITIVE_INFINITY));
    assertEquals(NEGATIVE_INFINITY, Float16.toFloat16(Float.NEGATIVE_INFINITY));
    // Known values
    assertEquals((short) 0x3c01, Float16.toFloat16(1.0009765625f));
    assertEquals((short) 0xc000, Float16.toFloat16(-2.0f));
    assertEquals((short) 0x0400, Float16.toFloat16(6.10352e-5f));
    assertEquals((short) 0x7bff, Float16.toFloat16(65504.0f));
    assertEquals((short) 0x3555, Float16.toFloat16(1.0f / 3.0f));
    // Subnormals
    assertEquals((short) 0x03ff, Float16.toFloat16(6.09756e-5f));
    assertEquals(MIN_VALUE, Float16.toFloat16(5.96046e-8f));
    assertEquals((short) 0x83ff, Float16.toFloat16(-6.09756e-5f));
    assertEquals((short) 0x8001, Float16.toFloat16(-5.96046e-8f));
    // Subnormals (flushed to +/-0)
    assertEquals(POSITIVE_ZERO, Float16.toFloat16(5.96046e-9f));
    assertEquals(NEGATIVE_ZERO, Float16.toFloat16(-5.96046e-9f));
    // Test for values that overflow the mantissa bits into exp bits
    assertEquals((short) 0x1000, Float16.toFloat16(Float.intBitsToFloat(0x39fff000)));
    assertEquals((short) 0x0400, Float16.toFloat16(Float.intBitsToFloat(0x387fe000)));
    // Floats with absolute value above +/-65519 are rounded to +/-inf
    // when using round-to-even
    assertEquals((short) 0x7bff, Float16.toFloat16(65519.0f));
    assertEquals((short) 0x7bff, Float16.toFloat16(65519.9f));
    assertEquals(POSITIVE_INFINITY, Float16.toFloat16(65520.0f));
    assertEquals(NEGATIVE_INFINITY, Float16.toFloat16(-65520.0f));
    // Check if numbers are rounded to nearest even when they
    // cannot be accurately represented by Half
    assertEquals((short) 0x6800, Float16.toFloat16(2049.0f));
    assertEquals((short) 0x6c00, Float16.toFloat16(4098.0f));
    assertEquals((short) 0x7000, Float16.toFloat16(8196.0f));
    assertEquals((short) 0x7400, Float16.toFloat16(16392.0f));
    assertEquals((short) 0x7800, Float16.toFloat16(32784.0f));
    // Miscellaneous values. In general, they're chosen to test the sign/exponent and
    // exponent/mantissa boundaries
    assertEquals((short) 0x101c, Float16.toFloat16(+0.00050163269043f));
    assertEquals((short) 0x901c, Float16.toFloat16(-0.00050163269043f));
    assertEquals((short) 0x101d, Float16.toFloat16(+0.000502109527588f));
    assertEquals((short) 0x901d, Float16.toFloat16(-0.000502109527588f));
    assertEquals((short) 0x121c, Float16.toFloat16(+0.00074577331543f));
    assertEquals((short) 0x921c, Float16.toFloat16(-0.00074577331543f));
    assertEquals((short) 0x141c, Float16.toFloat16(+0.00100326538086f));
    assertEquals((short) 0x941c, Float16.toFloat16(-0.00100326538086f));
    assertEquals((short) 0x501c, Float16.toFloat16(+32.875f));
    assertEquals((short) 0xd01c, Float16.toFloat16(-32.875f));
    // A few subnormals for good measure
    assertEquals((short) 0x001c, Float16.toFloat16(+1.66893005371e-06f));
    assertEquals((short) 0x801c, Float16.toFloat16(-1.66893005371e-06f));
    assertEquals((short) 0x021c, Float16.toFloat16(+3.21865081787e-05f));
    assertEquals((short) 0x821c, Float16.toFloat16(-3.21865081787e-05f));
  }