NaNcodes -- a missed opportunity
Being unfettered by precedent, the DFP handling of NaN payloads is much
better specified than that for BFP (Decimal floating-point vs Binary FP).
There is still ambiguity in NaNcode propagation rules when multiple NaNs
are involved, and even in the single-NaN case preservation of the payload
is only a "should", but at least the preferred interpretation is clear.
DFP NaNcodes *are* the integer encoded by the trailing significand, but
BFP NaNcodes are only "encoded by" the p-2 least-significant bits. This
distinction was necessary because existing environments that do support
input and output of NaNcodes (via the C99 "NaN(n-char-sequence)" format
for example) do this in radically different ways. The "n-char-sequence"
is not even required to be numeric -- it could be names for diagnostic
conditions for example, though the two implementations I have seen
(Linux glibc and z/OS Language Environment) do expect them to be numeric.
(z/OS puts a bit-reversed binary integer into the payload, thus preserving
propagation of small integers through narrowing and widening conversions
as well as through BFP<->DFP conversions; glibc right-aligns the binary
integer in the payload field, which is more natural when there are no
conversions between different formats.)
We (the 754R working group) could have brought a bit more clarity into
this by explicitly defining (and at least recommending if not requiring)
a pair of operations to insert and extract numeric NaNcodes, for each
supported format. A numeric NaNcode can be represented as an exact
floating-point integer in the same format, so the result would be in the
same format as the operand:
extractNaNcode(x) returns a numeric NaN payload as a floating-point
integer when x is a NaN, without signalling
exceptions (even when x is an SNaN).
insertNaNcode(x) returns a Quiet NaN whose payload is the integral
part of x, or returns x itself if x is a NaN.
These definitions are incomplete, and we would have discussed how to deal
with the remaining cases, e.g. what to do about Infinities (or out-of-range
NaNcodes in general), and (for extractNaNcode) what to return when x is not
a NaN (Infinity would be unambiguous, for example). Also, should it be
possible to generate a Signalling NaN (C99 only specifies creating QNaNs)?
Environments with non-numeric NaNcodes could define symbols that map to
numeric codes, or additional functions that map numeric codes to strings,
though the normal convertToDecimalCharacter() operation is already supposed
to do that.
For simple numeric NaNcodes it seems gross overkill however to have to go
through a character string intermediate (e.g. via sprintf() and atof()).
P.S. As the sign can be dealt with separately (we have copySign()),
the extracted NaNcode could be non-negative -- in fact, should be
non-negative because 754 already states that the sign of a NaN is
not significant. Then a non-NaN could return -1.0 -- easier to
test for than an Infinity. The isSignalling() predicate is there
to further qualify a NaNcode.
---Sent: 2011-01-22 17:29:01 UTC