convert 8 byte real to double

S

scosmo

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

S = sign
E = exponent
M = mantissa

Thank you,

regards,

Camelot
 
B

Ben Bacarisse

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?

This is a little bit under-specified. Do you have a more formal
description of the format for these numbers?
8-byte real:

SEEEEEEE MMMMMMMM MMMMMMMM MMMMMMMM .... MMMMMMMM

If this means what I think, you may have some trouble. With only 7
exponent bits, there are more bits in the mantissa than are used in
the most common IEEE format -- only a few bits, but you don't say what
accuracy you need.

Depending on the details of the format, it may be quote simple to
write C function to convert the data.

<snip>
 
B

BartC

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

S = sign
E = exponent
M = mantissa

Might help to post some actual numbers in this format.

What's the binary representation of 1.0 for example? Or -0.625?

And if stored in memory, is the SEEEEEE in the first byte or the last?

Do you have any code that will translate it to text? That might be one way
of converting.
 
M

Mark Dickinson

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

S = sign
E = exponent
M = mantissa

It's a bit difficult to tell without more information. I'm
assuming that on your target platform doubles are IEEE 754
binary64 format. If the format you're converting *from*
is some relatively recent non-IEEE 754 format (e.g.,
VAX D_floating, VAX G_floating, IBM or Cray) then you should
be able to find functions for converting to and from IEEE 754
on the web. The only one of the listed formats that matches
what you have above is the IBM hex format.

If the floating-point format is something more obscure then
you'll probably need to arm yourself with the necessary
knowledge and then do the conversion yourself: perhaps try
converting your 8 bytes to an unsigned long long (being
careful of endianness issues) to do the required bit
manipulations.

My best guess is that your values are in VAX D_floating format
(perhaps produced by a Fortran program sometime last century?),
and that one of your 'M's above should be an 'E'. Is this
close to the mark, or do I need a better crystal ball?

Do you know any example byte sequences and corresponding
values? That would help with the detective work.

Mark Dickinson
 
R

Richard Bos

What kind of help do you think you need? The C double is described in
IEEE-754.

Nope. It _may_ be, and _if_ your implementation defines __STDC_IEC_559__
it must be, but implementations aren't required to define that constant.
I wouldn't at all be surprised if most do, but then it's still only the
most common double on C implementations, not "the" C double.

Richard
 
M

Mark Dickinson

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.
 
B

Barry Schwarz

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

S = sign
E = exponent
M = mantissa

If this is the standard IBM hex floating point format, there is no
standard function but it is easy enough to convert. The implied hex
point is to the left of the first M and there is no implied leading
digit like some other formats use. The unbiased value of the exponent
is obtained by subtracting 64 from the unsigned EEEEEEE. The base for
the exponent is 16 so it tells you how many nybbles to the left or
right the implied point should move. The value 0x4118000000000000 is
1.5 while 0xcC212400000000000 is -18.25.

If you use an unsigned char* pointing at the start then the absolute
value can be computed simply as
value = pow(16,(ptr[0]&0x7f)-64) *
( ptr[1]/pow(256,1) + ptr[2]/pow(256,2) + ... +
ptr[7]/pow(256,7));
Then you test the sign bit and make value negative if necessary.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,272
Latest member
MaricruzDu

Latest Threads

Top