Reputation: 20838
I need to decode a timestamp encoded as an IEEE double
(from iOS NSTimeInterval
) and stored in a 8 byte array, so that I can use ctime
to print out the timestamp in a human readable format. This is trivial on most systems, but not on mine.
Example: on iOS side
uint8_t data[8];
double x = 3.14;
memcpy(data,&x,8);
I'm running on a MSP430F5438A and I need to use the COFF ABI to link with 3rd part libraries. TI's Code Composer does not support 64-bit floating point types (IEEE double) if you use the COFF ABI. It treats double
the same as float
(ie single precision).
These don't work.
uint8_t data[8];
double x;
memcpy(&x,data,8);
or
x = *(double*)data;
or
union {
uint8_t data[8];
double d;
} x;
memcpy(x.data,data,8);
I just get gibberish, because double
is only 4 bytes using Code Composer. I need a way to directly convert the uint8_t[8]
data (which is a legitimate IEEE double precision value) into an integer value.
Upvotes: 0
Views: 1407
Reputation: 20838
This will convert an integral double
to an exact uint32_t
(as long as there is no overflow, up to 2^32-1). It will not work if the double is Nan or Inf, but that is unlikely.
static unsigned long ConvertDoubleToULong(void* d)
{
unsigned long long x;
unsigned long long sign ;
long exponent;
unsigned long long mantissa;
memcpy(&x,d,8);
// IEEE binary64 format (unsupported)
sign = (x >> 63) & 1; // 1 bit
exponent = ((x >> 52) & 0x7FF); // 11 bits
mantissa = (x >> 0) & 0x000FFFFFFFFFFFFFULL; // 52 bits
exponent -= 1023;
mantissa |= 0x0010000000000000ULL; // add implicit 1
int rshift = 52 - exponent;
if (rshift > 52) {
x = 0;
} else if (rshift >=0) {
x = mantissa >> rshift;
} else {
x = 0x7FFFFFFF;
}
if (sign == 0) {
return x;
} else {
return -x;
}
}
Upvotes: 1