RFR: 8318158: RISC-V: implement roundD/roundF intrinsics [v6]

Olga Mikhaltsova omikhaltcova at openjdk.org
Tue Dec 12 23:42:50 UTC 2023


On Tue, 12 Dec 2023 03:24:40 GMT, Fei Yang <fyang at openjdk.org> wrote:

>> Subnormal numbers can be distinguished after fclass call, they were also added here in order not to do redundant operations further, they results to 0 as well.
>> 
>> Yes, that's right, I verified output of this algorithm against the current java implementation on the full 32-bit range.
>> 
>> Thanks for the advice below!
>
>> Yes, that's right, I verified output of this algorithm against the current java implementation on the full 32-bit range.
> 
> Hi, can you share with us your test? I am also trying to understand how this works. Thanks.

@RealFYang Here it is my draft. I made very simple check. The java Math.round() was copy-pasted into the test for getting an etalon value to compare. In addition as a paranoid check, I made a special build with a stub on Math.round() returning a fake value = 777, in order to be absolutely sure that the intrincified method is executing and all values in the range are checked. Also I added the option "-Xcomp" while running the test.


public class MathTest_RangeRun {

  public static final int PRECISION = 24;
  public static final int SIZE = 32;
  public static final int SIGNIFICAND_WIDTH = PRECISION;
  public static final int EXP_BIT_MASK = ((1 << (SIZE - SIGNIFICAND_WIDTH)) - 1) << (SIGNIFICAND_WIDTH - 1);
  public static final int EXP_BIAS = (1 << (SIZE - SIGNIFICAND_WIDTH - 1)) - 1; // 127
  public static final int SIGNIF_BIT_MASK = (1 << (SIGNIFICAND_WIDTH - 1)) - 1;

  public static int java_round(float a) {
    int intBits = Float.floatToRawIntBits(a);
    int biasedExp = (intBits & EXP_BIT_MASK) >> (SIGNIFICAND_WIDTH - 1);
    int shift = (SIGNIFICAND_WIDTH - 2 + EXP_BIAS) - biasedExp;
    if ((shift & -32) == 0) {
      // shift >= 0 && shift < 32
      // a is a finite number such that pow(2,-32) <= ulp(a) < 1
      int r = ((intBits & SIGNIF_BIT_MASK) | (SIGNIF_BIT_MASK + 1));
      if (intBits < 0) {
        r = -r;
      }
      // In the comments below each Java expression evaluates to the value
      // the corresponding mathematical expression:
      // (r) evaluates to a / ulp(a)
      // (r >> shift) evaluates to floor(a * 2)
      // ((r >> shift) + 1) evaluates to floor((a + 1/2) * 2)
      // (((r >> shift) + 1) >> 1) evaluates to floor(a + 1/2)
      return ((r >> shift) + 1) >> 1;
    } else {
      // a is either
      // - a finite number with abs(a) < exp(2,FloatConsts.SIGNIFICAND_WIDTH-32) < 1/2
      // - a finite number with ulp(a) >= 1 and hence a is a mathematical integer
      // - an infinity or NaN
      return (int) a;
    }
  }

  public static void test(int start, int end) {
    long beg_ms = System.currentTimeMillis();
    boolean warm_up = true;
    for (int j = 0; j < 2; ++j) {
      for (int x = start; ; ++x) {
        float src = Float.intBitsToFloat(x);
        int dst = Math.round(src);
        int etalon = java_round(src);
        if (warm_up && dst != 777) {
          System.out.printf("END warm up: j = %d  x = %d \n", j, x);
          warm_up = false;
          break;
        }
        if (dst != etalon) {
          System.out.printf("ERROR: x = %d  src = %f  dst = %d  etalon = %d \n", x, src, dst, etalon);
        }
        if (x == end)
          break;
      }
    }
    System.out.printf("END test: time_elapsed = %d ms \n", System.currentTimeMillis() - beg_ms);
  }

  public static void main(String[] args) {
    int start = 0;
    int end   = 0xFFFFFFFF;
    test(start, end);
  }
}

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/16382#discussion_r1424686631


More information about the hotspot-dev mailing list