2

I'm looking for a way to detect whether a C compiler uses the IEEE-754 floating point representation at compile time, preferably in the preprocessor, but a constant expression is fine too.

Note that the __STDC_IEC_559__ macro does not fit this purpose, as an implementation may use the correct representation while not fully supporting Annex F.

squirl
  • 1,636
  • 1
  • 16
  • 30
  • 1
    Most likely the compiler itself will be "using" whatever format used by the underlying hardware. – Some programmer dude Jul 29 '20 at 16:16
  • 2
    @Someprogrammerdude I think he means "implementation", which is the combination of hardware, compiler, libraries, etc. – Barmar Jul 29 '20 at 16:18
  • 2
    A common issue with `__STDC_IEC_559__` is its "shall implement floating point types (what OP wants - easy enough to comply) and arithmetic conforming to IEC 60559 (the hard part)". The "arithmetic conforming to IEC 60559" is a hard test to do, let alone pass. Some highly compliant compilers leave it undefined rather than risk a missed corner case. – chux - Reinstate Monica Jul 29 '20 at 17:13

2 Answers2

3

Not an absolute 100% solution, but will get you practically close.

Check if the characteristics of floating type double match binary64:

#include <float.h>

#define BINARY64_LIKE ( \
  (FLT_RADIX == 2) \
  (DBL_MANT_DIG == 53)  \
  (DBL_DECIMAL_DIG == 17) \
  (DBL_DIG == 15) \
  (DBL_MIN_EXP == -1021) \
  (DBL_HAS_SUBNORM == 1) \
  (DBL_MIN_10_EXP == -307) \
  (DBL_MAX_EXP == +1024) \
  (DBL_MAX_10_EXP == +308))

BINARY64_LIKE usable at compile time. Need additional work though for older compilers that do not define them all like: DBL_HAS_SUBNORM since C11.

Likewise for float.

Since C11, code could use _Static_assert() to detect some attributes.

_Static_assert(sizeof(double)*CHAR_BIT == 64, "double unexpected size");

See also Are there any commonly used floating point formats besides IEEE754?.

Last non-IEEE754 FP format I used was CCSI 5 years ago.


Caution: Unclear why OP wants this test. If code is doing some bit manipulations of a floating point, even with __STDC_IEC_559__ defined there remains at least one hole: The endian of floating point and integer may differ - uncommon - but out there.

Other potential holes: support of -0.0, NaN sign, encoding of infinity, signalling NaN, quiet NaN, NaN payload: the usual suspects.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • A [link to page with the floating point MACRO reference for C](https://en.cppreference.com/w/c/types/limits#Limits_of_floating_point_types). – Myst Jul 29 '20 at 16:49
  • @Myst Thanks for the link. Pretty much one can use all characteristics except ones like `DBL_MAX, FLT_MIN` as those do not work uniformly well with preprocessor math. – chux - Reinstate Monica Jul 29 '20 at 16:54
  • There is no need to check the values with `DECIMAL` or `10` in their names, because they are functions of the others, which completely characterize the representable values except for infinity and NaN support. (Hypothetically, a format could use more bits and allow, say, unnormalized representations. But the set if representable values would be the same.) – Eric Postpischil Jul 29 '20 at 17:26
  • @EricPostpischil A reasonable simplification. – chux - Reinstate Monica Jul 29 '20 at 17:48
  • "The endian of floating point and integer may differ" - I was unaware of this issue, thanks for mentioning it. Is there any straightforward way to detect this? – squirl Jul 29 '20 at 17:48
  • @vktec I think `_Static_assert()` and some `union` magic test can work. But endian FP/integer same-ness is stepping beyond "Detect IEEE-754 floating point representation at compile time" as IEEE does not spec FP nor integer endian. If your real goal is beyond that, perhaps post that question. – chux - Reinstate Monica Jul 29 '20 at 17:53
  • Most machines not using IEEE754 are in museums or junkyards. That standard is 1/3 century old and has been heavily adopted. Granted, the "usual suspects" held out for a long time. – Rick James Jul 29 '20 at 20:02
  • By most "weight" I agree and older big-iron machines with variant FP encodings are are now historic curiosities. But by "most", I am not so sure. There are billions of embedded processors made each year and for the past 20-5 years ago, millions, if not 10s millions of those used variant FP owing to the need for simple FP and no HW FP support. IAC, I suspect OP's final goal remains hidden as the need for "Detect IEEE-754 floating point representation at compile time" makes sense to reduce/simplify regression testing, yet I suspect OP is doing something else. – chux - Reinstate Monica Jul 29 '20 at 20:09
1

As of July 2020, this would still be compiler specific... though C2x intends to change that with the __STDC_IEC_60559_BFP__ macro - see Annex F, section F.2.

It might be noted that:

  • The compiler usually doesn't choose the binary representation. The compiler usually follows the target system's architecture (the chipset instruction design for the CPU / GPU, etc').

  • The use of non-conforming binary representations for floating-point is pretty much a thing of the past. If you're using a modern (or even a moderately modern) system from the past 10 years, you are almost certainly using a conforming binary representation.

Myst
  • 18,516
  • 2
  • 45
  • 67
  • 1
    @KamilCuk ,yes, you're right. I usually paint in broad strokes and missed the details on that one. I updated the answer, I hope it's better now. – Myst Jul 29 '20 at 16:47
  • It seems to me that `__STDC_IEC_60559_BFP__` still requires conformant arithmetic. Am I misreading the draft standard? – squirl Jul 29 '20 at 17:38
  • @vktec the macro also requires the `float` and `double` types to use specific IEEE 754 binary representations (though using the updated specification documents and names). This was the root of your question, right? – Myst Jul 29 '20 at 17:42
  • 1
    Then it has the same issue as `__STDC_IEC_559__`: an implementation that uses the desired *representation* in memory may not implement all operations correctly and may thus not define the macro – squirl Jul 29 '20 at 17:44