$ ./a.out
in.val = 86.3115158 -> Its a valid floating point number
out1.val = nan -> Swapped it and now its a NaN! That's OK swap it back.
out2.val = 86.4365158 -> What, its not the same number???
in.m = {0x7f, 0x9f, 0xac, 0x42} -> Notice the second number is 0x9f
out1.m = {0x42, 0xac, 0xdf, 0x7f} -> But in the flipped version it became 0xdf?
out2.m = {0x7f, 0xdf, 0xac, 0x42} -> So, this can't be the same number.
The error comes from when I swaped the first number 86.3115158, its flipped version produced a NaN.
That would be OK if the flipped version just returned the same number, but that is not the case!
I surmised that when I assign the NaN value to another float, the 'a' bit in the register was
changed to indicate a Quiet NaN http://en.wikipedia.org/wiki/NaN#Floating_point
So, I changed the byteSwap function to not return the result but just modify the input.
in.val = 86.3115158 -> Its a valid float.
in.val = nan -> Swapped it and now its a NaN!
in.val = 86.3115158 -> Swap it back and its OK!
Because I don't do an assignment to a float it works.
$
#include <string>
#include <iostream>
#include <iomanip>
//-------------------------------------------------------------------------
// Swap stuff
template <class T> inline void byteSwap2(T& v) {
union {
T val;
char m[sizeof(T)];
} in, tmp;
in.val = v;
for (unsigned int j(1); j <= sizeof(T); j++) {
tmp.m[j-1] = in.m[sizeof(T)-j];
}
memcpy(&v,tmp.m,sizeof(T));
return;
}
//-------------------------------------------------------------------------
// Swap stuff
template <class T> inline T byteSwap(const T& v) {
unsigned int j(1);
union {
T val;
char m[sizeof(T)];
} in, tmp;
in.val = v;
//----------------------------------------------------------------------
// Swap the data
for (; j <= sizeof(T); j++)
tmp.m[j-1] = in.m[sizeof(T)-j];
return (tmp.val);
}
//-------------------------------------------------------------------------
// Print stuff
void printIt(const char *name,char o[],int s){
unsigned int j(0);
std::cout << name << " = {";
for (; j<s-1; j++)
std::cout << std::hex << std::showbase << int(o[j]&0xff) << ", ";
std::cout << int(o[j]&0xff) << "}";
}
int main(){
unsigned int j(0);
union {
float val;
char m[sizeof(float)];
} in,out1,out2;
//----------------------------------------------------------------------
// I need a specific value for the floating point number, so in order
// to get it exact I load it like this
in.m[0] = 0x7f, in.m[1] = 0x9f, in.m[2] = 0xac, in.m[3] = 0x42;
//----------------------------------------------------------------------
// in.val is a valid floating point number
std::cout << std::setprecision(9) << "in.val = " << in.val;
std::cout << " -> Its a valid floating point number" << std::endl;
//----------------------------------------------------------------------
// Swap the number
out1.val = byteSwap(in.val);
//----------------------------------------------------------------------
// Print out result, its a NaN?
std::cout << "out1.val = " << out1.val;
std::cout << " -> Swapped it and now its a NaN! That's OK swap it back." << std::endl;
//----------------------------------------------------------------------
// That OK, swap it back
out2.val = byteSwap(out1.val);
std::cout << "out2.val = " << out2.val;
std::cout << " -> What, its not the same number???" << std::endl;
printIt("in.m ", in.m,sizeof(out1.m));
std::cout << " -> Notice the second number is 0x9f" << std::endl;
printIt("out1.m", out1.m,sizeof(out1.m));
std::cout << " -> But in the flipped version it became 0xdf?" << std::endl;
printIt("out2.m", out2.m,sizeof(out1.m));
std::cout << " -> So, this can't be the same number." << std::endl;
std::cout << "\nThe error comes from when I swaped the first number "
<< in.val << ", its flipped version produced a NaN.\n"
<< "That would be OK if the flipped version just returned the"
<< " same number, but that is not the case!\n"
<< "I surmised that when I assign the NaN value to another "
<< "float, the 'a' bit in the register was\n"
<< "changed to indicate a Quiet NaN http://en.wikipedia.org/wiki/NaN#Floating_point\n\n"
<< "\nSo, I changed the byteSwap function to not return the "
<< "result but just modify the input." << std::endl;
//----------------------------------------------------------------------
// Print out valid floating point number
std::cout << "in.val = " << in.val;
std::cout << " -> Its a valid float." << std::endl;
//----------------------------------------------------------------------
// Swap the number
byteSwap2(in.val);
//----------------------------------------------------------------------
// Print out result, its a NaN?
std::cout << "in.val = " << in.val;
std::cout << " -> Swapped it and now its a NaN!" << std::endl;
//----------------------------------------------------------------------
// Swap the number
byteSwap2(in.val);
//----------------------------------------------------------------------
// Print out result, its correct
std::cout << "in.val = " << in.val;
std::cout << " -> Swap it back and its OK!" << std::endl;
std::cout << "\nBecause I don't do an assignment to a float it works." << std::endl;
return 0;
}