Date: Thu, 16 Apr 2026 11:26:49 +0200
We ought to have some portable way to classify a floating-point type
according to its ISO/IEC 60559 format. For example, one may want to detect
at compile time whether float has the same representation as std::float32_t,
and other such things.
Merely checking whether the type is 32 bits large and is_iec559 is true
doesn't necessarily work. The floating-point type could also be in an
extended 16-bit format, or in an interchange format that also has 32 bits
but is not binary32, or it could be binary16 with 16 bits of padding. A
perfectly reliable approach (that doesn't involve querying all sorts of
other properties like the number of digits and the exponent) would look
like:
enum class iec559_format : /* unspecified */ {
unclassified,
binary_arithmetic, // e.g. x87 80-bit long double;
// has inf, qNaN, sNaN, and can represent numbers,
// but is not an interchange format
binary_interchange, // generic binary interchange format,
// e.g. binary256 or binary512
binary16, // basic binary interchange format (std::float16_t)
binary32,
binary64,
binary128,
binary16x, // extended format for binary16 (C23 _Float16x)
binary32x,
binary64x,
binary128x,
decimal_arithmetic,
decimal_interchange, // generic decimal interchange format
decimal32, // basic decimal interchange format
decimal64,
decimal128,
decimal32x, // extended format for decimal32 (C23 _Decimal32x)
decimal64x,
decimal128x,
};
The user could use this as follows:
constexpr auto f = std::numeric_limits<T>::iec559_format;
if constexpr (f == std::iec559_format::binary32) {
// always true for std::float32_t, usually true for float
}
if constexpr (f == std::iec559_format::binary64) {
// always true for std::float32_t, usually true for double,
// sometimes true for long double
}
according to its ISO/IEC 60559 format. For example, one may want to detect
at compile time whether float has the same representation as std::float32_t,
and other such things.
Merely checking whether the type is 32 bits large and is_iec559 is true
doesn't necessarily work. The floating-point type could also be in an
extended 16-bit format, or in an interchange format that also has 32 bits
but is not binary32, or it could be binary16 with 16 bits of padding. A
perfectly reliable approach (that doesn't involve querying all sorts of
other properties like the number of digits and the exponent) would look
like:
enum class iec559_format : /* unspecified */ {
unclassified,
binary_arithmetic, // e.g. x87 80-bit long double;
// has inf, qNaN, sNaN, and can represent numbers,
// but is not an interchange format
binary_interchange, // generic binary interchange format,
// e.g. binary256 or binary512
binary16, // basic binary interchange format (std::float16_t)
binary32,
binary64,
binary128,
binary16x, // extended format for binary16 (C23 _Float16x)
binary32x,
binary64x,
binary128x,
decimal_arithmetic,
decimal_interchange, // generic decimal interchange format
decimal32, // basic decimal interchange format
decimal64,
decimal128,
decimal32x, // extended format for decimal32 (C23 _Decimal32x)
decimal64x,
decimal128x,
};
The user could use this as follows:
constexpr auto f = std::numeric_limits<T>::iec559_format;
if constexpr (f == std::iec559_format::binary32) {
// always true for std::float32_t, usually true for float
}
if constexpr (f == std::iec559_format::binary64) {
// always true for std::float32_t, usually true for double,
// sometimes true for long double
}
Received on 2026-04-16 09:27:04
