Two handy functions

Mark Smith mark at maseurope.net
Mon Jan 23 19:16:26 EST 2006


These two functions are from Mark Waddingham (I checked with him that  
it was ok to make them public), the result of a 'silver support  
incident' (cheap at the price). Probably not everyday must-haves, but  
ended my quest to read the sample rate from AIF files.

They convert ieee 10 byte floats to ieee 8 byte floats (which  
binaryDecode can cope with) and back again.

Mark



------------------------------------------------------------------------ 
----------------------------
-- Take a sequence of 10-bytes encoding an extended number, and return
-- a sequence of 8-bytes encoding a double number

function ieeeExtendedToDouble pExtended
   local tExtendedSign, tExtendedExponent, tExtendedMantissa,  
tExtendedBits
   local tDoubleExponent, tDoubleMantissa, tDoubleBits

   if the length of pExtended is not 10 then
     throw "ieeeerr,Extended number must be 10 bytes long"
   end if

   -- Step 1: Split the extended number up
   get binaryDecode("B80", pExtended, tExtendedBits)
   put char 1 of tExtendedBits into tExtendedSign
   put char 2 to 16 of tExtendedBits into tExtendedExponent
   put char 17 to 80 of tExtendedBits into tExtendedMantissa

   -- Step 2: Truncate the fields

   -- The exponent is the trickiest because it is stored as a number  
relative to
   -- the smallest possible exponent which in the case of an extended  
number is
   -- -16383.
   -- Therefore, we take the following steps:
   --   . Make sure we have 16-binary digits
   --   . Encode as two binary bytes
   --   . Decode as a 2-byte integer, most-significant byte first  
(network byte-order)
   --   . Adjust and clamp to the double exponent range
   local tNumericExponent
   get binaryDecode("n", binaryEncode("B16", "0" &  
tExtendedExponent), tNumericExponent)
   subtract 16383 from tNumericExponent
   put max(min(tNumericExponent, 2046), -2046) into tNumericExponent

   -- IEEE Doubles actually have a normalization requirement for  
representation.
   -- The Mantissa is taken to be 1.F where F is the binary fraction  
encoded in the
   -- number. This seems subtlety different from the extended format,  
which has no
   -- such requirement (it appears). Therefore, we have to find the  
leading '1' in the
   -- extended mantissa and adjust the exponent accordingly.
   -- Of course, if there is no leading 1, then the number is 0
   local tLeadingOne

   -- Find the leading one, and return zero if there is none
   put offset("1", tExtendedMantissa) into tLeadingOne
   if tLeadingOne is 0 then
     return 0
   end if

   -- Extract 52-bits for the mantissa, and pad with zeros if we  
don't have enough
   put char tLeadingOne + 1 to tLeadingOne + 1 + 52 of  
tExtendedMantissa into tDoubleMantissa
   repeat while the length of tDoubleMantissa < 52
     put "0" after tDoubleMantissa
   end repeat

   -- Adjust the exponent
   subtract tLeadingOne - 1 from tDoubleExponent

   -- Finish encoding the exponent
   get binaryDecode("B16", binaryEncode("n", 1023 +  
tNumericExponent), tDoubleExponent)
   put char 6 to 16 of tDoubleExponent into tDoubleExponent

   -- Now reconstruct the double as bits
   put tExtendedSign & tDoubleExponent & tDoubleMantissa into  
tDoubleBits

   -- And perform the final encoding
   return binaryEncode("B64", tDoubleBits)
end ieeeExtendedToDouble


------------------------------------------------------------------------ 
----------------------------
-- Take a sequence of 8 bytes encoding a double number, and return a
-- sequence of 10-bytes encoding an extended number

function ieeeDoubleToExtended pDouble
   local tSign, tExtendedExponent, tExtendedMantissa, tExtendedBits
   local tDoubleExponent, tDoubleMantissa, tDoubleBits

   if the length of pDouble is not 8 then
     throw "ieeeerr,Double number must be 8 bytes long"
   end if

   get binaryDecode("B64", pDouble, tDoubleBits)
   put char 1 of tDoubleBits into tSign
   put char 2 to 12 of tDoubleBits into tDoubleExponent
   put char 13 to 64 of tDoubleBits into tDoubleMantissa

   local tNumericExponent
   get binaryDecode("n", binaryEncode("B16", "00000" &  
tDoubleExponent), tNumericExponent)
   if tNumericExponent is 0 then
     put 0 into tNumericExponent
     put tDoubleMantissa into tExtendedMantissa
   else
     add 16383 - 1023 to tNumericExponent
     put "1" & tDoubleMantissa into tExtendedMantissa
   end if

   repeat while the length of tExtendedMantissa < 64
     put "0" after tExtendedMantissa
   end repeat

   get binaryDecode("B16", binaryEncode("n", tNumericExponent),  
tExtendedExponent)
   put char 2 to 16 of tExtendedExponent into tExtendedExponent

   put tSign & tExtendedExponent & tExtendedMantissa into tExtendedBits

   return binaryEncode("B80", tExtendedBits)
end ieeeDoubleToExtended

------------------------------------------------------------------------ 
----------------------------



More information about the use-livecode mailing list