views:

453

answers:

2

In the stdint.h (C99), boost/cstdint.hpp, and cstdint (C++0x) headers there is, among others, the type int32_t.

Are there similar fixed-size floating point types? Something like float32_t?

+11  A: 

Nothing like this exists in the C or C++ standards at present. In fact, there isn't even a guarantee that float will be a binary floating-point format at all.

Some compilers guarantee that the float type will be the IEEE-754 32 bit binary format. Some do not. In reality, float is in fact the IEEE-754 single type on most non-embedded platforms, though the usual caveats about some compilers evaluating expressions in a wider format apply.

There is a working group discussing adding C language bindings for the 2008 revision of IEEE-754, which could consider recommending that such a typedef be added. If this were added to C, I expect the C++ standard would follow suit... eventually.

Stephen Canon
I hope the working group will bind C/C++ to IEEE-754. So if you want portability you can get it more easily, and if you don't need it you can keep using the old platform dependent types.
Pietro
Regardless of IEEE-754 or not, it still won't prevent endian portability problems.
Mark B
@Pietro: changing the language won't affect your hardware compatibility, it would only preclude some hardware from compliance. How would an IEEE FP guarantee help portability?
Potatoswatter
@Potatoswatter: It would encourage hardware vendors to provide compliant solutions. If part a supports standard C without needing soft-float library hacks and part b doesn't, that's a market advantage for part a.
Stephen Canon
@Stephen: Speculation. I don't think hardware vendors need any more encouragement about that. It isn't the language committee's job to twist their arm. Hardware can be faster if fewer restrictions are made on it.
Potatoswatter
@Potatoswatter: (Almost) no one cares about the speed of hardware. We care about the speed of software running on the hardware. Software can be faster if the hardware it is running on is held to standards and the software doesn't need to detect and patch up 15 different special cases depending on what platform it is running on.
Stephen Canon
@Stephen: The class of programs amenable to C is much broader than the class of programs sensitive to the FP format and environment. If a platform has already decided to be non-754 compliant, it's probably niche enough to fail other standards as well. Whatever value C compliance has stands apart from 754… they are both brand names. But the true value of a C memory model and 754 numerics are that they are practical ways of doing things! Standards shouldn't be treated as brand-names.
Potatoswatter
How on Earth would you get *better* portability by preventing your code from compiling on a number of niche architectures?Either you rely on floats being IEEE, in which case your code will *already* run on every IEEE-compliant implementation and nothing else, or you don't, in which case your code will run on a wider range of systems. If C++ *guaranteed* IEEE compliance, your code wouldn't magically get more portable, you'd just rule out that it could *ever* run on those non-compliant architectures.Your logic is completely backwards.
jalf
+5  A: 

If you want to know whether your float is the IEEE 32-bit type, check std::numeric_traits<float>::is_iec559. It's a compile-time constant, not a function. If true, then assume away. If false, you might be able to find a platform flag that guarantees IEEE formatting: it might only be false because of operating restrictions.

EDIT: I just poked at my computer (OS X x64) for a bit and discovered that is_iec559 is true for long double despite a dodgy memory layout: the number is rotated by 16 bits, then put in little-endian 64-bit halves arranged in big-endian order. The C++ standard, even C++0x, doesn't define what IEEE compliance means or even which revision of IEEE 754 it's referring to. So, be careful :v( .

EDIT 2: is_iec559 is true for long double on Mac OS X at least despite being the non-IEEE 80-bit Intel format. So indeed, that sucks.

EDIT 3: Apparently the confusion is exacerbated by C99 §F.2/1 footnote 307,

307) ‘‘Extended’’ is IEC 60559’s double-extended data format. Extended refers to both the common 80-bit and quadruple 128-bit IEC 60559 formats.

