Skip to content

-nan + 0 = +nan on riscv64 #269

Description

@svmhdvn

As stated in the riscv reference here: https://docs.riscv.org/reference/isa/unpriv/f-st-ext.html#21-1-3-nan-generation-and-propagation

Except when otherwise stated, if the result of a floating-point operation is NaN, it is the canonical NaN. The canonical NaN has a positive sign and all significand bits clear except the MSB, a.k.a. the quiet bit.

With relevance to awk, since awk uses double-precision floats for numbers, canonical NaN translates to +nan = 7ff8000000000000.

In

-inf -inform inform -nan -nancy nancy -123 0 123 +123 nancy +nancy +nan inform +inform +inf
, line 4 asserts that -nan + 0 = -nan, but this is NOT true on riscv64.

Here's a minimal repro that shows the issue on both gcc and clang on riscv64:

#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define myprint(d) do { \
  double _d = (d); \
  uint64_t _u; \
  memcpy(&_u, &_d, sizeof(_d)); \
  printf("%s = %f %" PRIx64 "\n", #d, _d, _u); \
} while (0)

int main(void)
{
    double f = -NAN;
    double g = 0;
    myprint(f);
    myprint(g);
    myprint(-NAN + 0);
    myprint(f + g);
}

Thus, that testcase is not portable. Downstream, we can see the test failure on FreeBSD in CI here: https://ci.freebsd.org/job/FreeBSD-main-riscv64-test/16606/testReport/usr.bin.awk.bugs-fixed/bug_fix_test/inf_nan_torture/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions