7
#include <stdio.h>
#include <stdint.h>
#include <fenv.h>
#include <math.h>

int main()
{
    typedef union { uint32_t u; float f; } ufloat;
    ufloat val;
    float arg = 2401.999999;
    int r;
    r = fesetround(FE_DOWNWARD);
    val.f = sqrtf(arg);
    printf ("FE_DOWNWARD   %22.13a [0x%x] %d\n", val.f, val.u, r);
    r = fesetround(FE_TONEAREST);
    val.f = sqrtf(arg);
    printf ("FE_TONEAREST  %22.13a [0x%x] %d\n", val.f, val.u, r);
    r = fesetround(FE_TOWARDZERO);
    val.f = sqrtf(arg);
    printf ("FE_TOWARDZERO %22.13a [0x%x] %d\n", val.f, val.u, r);
    r = fesetround(FE_UPWARD);
    val.f = sqrtf(arg);
    printf ("FE_UPWARD     %22.13a [0x%x] %d\n", val.f, val.u, r);
    return 0;
}

Host: Win10 x64.

Results:

Case 1.

$ clang t2.c -o t2.clang.exe && ./t2.clang.exe
FE_DOWNWARD     0x1.8814e60000000p+5 [0x42440a73] 0
FE_TONEAREST    0x1.8814e60000000p+5 [0x42440a73] 0
FE_TOWARDZERO   0x1.8814e60000000p+5 [0x42440a73] 0
FE_UPWARD       0x1.8814e60000000p+5 [0x42440a73] 0
 
$ clang --version
clang version 8.0.1 (tags/RELEASE_801/final)

Case 2.

$ gcc t2.c -o t2.gcc.exe && ./t2.gcc.exe
FE_DOWNWARD     0x1.8814e60000000p+5 [0x42440a73] 0
FE_TONEAREST    0x1.8814e60000000p+5 [0x42440a73] 0
FE_TOWARDZERO   0x1.8814e60000000p+5 [0x42440a73] 0
FE_UPWARD       0x1.8814e60000000p+5 [0x42440a73] 0
 
$ gcc --version
gcc (GCC) 10.2.0

Case 3.

cl t2.c && t2
Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28611 for x64
...
FE_DOWNWARD     0x1.8814e40000000p+5 [0x42440a72] 0
FE_TONEAREST    0x1.8814e60000000p+5 [0x42440a73] 0
FE_TOWARDZERO   0x1.8814e40000000p+5 [0x42440a72] 0
FE_UPWARD       0x1.8814e60000000p+5 [0x42440a73] 0

Case 4.

cl t2.c && t2
Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28611 for x86
...
The system cannot execute the specified program.
Pop-up window appears: "Virus & thread protection: Windows Defender Antivirus found threats. Get details."

Case 5.

wandbox.org: gcc HEAD 11.0.0 20200
$ gcc prog.c -Wall -Wextra -std=c99 "-lm"
FE_DOWNWARD     0x1.8814e40000000p+5 [0x42440a72] 0
FE_TONEAREST    0x1.8814e60000000p+5 [0x42440a73] 0
FE_TOWARDZERO   0x1.8814e40000000p+5 [0x42440a72] 0
FE_UPWARD       0x1.8814e60000000p+5 [0x42440a73] 0

Case 6.

wandbox.org: clang HEAD 12.0.0
$ clang prog.c -Wall -Wextra -std=gnu11 "-lm"
FE_DOWNWARD     0x1.8814e40000000p+5 [0x42440a72] 0
FE_TONEAREST    0x1.8814e60000000p+5 [0x42440a73] 0
FE_TOWARDZERO   0x1.8814e40000000p+5 [0x42440a72] 0
FE_UPWARD       0x1.8814e60000000p+5 [0x42440a73] 0

Questions:

  1. Why there are different results (0x42440a72 vs. 0x42440a73) between compilers?
  2. How to get the same results between compilers?
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
pmor
  • 5,392
  • 4
  • 17
  • 36
  • You can - and must post those - just don't put *everything as a code block*. Format the headings of the separate runs as normal text! – Antti Haapala -- Слава Україні Sep 13 '20 at 12:55
  • 1
    @AnttiHaapala, thanks for the hint (using `
    code
    ` pattern)!
    – pmor Sep 13 '20 at 13:16
  • 3
    Changing floating-point rounding modes is not well supported by some compilers and libraries, but one problem in your source code is that the C standard does not define the behavior if you change rounding modes with `FENV_ACCESS` off (C 2018 7.6.1 2). You can turn it on with `#pragma STDC FENV_ACCESS ON` in compilers that support it. – Eric Postpischil Sep 13 '20 at 13:17
  • Do I understand correctly that in case of `FENV_ACCESS` off we cannot rely on `fesetround()` return value because of UB? In the example above `fesetround()` does [falsely] return `0` (i.e. rounding direction was successfully set), but from the results we see that rounding direction was not set. – pmor Sep 13 '20 at 17:20

1 Answers1

1

Why there are different results (0x42440a72 vs. 0x42440a73) between compilers?

At least with older gcc, <fenv.h> support not required.

See floating-point environment access in <fenv.h>, Library feature, no compiler support required.

When I compile with "GNU C11 (GCC) version 9.3.0 (x86_64-pc-cygwin)", the below

#include <fenv.h>
#pragma STDC FENV_ACCESS ON

I receive the below:

warning: ignoring #pragma STDC FENV_ACCESS [-Wunknown-pragmas]

See also If pragma STDC FENV_ACCESS is absent, does it mean default rounding mode?, pragma STDC FENV_ACCESS ON is not supported

How to get the same results between compilers?

Not that helpful, but do not use optional features of fenv.h or avoid select compilers.

There may exist a gcc compile time flag to help, but I am not aware of one.

Also use #pragma STDC FENV_ACCESS ON @Eric Postpischil. This may not solve this issue, but prevent related ones.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • 1
    Both gcc and clang do not support `#pragma STDC FENV_ACCESS ON`. gcc: `warning: ignoring '#pragma STDC FENV_ACCESS'`, clang: `warning: pragma STDC FENV_ACCESS ON is not supported`. For clang it seems that there is a patch: https://reviews.llvm.org/D69272. For cl: need to use `#pragma fenv_access (on)`. – pmor Sep 13 '20 at 17:11