Search code examples
c++memorynetwork-programmingtypesieee-754

Are there any modern platforms with non-IEEE C/C++ float formats?


I am writing a video game, Humm and Strumm, which requires a network component in its game engine. I can deal with differences in endianness easily, but I have hit a wall in attempting to deal with possible float memory formats. I know that modern computers have all a standard integer format, but I have heard that they may not all use the IEEE standard for floating-point integers. Is this true?

While certainly I could just output it as a character string into each packet, I would still have to convert to a "well-known format" of each client, regardless of the platform. The standard printf() and atod() would be inadequate.

Please note, because this game is a Free/Open Source Software program that will run on GNU/Linux, *BSD, and Microsoft Windows, I cannot use any proprietary solutions, nor any single-platform solutions.

Cheers,
Patrick


Solution

  • I think it is safe to assume that each platform has an implementation of the IEEE-754 spec that you can rely on. However, even if they all implement the same spec, there is no guarantee that each platform has the exact same implementation, has the same FP control flags set, does the same optimizations, or implements the same non-standard extensions. This makes floating-point determinism very hard to control and somewhat unreliable to use for this kind of thing (where you'll be communicating FP values over the network).

    For more information on that; read http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/

    Another problem to tackle is handling clients that don't have a floating-point unit; most of the time these will be low-end CPUs, consoles or embedded devices. Make sure to take this into account if you want to target them. FP emulation can be done but tends to be very slow on these devices so you'll have to get a hang of doing fixed-point calculations. Be advised though: writing elaborate classes to abstract floating point and fixed point calculations to the same code sounds like a plan but on most devices it isn'ta good one. It doesn't allow you to squeeze out the maximum precision and performance when dealing with fixed point values.

    Yet another problem is handling the endianness of the floating point values because you cannot just swap bytes and stack 'm in a floating point register again (the bytes might get a different meaning, see http://www.dmh2000.com/cpp/dswap.shtml on that).

    My advice would be to convert the floats to fixed point intermediate values, do an endian correction if needed and transmit that. Also, don't assume that two floating point calculations on different machines will yield the same results; they don't. However, floating point implementations other than IEEE-754 are rare. For example GPUs tended to use fixed point, but are more likely to have a subset of IEEE-754 these days because they don't want to deal with division-by-zero exceptions but they will have extensions for half-floats that fit in 16 bits.

    Also, realize that there are libraries out there that have already solved this problem (sending low-level data formats in a gaming context) for you. One such library is RakNet: specifically, its BitStream class is designed to send these kinds of data reliably to different platforms while keeping the overhead to a minimum. For example, RakNet goes through quite some trouble not to waste any bandwidth on sending strings or vectors.