Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea652eac authored by xueliang.zhong's avatar xueliang.zhong Committed by Xueliang Zhong
Browse files

Quiet SNaN inputs in Half.toFloat()

This CL fixes Half.toFloat() in handling SNaN inputs,
to make sure the Java implementation has same semantics
as the hardware implementations (Arm and Intel).

1. Armv8.2 implementation (FCVT):
  // tested as ART intrinsic on Pixel3
  __ Fmov(h31, w1);  // input: w1 register
  __ Fcvt(s0, h31);  // output: s0 register

2. X86 implementation (VCVTPH2PS):
  // clang -mf16c test.c
  float x86_toFloat(short h) {
    __v8hi v = {h, 0, 0, 0, 0, 0, 0, 0};
    __v4sf r = __builtin_ia32_vcvtph2ps(v);
    return r[0];
  }

3. Java implementation (software):
  android.util.Half.toFloat(short);

Test: Exhaustive testing of 0x0..0xFFFF input bits on above three
      implementations and compare output values.

Change-Id: Iff137858379bf43e59cde94c9d19c2054a3d4f93
parent 17f9b9bf
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -162,6 +162,7 @@ public final class Half extends Number implements Comparable<Half> {
    private static final int FP32_EXPONENT_MASK     = 0xff;
    private static final int FP32_SIGNIFICAND_MASK  = 0x7fffff;
    private static final int FP32_EXPONENT_BIAS     = 127;
    private static final int FP32_QNAN_MASK         = 0x400000;

    private static final int FP32_DENORMAL_MAGIC = 126 << 23;
    private static final float FP32_DENORMAL_FLOAT = Float.intBitsToFloat(FP32_DENORMAL_MAGIC);
@@ -903,6 +904,9 @@ public final class Half extends Number implements Comparable<Half> {
            outM = m << 13;
            if (e == 0x1f) { // Infinite or NaN
                outE = 0xff;
                if (outM != 0) { // SNaNs are quieted
                    outM |= FP32_QNAN_MASK;
                }
            } else {
                outE = e - FP16_EXPONENT_BIAS + FP32_EXPONENT_BIAS;
            }