luachunk-0.1.0.0: src/Scripting/Lua/Chunk/IEEE754.hs
{-# LANGUAGE MagicHash #-}
{- Fast Parsing and writing IEEE Double values to/from ByteStrings -}
{- NOTE: This implementation is GHC specific -}
{- For portable (50-100x slower) versions, use data-binary-ieee754 -}
module Scripting.Lua.Chunk.IEEE754
( encodeIEEEDouble
, decodeIEEEDouble
) where
import CustomPrelude
import qualified Data.ByteString.Lazy as BS
import Data.Binary.Put (runPut, putWord64be, putWord64le)
import Data.Binary.Get (runGet, getWord64be, getWord64le)
import GHC.Prim (unsafeCoerce#)
import GHC.Types (Double(D#))
import GHC.Word (Word64(W64#))
-- | Read a 64-bit double in supplied endianness format
decodeIEEEDouble :: Bool -> BS.ByteString -> Double
decodeIEEEDouble littleEndian = word64ToDouble . bytestringToWord64 littleEndian
-- | Write a 64-bit double to supplied endianness format
encodeIEEEDouble :: Bool -> Double -> BS.ByteString
encodeIEEEDouble littleEndian = word64ToBytestring littleEndian . doubleToWord64
-- Conversion to and from IEE754 representation for numbers
-- Assumes that Double values are stored in IEEE 754 format (always true for GHC)
-- and that the endianness of the word matches that of the system
word64ToDouble :: Word64 -> Double
word64ToDouble (W64# x) = D# (unsafeCoerce# x)
doubleToWord64 :: Double -> Word64
doubleToWord64 (D# x) = W64# (unsafeCoerce# x)
-- Bytestring <-> Word64 conversion functions
bytestringToWord64 :: Bool -> BS.ByteString -> Word64
bytestringToWord64 littleEndian = runGet $ if littleEndian then getWord64le else getWord64be
word64ToBytestring :: Bool -> Word64 -> BS.ByteString
word64ToBytestring littleEndian = runPut . if littleEndian then putWord64le else putWord64be