Skip to content

[conv] Floating-point conversions should not require signaling NaN to be preserved #887

@eisenwave

Description

@eisenwave

Section: [conv]

Issue description

Floating-point promotion ([conv.fpprom]) and floating-point conversion ([conv.double]) require that a value is unchanged if possible.

No compiler fully implements this wording because for a conversion from float to double, they emit a cvtss2sd instruction, which converts signaling NaNs to quiet NaNs. This implements the convertFormat operation as specified in ISO/IEC 60559:2020 §5.4.2.

Proposed resolution

Change [conv.fpprom] paragraph 1 as follows:

 A prvalue of type float can be converted to a prvalue of type double.
 The value is unchanged
+, except that a signaling NaN may be converted to a quiet NaN
 .

Change [conv.double] paragraph 2 as follows:

 If the source value can be exactly represented in the destination type,
 the result of the conversion is that exact representation
+, except that a signaling NaN may be converted to a quiet NaN
 .
 If the source value is between two adjacent destination values,
 the result of the conversion is an implementation-defined choice of either of those values. 
 Otherwise, the behavior is undefined.

Important

UPDATE: I now believe that there is no defect specifically in this area, if we make it clear that qNaN and sNaN are the same value in P3938R1.

I've had a chat with the Floating-Point Study Group; the C wording is almost identical to that of C++ here, which can give us guidance. The corresponding C wording seems to work because quiet and signaling NaN are not distinct values. Consider Table 3.1 from ISO/IEC 60559:
Image
When C talks about a "value", this is talking about specification level 2; anything below that deals with the representation of the same value. Notably, the C standard says in §5.3.5.3.3:

A NaN is a value signifying Not-a-Number. A quiet NaN propagates through almost every arithmetic
operation without raising a floating-point exception; a signaling NaN generally raises a floating-point exception when occurring as an arithmetic operand.

It looks like "NaN" is the only thing defined as a value, and whether that value is quiet or signaling is an additional property. We don't have any C++ wording that clarifies that, but if we did, [conv] would work fine.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions