packages feed

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