cereal-ieee754-0.1: src/Data/Serialize/IEEE754.hs
{-# LANGUAGE FlexibleContexts #-}
-- | Functions for reading, writing and converting IEEE 754 floating
-- point numbers.
--
-- Conversions use 'STUArray' and the 'ST' monad to reinterpret bytes
-- and get /what we assume to be/ the IEEE 754 binary representation
-- of single and double precision floating point numbers.
module Data.Serialize.IEEE754 (
-- * Big-endian reads
getFloat32be
, getFloat64be
-- * Little-endian reads
, getFloat32le
, getFloat64le
-- * Host-endian, unaligned reads
, getFloat32host
, getFloat64host
-- * Little-endian writes
, putFloat32le
, putFloat64le
-- * Big-endian writes
, putFloat32be
, putFloat64be
-- * Host-endian, unaligned writes
, putFloat32host
, putFloat64host
-- * Conversions
, floatToWord
, wordToFloat
, doubleToWord
, wordToDouble
) where
import Control.Applicative ((<$>))
import Data.Array.ST (newArray, castSTUArray, readArray, MArray, STUArray)
import Data.Serialize
import Data.Word (Word32, Word64)
import GHC.ST (runST, ST)
------------------------------------------------------------------------
-- Get
-- | Read a 32-bit float in little endian format
getFloat32le :: Get Float
getFloat32le = wordToFloat <$> getWord32le
-- | Read a 64-bit float in little endian format
getFloat64le :: Get Double
getFloat64le = wordToDouble <$> getWord64le
-- | Read a 32-bit float in big endian format
getFloat32be :: Get Float
getFloat32be = wordToFloat <$> getWord32be
-- | Read a 64-bit float in big endian format
getFloat64be :: Get Double
getFloat64be = wordToDouble <$> getWord64be
-- | Read a 32-bit float in native host order and host endianness
getFloat32host :: Get Float
getFloat32host = wordToFloat <$> getWord32host
-- | Read a 64-bit float in native host order and host endianness
getFloat64host :: Get Double
getFloat64host = wordToDouble <$> getWord64host
------------------------------------------------------------------------
-- Put
-- | Write a 32-bit float in little endian format
putFloat32le :: Putter Float
putFloat32le = putWord32le . floatToWord
-- | Write a 64-bit float in little endian format
putFloat64le :: Putter Double
putFloat64le = putWord64le . doubleToWord
-- | Write a 32-bit float in big endian format
putFloat32be :: Putter Float
putFloat32be = putWord32be . floatToWord
-- | Write a 64-bit float in big endian format
putFloat64be :: Putter Double
putFloat64be = putWord64be . doubleToWord
-- | Write a 32-bit float in native host order and host endianness
putFloat32host :: Putter Float
putFloat32host = putWord32host . floatToWord
-- | Write a 64-bit float in native host order and host endianness
putFloat64host :: Putter Double
putFloat64host = putWord64host . doubleToWord
------------------------------------------------------------------------
-- Conversions
-- | Interpret a 32-bit word as a 32-bit float.
wordToFloat :: Word32 -> Float
wordToFloat x = runST (cast x)
-- | Interpret a 32-bit float as a 32-bit word.
floatToWord :: Float -> Word32
floatToWord x = runST (cast x)
-- | Interpret a 64-bit word as a 64-bit float.
wordToDouble :: Word64 -> Double
wordToDouble x = runST (cast x)
-- | Interpret a 64-bit float as a 64-bit word.
doubleToWord :: Double -> Word64
doubleToWord x = runST (cast x)
{-# INLINE cast #-}
cast :: (MArray (STUArray s) a (ST s),
MArray (STUArray s) b (ST s)) => a -> ST s b
cast x = newArray (0 :: Int, 0) x >>= castSTUArray >>= flip readArray 0