This snippet expects to find the bytes in big-endian order, such as on a PowerPC. Much probing via unpack 'b80',... and the like were needed to get myself more fully educated on how the bits were actually laid out.
This version cribs liberally from BrowserUK's snippet.
It's been lightly tested on a G4 PPC. I don't have a way to generate arbitrary 80-bit values, and my source only generates a limited range that runs in the 0..100 or less range.
Update: further testing lead to changes and some simplifications...
With that, the code:
sub IEEE80toIEEE64 { my $ieee80 = shift; # reverse the byte order; this makes it look like an Intel 80-bit +doohickey my $ieee80r = join('', reverse(split //, unpack 'a10', $ieee80)); # now pick it apart my( $discard, $mantissa, $hidden, $exponent, $sign ) = unpack 'a11 a52 a1 a15 a1', unpack 'b80', $ieee80r; # readjust the exponent $exponent = unpack( 'v', pack 'b15', $exponent ) - 16383 + 1023; $exponent = 32767, $mantissa = '0' x 52 if $exponent < 0 or $exponent > 2047; $exponent = unpack 'b11', pack 'v', $exponent; # put it back together my $ieee64r = join('', $mantissa, $exponent, $sign); # reverse the byte order back to Motorola-normal my $ieee64 = join('', reverse(split //, unpack 'a8', pack 'b64', $ +ieee64r)); # ...and convert the binary to a Perl NV return unpack 'd', $ieee64; }
|
|---|