Hello,
does anybody know if is there any function library in C that could
help me to convert a 8 byte real floating point representation into a
C double format?
8-byte real:
SEEEEEEE MMMMMMMM MMMMMMMM MMMMMMMM .... MMMMMMMM
After a bit of googling, I'm going to retract my guess and
guess instead that the above really is IBM hex format. It
seems this format is used quite frequently for various
data formats (SAS transport files, GDSII files, ...).
In that case, something like the following code should
be good enough to convert from IBM to IEEE 754.
#include <math.h>
#include <stdint.h>
#define SIGN_MASK (1ULL << 63)
#define EXP_MASK ((1ULL << 63) - (1ULL << 56))
#define EXP_SHIFT 56
#define SIG_MASK ((1ULL << 56) - 1)
double ibm2ieee(unsigned char *s) {
uint64_t x;
int exp, negate;
double absval;
x = *(uint64_t *)s;
negate = (x & SIGN_MASK) != 0;
exp = (int)((x & EXP_MASK) >> EXP_SHIFT);
absval = ldexp((double)(x & SIG_MASK), 4*exp-312);
return negate ? 0.0-absval : absval;
}
Notes:
(1) This assumes that the incoming 8-byte format
and the native uint64_t format have the same endianness.
If not, you'll need to reverse the 8-byte sequences
by hand.
(2) It also assumes you're content with the way
your C implementation chooses to round integer to
double conversions. It's probably round-half-to-even,
but the standards leave the choice up to the
implementation.
(3) The use of 0.0-absval instead of -absval is
deliberate: the IBM format allows the bit pattern
that would correspond to a 'negative' zero, but
doesn't distinguish negative and positive zeros in
practice, so both should be converted to 0.0.
(4) The conversion in this direction is particularly
easy because the IBM format doesn't have infinities
or nans, and its exponent range is smaller than IEEE's, so
there's no need to worry about overflow or underflow.
Conversion in the other direction would be more involved.