Which is a direct self contradiction. If ‘‘Extended’’ is IEC 60559’s double-extended data format. then refers to both is obviously impossible. It's fairly obvious that one format is proper IEEE and the other is an anachronism, but I'm guessing that Intel corrupted the standard to grandfather in their hardware. Yecchh. There's your language standard encouraging hardware improvement!

On the other hand, C99 defines 754 compliance as a binary issue: either the entire implementation complies or it doesn't. Either Intel 80 is 754 or the machine can't ever use Intel 80 or the system is non-compliant. C++ provides an answer to the specific question of whether the 80-bit format comes from 754, and carrying over C99's generalizing seems inappropriate.

Potatoswatter
The `long double` format on OS X (both 32-bit and 64-bit Intel) is exactly the IEEE-754 double extended format stored in little-endian order. Nothing funky about it at all. Bytes 0-7 hold the significand field, and bytes 8 and 9 hold the exponent and sign fields.
Stephen Canon
@Stephen: that's good news :v) . Does that agree with the numbers I posted?
Potatoswatter
Remember that double extended (unlike the other 754 formats) has an explicit leading significand bit, so `5.0L` has a significand of `a000000000000000`. Its unbiased exponent is +2, and the double extended exponent bias is `3fff`, so the biased exponent for 5.0L is `4001`. The actual byte pattern when stored in little-endian order is `00 00 00 00 00 00 00 a0 01 40`, and if you view that as two little-endian 64-bit integers, you will see exactly what you observed.
Stephen Canon
(*) double extended as implemented by Intel in hardware, that is. The double extended format isn't actually pinned down the way the other two basic formats of IEEE-754 (1985) are.
Stephen Canon
@Stephen: I'm pretty sure that `4001` in little-endian is `01 40 00 00 ...` If nothing else, the least significant byte comes first. I do expect the sequence `a0 01 40` to appear somewhere in the number (if they only performed a rotation) but I don't think you've explained why `a0` and `01 40` are in completely separate halves.
Potatoswatter
`01 40` is exactly what I wrote (the bytes above `40` aren't part of the number, so they need not be zero). Why would `a0` be in the same half as `01 40`? `a0` is the high-order byte of the significand (bits 56:63) and so it should (and does) appear in the seventh byte of the encoding, which is in the low-addressed 64-bit chunk of memory. I'm also not sure what you mean by "rotation"; no rotation is happening here.
Stephen Canon
@Stephen: the encoding is sixteen bytes long, not eight. The sign+exponent are 16 bits so the top byte of the significand should be at 104:111 or little-endian byte 13.
Potatoswatter
No. The Intel double extended type is *ten* bytes long, which is what I've been saying all along.
Stephen Canon
@Stephen: Oh, the 80 bit format. That clarifies everything. Then this is all irrelevant because that's completely nonstandard. The only IEEE format larger than 64 bits is 128 bits: http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format . I was confused because `sizeof(long double) == 16`.
Potatoswatter
Now I looked at the unused trailing bits. The reported size is 16, the first 10 bytes are used, the next 2 bytes are zeroed out, and the final 4 bytes are left untouched. I suppose that's specified by Intel, and the padding is supposed to make thing easier.
Potatoswatter
"The only IEEE format larger than 64 bits is 128 bits" is false. The Intel 80-bit types satisfies the specification for the IEEE-754 *double extended* type, and is, in fact, an IEEE-754 type.
Stephen Canon
Also, Intel specifies only the 10 bytes that comprise the number. The ABI imposes some alignment requirements when they are passed between functions, and the compiler can do whatever it wants with the padding bits required to satisfy the ABI (including zeroing them, zeroing some of them, or leaving them untouched).
Stephen Canon
@Stephen: IEEE 754 defines "single extended" and "double extended" as all types capable of representing a superset of single and double, respectively. It says nothing about 80-bit, and essentially any extension type implemented by an FPU that also supports standard types will fall into that category. See the defect report I just submitted to comp.std.c++ and we might as well continue discussion there.
Potatoswatter