Can NAN and INFINITY be used under non-default rounding modes?
Sample code:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
#if _MSC_VER && ! __clang__ && ! __INTEL_COMPILER
#pragma fenv_access (on)
#else
#pragma STDC FENV_ACCESS ON
#endif
int main(void)
{
float f;
if (fesetround(RM) != 0) return 1;
f = V;
printf("%f\n", f);
return 0;
}
Invocations:
$ gcc t583.c -std=c11 -pedantic -Wall -Wextra -DV=NAN -DRM=FE_TOWARDZERO && ./a.exe
nan
$ gcc t583.c -std=c11 -pedantic -Wall -Wextra -DV=INFINITY -DRM=FE_TOWARDZERO && ./a.exe
inf
$ cl t583.c /std:c11 /Za /fp:strict /DV=NAN /DRM=FE_TOWARDZERO /nologo && ./t583.exe
0.000000
$ cl t583.c /std:c11 /Za /fp:strict /DV=INFINITY /DRM=FE_TOWARDZERO /nologo && ./t583.exe
340282346638528859811704183484516925440.000000
GCC defines NAN
and INFINITY
as:
#define NAN (__builtin_nanf(""))
#define INFINITY (__builtin_inff())
while MSVC defines NAN
and INFINITY
as:
#define NAN ((float)(INFINITY * 0.0F))
#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
and _HUGE_ENUF
as:
#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow
So, with MSVC under /fp:strict
AND under FE_TOWARDZERO
and FE_DOWNWARD
:
- the
INFINITY
evaluates toFLT_MAX
, and - the
NAN
evaluates to0.0
.
Confused.
However, is it allowed at all to use NAN
and INFINITY
under non-default rounding modes, such as FE_TOWARDZERO
and FE_DOWNWARD
?
Reason of the question: better understanding of the C standard.
What problem is being solved: experimenting with non-default rounding modes using MSVC, trying to produce expected results.
is it allowed at all to use
NAN
andINFINITY
under non-default rounding modes, such asFE_TOWARDZERO
andFE_DOWNWARD
?
The language specification does not express any limitation on using INFINITY
. A conforming implementation must therefore accept it and interpret it consistently with the provisions of the language specification regardless of rounding mode. Specifically, it
expands to a constant expression of type
float
representing positive or unsigned infinity, if available; else to a positive constant of typefloat
that overflows at translation time.
(C17 7.12/4)
That is not conditioned on the rounding mode in effect at any particular time. Since MSVC does have an available float
representation for infinity and FLT_MAX
is required to be a representation of a finite number, it is non-conforming for INFINITY
to evaluate equal to FLT_MAX
in MSVC, under any circumstances. Indeed, MSVC is non-conforming to whatever extent INFINITY
ever fails to evaluate to a positive float
infinity.
It is even more clear for NAN
. The specification says that it
is defined if and only if the implementation supports quiet NaNs for the
float type
.
In that case,
It expands to a constant expression of type
float
representing a quiet NaN.
(C17 7.12/5)
If NAN
is defined at all then it expands to an expression that evaluates to a quiet NaN. Period. If MSVC provides for circumstances in which it instead expands to 0.0, then MSVC is non-conforming under those circumstances.
It should be acknowledged that most, if not all, C implementations have some non-conformity, whether by default or accessible via command-line options or similar. Nevertheless, MSVC is notorious for its comparatively poor conformance among the widely used C implementations.