Hello,

Okay, so it looks like the test is expected the same bit pattern to be used for a NaN output if a NaN was used as an input.

That isn't necessarily unreasonable, but it is *not* required by the specifications for the Math or StrictMath method, spec for Math.acos:

Returns the arc cosine of a value; the returned angle is in the range 0.0 through /pi/. Special case:

  * If the argument is NaN or its absolute value is greater than 1,
    then the result is NaN.
  * If the argument is |1.0|, the result is positive zero.

The computed result must be within 1 ulp of the exact result. Results must be semi-monotonic.

https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/lang/Math.html#acos(double)

On a NaN argument, any NaN bit pattern is valid per the spec. Even if you're trying to return the same NaN, there can be challenges to doing so depending on how the underlying processor handles signaling NaNs, a concept which doesn't exist in the Java platform.

HTH,

-Joe

On 12/8/2022 8:26 AM, Ludovic Henry wrote:
Adding the right address for core-libs-dev.

On Thu, Dec 8, 2022 at 12:19 PM Ludovic Henry <ludo...@rivosinc.com> wrote:

    Hello,

    I've noticed that some Math trigonometry tests are failing in the
    GNU Mauve test suite. From digging into it, it's related to NaN
    values being passed to java.lang.Math trigonometry functions, and
    how these values are handled in the native libm library.

    Given the following C test case compiled and run with `gcc acos.c
    -lm && ./a.out`

    ```
    #include <stdint.h>
    #include <math.h>
    #include <stdlib.h>
    #include <stdio.h>

    void main(int argc, char* argv[]) {
        int64_t bitsNaN = 0x7fff800000000000L;
        double valNaN = *((double*)&bitsNaN);

        double resD = acos(valNaN);
        int64_t res = *((int64_t*)&resD);
        if (!(res == bitsNaN)) {
            printf("expected 0x%lx but got 0x%lx\n", bitsNaN, res);
            exit(1);
        }
    }
    ```

    On a Linux-x64, the test succeeds, but on Linux-RISC-V, the test
    fails.

    You've the same test failure in the equivalent Java code:

    ```
    public class acos {
        public static void main (String[] args) {
            long bitsNaN = 0x7fff800000000000L;
            double valNaN = Double.longBitsToDouble(bitsNaN);

            long res = Double.doubleToRawLongBits(Math.acos(valNaN));
            if (!(res == bitsNaN)) {
                throw new RuntimeException(String.format("expected
    0x%x but got 0x%x", bitsNaN, res));
            }
        }
    }
    ```

    What approach should we take in these cases? Is it that the test
    case is wrong, and should assume that given a NaN, any value of
    NaN returned is valid? Or should we make sure that the behavior is
    the same across platforms and that we "fix" any difference in
    behavior of the native library?

    Cheers,
    Ludovic

Reply via email to