Conversion of Pascal real48 (48-bit float) to C++ double

Started by
10 comments, last by Xentropy 18 years, 10 months ago
I was going to try doing it using the __int64 data type with shifts/and/or etc, however I figured that for file loading speed although it is important, it isn't necessarily worth the effort to go furthur, unless of course you've got 100000 to do. It's also a little more difficult than Extrarius suggests.

The beauty of the method coded thus far is that it doesn't have to know anything about the internals of the double data type, and doesn't have endian issues etc, and is thus probably the most portable.

I have a habbit of always using shifts and ands instead of div and mod for things like this. Most of the time the compiler should optimise it, but not always, or with every compiler, particularly when using signed types. But this point isn't worth debating, I just do it like that always.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Advertisement
Yep, for my purposes the bit manipulation method only profiled marginally faster, since it has to allocate 8 bytes of memory for the __int64 and copy the 6 bytes to the new memory before doing anything else. It is not enough faster to make up for the loss of portability and eaes of understanding and maintenance.

That change to dividing bytes by 256 instead of bits by 2 worked out nicely, though. 3 million conversions took 716ms using the bit-by-bit method and 425ms using byte-by-byte. I tried some other minor tweaks to squeeze out more speed and only managed to make it slightly slower again, so I've nailed it down to a nice method. Considering the single pow() call left at the end of the function to calculate 2^exponent takes about 300ms of that 425ms, there isn't a lot of speed left to squeeze out of the mantissa formulation.

Here's the final fastest code, for future reference (if anyone finds this thread in a search for real48 or something):

double Real48ToDouble(unsigned char realValue[6]) {	if (realValue[0] == 0)		return 0.0; // Null exponent = 0	double exponent = realValue[0] - 129.0;	double mantissa = 0.0;	for (int byte = 1; byte <= 4; byte++) {		mantissa += realValue[byte];		mantissa *= 0.00390625; // mantissa /= 256	}	mantissa += (realValue[5] & 0x7F);	mantissa *= 0.0078125; // mantissa /= 128	mantissa += 1.0;	if (realValue[5] & 0x80) // Sign bit check		mantissa = -mantissa;	return mantissa * pow(2.0, exponent);}


I do the most significant byte calculation outside the loop since that byte also contains the sign bit and thus needs to be treated slightly differently. This code gets the exact same results as the other code in a little over half the time. A 70% speed savings if you don't include the time spent in the final pow. :)

[Edited by - Xentropy on June 20, 2005 4:23:11 PM]

This topic is closed to new replies.

Advertisement