The following was adopted from NCEG 91-028 (Floating-Point C Extensions), the last NCEG (Numerical C Extensions Group) document to discuss support for Signaling NaNs.
IEC-60559 (International version of IEEE-754) requires two kinds of NaNs: Quiet NaNs and Signaling NaNs. Standard C only adopted Quiet NaNs. It did not adopt Signaling NaNs because it was believed that they are of too limited utility for the amount of work required. But, for implementations that do wish to support Signaling NaNs, it is highly recommended that they be supported in the following manner (to promote consistency in implementations and portability among applications).
For this to work, there are several requirements on both applications and implementations. The application needs to be able to determine if the implementation supports signaling NaNs. The application needs to indicate to the implementation that it wishes to use signaling NaNs. The implementation needs a way to determine, both at translation time and runtime, if support for signaling NaNs is being asked for.
An application indicates that it wants to use signaling NaNs by defining the macro symbol _WANT_SNAN. If defined, _WANT_SNAN shall be defined before any Standard C headers are included. It is undefined if _WANT_SNAN is defined after any Standard C headers are included. It is undefined if _WANT_SNAN is both defined and undef'ed in a translation unit. An application that is made up of two or more translation units shall be consistent in its definition of _WANT_SNAN: either all translation units define _WANT_SNAN, or none of the translation units define _WANT_SNAN; otherwise, the results are undefined.
An implementation indicates that it supports signaling NaNs by predefining the macro symbol __SUPPORT_SNAN__.
It is assumed that if both _WANT_SNAN and __SUPPORT_SNAN__ are defined, the implementation will do some magic (such as define an external variable in the implementation's namespace), so that the runtime functions fprintf, fscanf, strtod, and related functions (including the wide character equivalents), know if support for signaling NaNs has been requested. That is, implementations that support signaling NaNs will extend those functions to test how signaling NaNs shall be treated at runtime (either as an extension or as an error).
Floating types may support not only numeric values, finite and possibly infinite, but also NaN (Not-a-Number) values, which do not represent numbers. A NaN that generally raises an exception when encountered as an operand of arithmetic operations is called a signaling NaN; the operation is said to trigger the signaling NaN. A NaN that behaves predictably and does not raise exceptions in arithmetic operations is called a quiet NaN. The IEEE floating-point standards specify quiet and signaling NaNs, but this document applies the general terms for non-IEEE implementations as well -- for example, the VAX reserved operand and the CDC and CRAY indefinite qualify as signaling NaNs. In IEEE standard arithmetic, operations that trigger a signaling NaN argument generally return a quiet NaN result, provided no trap is taken.
The primary utility of quiet NaNs -- "to handle otherwise intractable situations, such as providing a default value for 0.0/0.0" -- can be well supported through straightforward extensions to Standard C.
Other applications of NaNs may prove useful. Available parts of NaNs have been used to encode auxiliary information, for example about the NaN's origin. Signaling NaNs are good candidates for filling uninitialized storage; and their available parts could distinguish uninitialized floating objects. IEEE signaling NaNs and trap handlers potentially provide hooks for maintaining diagnostic information or for implementing special arithmetics.
However, C support for signaling NaNs, or for auxiliary information that could be encoded in NaNs, is problematic. Implementation mechanisms may trigger signaling NaNs, or fail to, in mysterious ways. The IEEE floating-point standards require that NaNs propagate, but not all implementations faithfully propagate the entire contents. And even the IEEE standards fail to specify the contents of NaNs through format conversion, which is pervasive in some C implementation mechanisms.
Whether an operation that merely returns the value of a numeric operand, changing at most its sign, triggers signaling NaNs is unspecified. Such operations include conversions that do not change precision, the unary + and - operators, and the fabs and copysign functions.
Leaving the semantics unspecified allows more efficient implementation. The IEEE floating-point standards explicitly give the option to implement same-precision conversions by either arithmetic operations or data moves, which is important because of the frequency of such conversions in parameter passing and assignments.
The predefined macro names are augmented with
which has the value integer constant 1, intended to indicate conformance to these specifications (optional support for Signaling NaNs).
The number classification macros are augmented with
which expand to integer constant expressions with values distinct from all the other number classification macros. FP_NANS is a subset of FP_NAN and is used to classify Signaling NaNs. FP_NANQ is also a subset of FP_NAN and is used to classify Quiet NaNs. Together, FP_NANS and FP_NANQ make up FP_NAN.
Results for the inquiry macros specified in the remainder of this section are undefined if the argument is not of floating type. These macros should not trigger signaling NaNs.
#include <math.h> double nans(const char *tagp); float nansf(const char *tagp); long double nansl(const char *tagp);
An implementation declares a nans function if and only if it supports signaling NaNs in the type of the function. The call nans("n-char-sequence") is equivalent to strtod("NANS(n-char-sequence)", (char**) NULL); the call nans("") is equivalent to strtod("NANS()", (char**) NULL). If tagp does not point to an n-char sequence or an empty string, the call is equivalent to strtod("NANS", (char**) NULL). Calls to nansf and nansl are equivalent to the corresponding calls to strtof and strtold.
The nans functions return a signaling NaN with content indicated through tagp, provided they don't trigger it first.
For a signaling NaN value, the implementation has the options to trigger the signaling NaN or to convert it in one of the styles [-]nans or [-]nans(n-char-sequence) -- which style, and the interpretation of any n-char sequence, is implementation-defined.
Use of an upper case format specifier, E, F, or G, results in INF, INFINITY, NAN, or NANS instead of inf, infinity, nan, or nans.
All valid syntax -- including infinity, NaN, and signed zero -- is treated in the same manner as strtod.
The fscanf function should not trigger a signaling NaN that it produces in response to a signaling NaN input string.
By not triggering signaling NaNs, fscanf provides a way of setting signaling NaN values. This might appear to be in conflict with the IEEE floating-point standards which require that binary-decimal conversion trigger signaling NaN input; however, the conversion of NANS input need not be regarded as decimal-to-binary conversion.
The expected form of the subject sequence (after an optional sign) is augmented to include:
-- NANS or NANS(n-char-sequenceopt), ignoring case in the NANS part
Strings of the form NANS or NANS(n-char-sequenceopt) produce signaling NaNs, if supported, else are treated as invalid input. If a signaling NaN is produced, the implementation has the option of returning it or triggering it. An implementation may use the n-char sequence to determine extra information to be represented in the NaN's significand; which n-char sequences are meaningful is implementation-defined.
The option to trigger a signaling NaN is needed by implementations whose function-return mechanism involves conversion between different formats, which may trigger the signaling NaN. For example, an implementation that returns functions' results in a wider-than-float register might not be able to return a signaling NaN result for strtof.
Although SNAN would have been a more suggestive representation for signaling NaNs, NANS was chosen instead because it lessens the likelihood of consuming non-numeric input, and because IEEE standard 854 says that string representations of NaNs should begin with "NAN". For quiet NaNs, NAN was chosen over NANQ for brevity and because the predominance of NaNs in I/O are expected to be quiet.
This function is extended in the same manner as fprintf.
This function is extended in the same manner as fscanf.
These functions are extended in the same manner as strtod, strtof, and strtold.