0

Swapping a bunch of bytes seems an easy job, but I always prefer to use libraries when they are available. So I stumble across Boost.Endian and I was surprised when I discover that it deals with intergers but not floating points. What is so special about floating point endianness? (I read Boost.Endian exaplantion but it doesn't fulfill my curiosity).

In particular I would like to understand this: if Boost.Endian already provides functions for swapping 4 and 8 bytes integers why not simply apply those functions to floats and doubles?

luca
  • 7,178
  • 7
  • 41
  • 55
  • 1
    in short there are many standards of floating point numbers and C++ standard do not define which should be used. There are differences not only between platforms, but also between compilers (for example size of `double` can be for different compiler on same platform). Boost doesn't have required functionality, but `QDataStream` has and Protobuf library should have it. – Marek R Feb 02 '21 at 09:57
  • 1
    In short, in common modern C++ implementations, rearranging the bits of an integer gives you another normal integer value. Rearranging the bits of a floating-point number does not always; it may produce a NaN, particularly a signaling NaN. C++ implementations do not always preserve the bits of NaNs when handling them, possibly even where we would expect a simple copy. Therefore the rearranged bits of a floating-point number are not safe to keep in an object with floating-point type. – Eric Postpischil Feb 02 '21 at 11:39
  • 1
    Which shows that bits rearranged for endianness should not be held in their normally typed object—even when we have the rearranged bits of an `int`, they may represent a valid `int` value, but they do not represent the value of the original `int`, generally. So we should not allow them to be interpreted as an `int`. When an object is converted to or received as bits in some non-native endianness or byte ordering, it ought to be held in a container of bits and never interpreted for its value. This is true for integers, floating-point values, and other types… – Eric Postpischil Feb 02 '21 at 11:42
  • 1
    … Functions to convert between native types like `int` or `float` and some specific endianness ought to take the native type as input and produce a bit-container type as output, or vice-versa. Converting `int` to `int` “in-place” or even “in type” is a kludge. It is just easier to get away with with integers than with floating-point. – Eric Postpischil Feb 02 '21 at 11:43
  • @EricPostpischil - you should post your comments as an answer, shouldn't you? – luca Feb 02 '21 at 11:50
  • 1
    @luca: Sorry, I started to look at the Boost documentation, and it would take too long (I have to go shovel snow when the sun rises) to look through the documentation to figure out whether Boost is providing native-to-container conversions as well as native-to-kludged-native conversions and also to confirm the issues I have related. I like to have a certain level of assured quality before I write an answer (not that I always meet that goal). So I just use comments to convey the information. Somebody else can use it as a basis for research, if they desire. – Eric Postpischil Feb 02 '21 at 11:57

1 Answers1

4

So I stumble across Boost.Endian and I was surprised when I discover that it deals with intergers but not floating points. What is so special about floating point endianness?

The documentation explains why:

An attempt was made to support four-byte floats and eight-byte doubles, limited to IEEE 754 (also known as ISO/IEC/IEEE 60559) floating point and further limited to systems where floating point endianness does not differ from integer endianness. Even with those limitations, support for floating point types was not reliable and was removed. For example, simply reversing the endianness of a floating point number can result in a signaling-NAN. For all practical purposes, binary serialization and endianness for integers are one and the same problem. That is not true for floating point numbers, so binary serialization interfaces and formats for floating point does not fit well in an endian-based library.

So, the problems are not related to the language, but to the underlying floating point format that the system uses.

The signaling-NAN mentioned as an example for example causes on POSIX systems the process to abort by default. This is typically an undesirable outcome when changing endianness.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Thanks, I saw it but it is not clear to me. That's why I posted the question in here. Could you elaborate on the boost.endian explanation? – luca Feb 02 '21 at 10:08
  • 1
    @luca I added elaboration. – eerorika Feb 02 '21 at 10:17
  • @eerorika I still don't understand - why not support at least buffer types for floating types? They are stored as arrays of `char` internally, so there is no place where floating-type variable is in non-native order. – peper0 Apr 16 '21 at 15:04