As someone who has just added IEEE FP to an implementation of the ANSI M language I recommend against saying much about NaNs in a language standard. All of our target platforms for ANSI M implement IEEE Std 754-1985 but almost none support IEEE Std 754-2008.

IEEE Std 754-1985 only defined binary representations for floating point. It defined nothing about the payload of a NaN other than there must be at least one signaling NaN, at least one quiet NaN, and the sign bit cannot be used to differentiate between signaling versus quiet.

IEEE Std 754-2008 says only a little bit more about NaNs. For decimal representation it defines a requirement that determines which payloads are quiet NaNs versus which payloads are signaling. But for binary representation it has a “recommendation” for which payloads are quiet versus signaling. (I assume this is a recommendation instead of a requirement so that existing implementations of IEEE 754-1985 that chose another quiet/signaling NaN representation could still comply with the standard.)

We allow customers to move their data accessed by ANSI M between all our supported platforms. When we do arithmetic on NaNs the various platforms will modify the payloads in different ways. On some platforms even moving floating-point data can modify the bit pattern representing a NaN. The biggest issue is that quiet versus signaling is sometimes different on different platforms.

Our solution was to say there is only one NaN (but it has lots of different binary representations). This one NaN works the same everywhere (regardless of its binary representation.) The IEEE FP standard requires that this one NaN never equals itself (even if two instances share the same internal binary representation.) We guarantee that if you give us a NaN as input or you do an arithmetic operation that results in a NaN then you will get one of the many binary representations of the one NaN value. If you give us a NaN generated externally and you retrieve that NaN without attempting to modify it then we do our best to avoid having the platform modify the bit pattern before we return it the external device that is the target of your retrieval. Nothing else is portable between platforms. Trapping on NaNs is not a feature of our language implementation because it is not portable.

If you are willing to be platform dependent (I.e. nonportable) then we allow you to enable trapping on signaling NaNs but you can expect different platforms to give you different results. You can do arithmetic on floating point values and we can promise the results do whatever the underlying platform supports (including archaic things like extended register arithmetic) but we can never promise that all our platforms give the same bit patterns when NaNs are involved. We consider conversions between floating-point representation and other representation to be “sacrosanct” so we do not use conversions supplied by the platform but we do our own conversions with “infinite” precision. (I.e., we supply more accuracy than required by the previous IEEE 754-1985 standard.) We also do comparisons between mixed data type representations with infinite precision. All other operations are done with the accuracies supplied by the platform.

If COBOL only supports decimal floating point then your language standard can promise that signaling and quiet NaNs are well defined separate classes of values; you can promise that values will be transferred between the classes in a well defined way. You really cannot easily define how operations choose between values in same class of NaN. It is best that your standard just says that choice of bit pattern for a signaling NaN and choice of bit pattern for a quiet NaN is either Implementation Defined (the implementation must document its choices) or Implementation Dependent (the implementation may make a choice without documenting it.) I recommend making it Implementation Dependent because some chip vendors have different model chips for the same architecture that transfer NaN values in different ways from each other.

PS: We also have the capability of converting a NaN in one IEEE format into another IEEE format (say, Binary128 to Decimal64) through the MOVE statement.

The currently-proposed specification is that the payload is transferred intact, with trailing bit or digit truncation of the payload as needed if the capacity of the receiving data item does not allow for a payload of that size. If the payload is other than a "left-justified integer" in the sending operand, this might make the payload value in the receiving NaN. I'm trying to avoid that.

Clause 5.4.2 seems to allow this for NaNs, applying the rules of Clause 4 to imply that the end result is rounded if need be. For MOVE in COBOL, the only rounding mode is roundTowardZero, so that could be interpreted as applying what is currently proposed for COBOL.

I can always propose deleting "POSITIVE-NAN" from the keyword list for SET CONTENT OF, but that leaves what happens to a NaN on a long-to-short convertFormat operation unspecified if that's what the (compiler) implementor uses for the MOVE statement in this case.

-Chuck Stevens

> To: charles.stevens@xxxxxxxx> CC: stds-754@xxxxxxxxxxxxxxxxx; bobkarlin@xxxxxxxxxxxxxxxxx; wmklein@xxxxxxxxxxxxx; forieee@xxxxxxxxxxxxxx> From: forieee@xxxxxxxxxxxxxx> Subject: Re: Payload length and interpretation in IEEE Std 754-2008> Date: Fri, 29 Apr 2011 08:39:31 -0700> > Chuck,> > I'm not sure where you are going with this observation> but it must be admitted that, as far as the utility of> payloads is concerned, NaNs have fallen far short of> our goals for them over the years.> > They were orginally intended to contain diagnostic> information beyond the fact that something invalid has> happened. Had there been a portable trap mechanism> they might have fulfilled that goal. As it is, the> only times they have been useful have been limited to> narrow applications on single implementations.> > Therefore, as a standards body, I think the best you> can do is leave that small utility in place. You will> not be able to define anything for Cobol as a whole &> get it to work.> > As for Ivan's attempt to patent something in this area,> I wouldn't worry too much about that. For the above> reasons as much as anything else.> > Yours,> > Dan> > > > From: Charles Stevens <charles.stevens@xxxxxxxx>> > To: IEEE 754 <stds-754@xxxxxxxxxxxxxxxxx>> > CC: Robert Karlin <bobkarlin@xxxxxxxxxxxxxxxxx>,> > William Klein <wmklein@xxxxxxxxxxxxx>> > Subject: Payload length and interpretation in IEEE Std 754-2008> > Date: Fri, 29 Apr 2011 08:31:41 -0600> > > > > > The payload seems to be provided to allow the implementor to specify diagno=> > stic information about the operation that produced it=2C and I don't find m=> > uch about how it should be encoded=2C what its limits are=2C and whether th=> > ose limits are the same regardless of the width of the format. > > > > It also seems to me that it would be illogical for the implementor to speci=> > fy payloads in=2C say=2C a decimal128 item that could not=2C on capacity gr=> > ounds=2C be specified to the same degree of exactness in a binary32 item.> > > > As I read it=2C to give two examples=2C the capacity limits (presuming a ri=> > ght-justified integer) are 23 bits (numeric range 1 - 8=2C388=2C607) for bi=> > nary32 and 33 digits (1 - 999=2C999=2C999=2C999=2C999=2C999=2C999=2C999=2C9=> > 99=2C999=2C999) for decimal128. Even the least of these ought to provide e=> > nough variations to allow the implementor to report whatever he felt was ap=> > propriate. Eight million potential "error codes" is a lot of error codes.=> > > > > > It's also unclear to me how this payload value (or bit-pattern) in the trai=> > ling significand is to be interpreted -- as a bit-pattern (even for decimal=> > )=2C as a right-justified integer=2C as a left-justified integer=2C as a fr=> > actional value=2C or as a canonic significand with the implied decimal/bina=> > ry point after the first digit/bit. Is this clearly specified somewhere? => > > > > > -Chuck Stevens => >