Skip to content

CWG2836 [conv.rank] long double + _Float64 is handled differently from C #472

Closed
cplusplus/draft
#7099
@jcranmer-intel

Description

@jcranmer-intel

Full name of submitter: Joshua Cranmer

Reference (section label): [conv.rank]

Issue description:

Suppose we have a system where double, long double, and _Float64 or std::float64_t all use the same underlying floating-point semantics. Under C23 (taken from draft N3096), the common real floating-point type is determined by first using the interchange type (i.e., _Float64), then long double, and then double). Under C++23, [conv.rank] specifies that long double and double are different ranks (per p2.2), with std::float64_t is in the same rank as double (per p2.5) and a higher subrank than double (per 3).

Under C's rules, then, if you were to add long double and _Float64, the _Float64 would be the result. But under C++, long double is the result, because the long double rank wins out over _Float64's rank. It is not clear that this result was intentional. P1467R6 and later revisions all have a C compatibility section, where these paragraphs appear:

Previously, there was also a difference in usual arithmetic conversions. This proposal and C have always agreed on the results of a binary operator when at least one of the operands is a floating-point type and the two types have different representations. However, when the two operands were different floating-point types with the same representation, this paper proposed that double + std::float64_t (assuming they have the same representation) would have type double, while in C, double + _Float64 has type _Float64. The rationale for the C rules is that if a user buys into the fixed-layout types explicitly, we should preserve that decision through expressions and library function calls.

This matter was discussed during an SG22 meeting, and a consensus was reached that this paper should instead adopt the C rules; now, with this revision, the result of double + std::float64_t is std::float64_t.

Records of the relevant SG22 meeting can be found at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2835.pdf, which confirm that this is accurate.

A subsequent followup to the CFP mailing list by the author of P1467 was sent to ask about this case, and if C would change its rules to make long double + _Float64 yield long double instead here: http://mailman.oakapple.net/pipermail/cfp-interest/2021-October/002256.html. The CFP reply indicated no desire in C to change, and the subsequent CFP telecon also affirmed that (see https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2876.pdf for meeting minutes). However, none of the further discussions of the paper in C++ appear to have observed this incompatibility with C, although the topic of mapping to double or long double was discussed during CWG telecons (specifically the one on 2022-03-25).

It is not clear if the incompatibility between C and C++ with regards to the arithmetic conversions here was intentional.

Suggested resolution:
Change [conv.rank]p2.5 to

An extended floating-point type with the same set of values as more than one cv-unqualified standard floating-point type has a rank equal to the highest rank among such types.

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