Regarding the FLT_ROUNDS macro declared in <float.h>, a footnote in the C standard states:
The rounding mode for floating-point addition is characterized by the implementation-defined value of FLT_ROUNDS:23)
-1 indeterminable
0 toward zero
1 to nearest
2 toward positive infinity
3 toward negative infinity
23) Evaluation of
FLT_ROUNDScorrectly reflects any execution-time change of rounding mode through the functionfesetroundin<fenv.h>.
Giving this a try with a little example program:
#include <float.h>
#include <fenv.h>
#include <stdio.h>
#pragma STDC FENV_ACCESS ON
int main()
{
printf( "Initial FLT_ROUND: %d\n", FLT_ROUNDS );
printf( "Initial fegetround: %d\n\n", fegetround() );
fesetround( FE_TOWARDZERO );
printf( "Current FLT_ROUND: %d\n", FLT_ROUNDS );
printf( "Current fegetround: %d\n", fegetround() );
}
Compiled with:
gcc -std=c11 testme.c -o testme -lm
I get the following output on Linux:
Initial FLT_ROUND: 1
Initial fegetround: 0
Current FLT_ROUND: 1
Current fegetround: 3072
On Cygwin:
Initial FLT_ROUND: 1
Initial fegetround: 0
Current FLT_ROUND: 1
Current fegetround: 3
Given the statement from the standard, I would be expecting:
...
Current FLT_ROUND: 0
...
Is this non-conforming implementation, or did I understand that standard footnote wrongly?
FWIW, trying the same on Android / Termux gives me:
Initial FLT_ROUND: 1
Initial fegetround: 0
Current FLT_ROUND: 0
Current fegetround: 3
This makes me suspect a faulty implementation on both Linux and Cygwin...?
This is GCC Bug 30569.
GCC documents this as "implementation-defined behavior":
The rounding behaviors characterized by non-standard values of FLT_ROUNDS (C90, C99 and C11 5.2.4.2.2).
GCC does not use such values.
Termux uses the BSD libc and clang "masquerading" as GCC, which explains the standard-compliant behavior on Android.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With