JTC1/SC22/WG14
N958
Signaling NaN Material for Rationale
by
Fred Tydeman
N958
Sept 12, 2001
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. The
following should be added to the Rationale as a new annex.
Annex B(?)
Optional 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).
5.2.4.2.2 Characteristics of floating types <float.h>
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.
6.10.8 Predefined macro names
The predefined macro names are augmented with
__SUPPORT_SNAN__
which has the value integer constant 1, intended to indicate
conformance to the specifications of this annex (optional
support for signaling NaNs).
7.12 Mathematics <math.h>
The number classification macros are augmented with
FP_NANS
FP_NANQ
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.
7.12.11.x The nans functions
Synopsis
#include <math.h>
double nans(const char *tagp);
float nansf(const char *tagp);
long double nansl(const char *tagp);
Description
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). Similarly
nansf and nansl are defined in terms of strtof and strtold.
If tagp does not point to an n-char-sequence string then the
result NaN's content is indeterminate.
Returns
The nans functions return a signaling NaN with content
indicated through tagp, provided they don't trigger it
first.
7.19.6.1 The fprintf function
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.
7.19.6.2 The fscanf function
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.
7.20.1.3 The strtod, strtof, and strtold functions
The syntax accepted by strtod is augmented to include:
sign-opt NANS
sign-opt NANS(n-char-sequence-opt)
Strings of the form NANS or NANS(n-char-sequence-opt)
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-sequence's 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.
---
Fred J. Tydeman +1 (512) 255-8696 Tydeman Consulting
3711 Del Robles [email protected] Programming, testing, numerics
Austin, Texas 78727 Vice-chair of J11 (ANSI "C")
USA Sample C99+FPCE tests: ftp://jump.net/pub/tybor/
Savers sleep well, investors eat well, spenders work forever.