Difference in behaviour in native math library
Ludovic Henry
ludovic at rivosinc.com
Thu Dec 8 18:01:23 UTC 2022
Hi,
Yes, this is very much a difference of behavior at the libm/libc level. I'm
trying to figure out whether that behavior difference is acceptable from
the libm/libc level (is it considered a bug to behave differently across
architectures in that case?). If that behaviour is acceptable in libm/libc,
then is it acceptable to behave differently in Java across architectures?
>From your answer Palmer, the difference _might_ not be acceptable in the
glibc test suite (I haven't check why the tests are failing). I'm still
trying to figure that one out.
>From your answer Joe, the difference _is_ acceptable from the
documentation. IMO the question becomes whether it's a case of the
implementation details bleeding into the API and whether we want to be 100%
compatible to avoid further issues. The fix for that could be a simple
`RISCV_ONLY(if (isnan(v)) return v);` or equivalent
in src/java.base/share/native/libjava/StrictMath.c to match the behavior
without any extra cost for other platforms.
Thanks,
Ludovic
On Thu, Dec 8, 2022 at 2:50 PM Palmer Dabbelt <palmer at dabbelt.com> wrote:
> On Thu, 08 Dec 2022 08:26:30 PST (-0800), ludovic at rivosinc.com 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?
>
> It might just be a glibc bug, we're failing the acos() tests:
>
> https://sourceware.org/glibc/wiki/Release/2.35#RISC-V_.28rv64imafdc.2Flp64d.29
> . I haven't looked at why, but they do have some nan-related bits in
> there.
>
> >>
> >> Cheers,
> >> Ludovic
> >>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/riscv-port-dev/attachments/20221208/ce6170ee/attachment-0001.htm>
More information about the riscv-port-dev
mailing list