Difference in behaviour in native math library

Joseph D. Darcy joe.darcy at oracle.com
Thu Dec 8 17:31:07 UTC 2022


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 <ludovic at 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/riscv-port-dev/attachments/20221208/c5ac1eb5/attachment-0001.htm>


More information about the riscv-port-dev mailing list