packages feed

data-binary-ieee754 0.2 → 0.3

raw patch · 2 files changed

+104/−64 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Data.Binary.IEEE754: type BitCount = Int
- Data.Binary.IEEE754: type Exponent = Int
- Data.Binary.IEEE754: type Fraction = Integer
+ Data.Binary.IEEE754: data BitCount
+ Data.Binary.IEEE754: data ByteCount
+ Data.Binary.IEEE754: data Exponent
+ Data.Binary.IEEE754: data Fraction
+ Data.Binary.IEEE754: instance Bits Exponent
+ Data.Binary.IEEE754: instance Bits Fraction
+ Data.Binary.IEEE754: instance Enum BitCount
+ Data.Binary.IEEE754: instance Enum ByteCount
+ Data.Binary.IEEE754: instance Enum Exponent
+ Data.Binary.IEEE754: instance Enum Fraction
+ Data.Binary.IEEE754: instance Eq BitCount
+ Data.Binary.IEEE754: instance Eq ByteCount
+ Data.Binary.IEEE754: instance Eq Exponent
+ Data.Binary.IEEE754: instance Eq Fraction
+ Data.Binary.IEEE754: instance Integral BitCount
+ Data.Binary.IEEE754: instance Integral ByteCount
+ Data.Binary.IEEE754: instance Integral Exponent
+ Data.Binary.IEEE754: instance Integral Fraction
+ Data.Binary.IEEE754: instance Num BitCount
+ Data.Binary.IEEE754: instance Num ByteCount
+ Data.Binary.IEEE754: instance Num Exponent
+ Data.Binary.IEEE754: instance Num Fraction
+ Data.Binary.IEEE754: instance Ord BitCount
+ Data.Binary.IEEE754: instance Ord ByteCount
+ Data.Binary.IEEE754: instance Ord Exponent
+ Data.Binary.IEEE754: instance Ord Fraction
+ Data.Binary.IEEE754: instance Real BitCount
+ Data.Binary.IEEE754: instance Real ByteCount
+ Data.Binary.IEEE754: instance Real Exponent
+ Data.Binary.IEEE754: instance Real Fraction
+ Data.Binary.IEEE754: instance Show BitCount
+ Data.Binary.IEEE754: instance Show ByteCount
+ Data.Binary.IEEE754: instance Show Exponent
+ Data.Binary.IEEE754: instance Show Fraction
- Data.Binary.IEEE754: bias :: (Integral a, Integral b) => a -> b -> a
+ Data.Binary.IEEE754: bias :: Exponent -> BitCount -> Exponent
- Data.Binary.IEEE754: putFloat32be :: (RealFloat a) => a -> Put
+ Data.Binary.IEEE754: putFloat32be :: Float -> Put
- Data.Binary.IEEE754: putFloat32le :: (RealFloat a) => a -> Put
+ Data.Binary.IEEE754: putFloat32le :: Float -> Put
- Data.Binary.IEEE754: putFloat64be :: (RealFloat a) => a -> Put
+ Data.Binary.IEEE754: putFloat64be :: Double -> Put
- Data.Binary.IEEE754: putFloat64le :: (RealFloat a) => a -> Put
+ Data.Binary.IEEE754: putFloat64le :: Double -> Put

Files

Data/Binary/IEEE754.hs view
@@ -1,3 +1,20 @@+{- Copyright (C) 2009 John Millikin <jmillikin@gmail.com>+   +   This program is free software: you can redistribute it and/or modify+   it under the terms of the GNU General Public License as published by+   the Free Software Foundation, either version 3 of the License, or+   any later version.+   +   This program is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+   GNU General Public License for more details.+   +   You should have received a copy of the GNU General Public License+   along with this program.  If not, see <http://www.gnu.org/licenses/>.+-}++{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Data.Binary.IEEE754 ( 	-- * Parsing 	 parseFloatBE, parseFloatLE@@ -32,9 +49,10 @@ 	,Exponent 	,Fraction 	,BitCount+	,ByteCount ) where -import Data.Bits ((.&.), (.|.), shiftL, shiftR)+import Data.Bits ((.&.), (.|.), shiftL, shiftR, Bits) import Data.Word (Word8) import Data.List (foldl') @@ -53,83 +71,83 @@ parseFloatLE = parseFloat . reverse  getFloat16be :: Get Float-getFloat16be = getFloat 2 parseFloatBE+getFloat16be = getFloat (ByteCount 2) parseFloatBE  getFloat16le :: Get Float-getFloat16le = getFloat 2 parseFloatLE+getFloat16le = getFloat (ByteCount 2) parseFloatLE  getFloat32be :: Get Float-getFloat32be = getFloat 4 parseFloatBE+getFloat32be = getFloat (ByteCount 4) parseFloatBE  getFloat32le :: Get Float-getFloat32le = getFloat 4 parseFloatLE+getFloat32le = getFloat (ByteCount 4) parseFloatLE  getFloat64be :: Get Double-getFloat64be = getFloat 8 parseFloatBE+getFloat64be = getFloat (ByteCount 8) parseFloatBE  getFloat64le :: Get Double-getFloat64le = getFloat 8 parseFloatLE+getFloat64le = getFloat (ByteCount 8) parseFloatLE  -- |Parse a floating-point value of the given width (in bytes) from within -- a Get monad. getFloat :: (RealFloat a) => ByteCount -> ([Word8] -> a) -> Get a-getFloat width parser = do+getFloat (ByteCount width) parser = do 	bytes <- getByteString width 	(return . parser . B.unpack) bytes  --------------------------------------------------------------------- -putFloat32be :: (RealFloat a) => a -> Put-putFloat32be = putFloat 4 encodeIntBE+putFloat32be :: Float -> Put+putFloat32be x = putFloat (ByteCount 4) encodeIntBE x -putFloat32le :: (RealFloat a) => a -> Put-putFloat32le = putFloat 4 encodeIntLE+putFloat32le :: Float -> Put+putFloat32le x = putFloat (ByteCount 4) encodeIntLE x -putFloat64be :: (RealFloat a) => a -> Put-putFloat64be = putFloat 8 encodeIntBE+putFloat64be :: Double -> Put+putFloat64be x = putFloat (ByteCount 8) encodeIntBE x -putFloat64le :: (RealFloat a) => a -> Put-putFloat64le = putFloat 8 encodeIntLE+putFloat64le :: Double -> Put+putFloat64le x = putFloat (ByteCount 8) encodeIntLE x  putFloat :: (RealFloat a) => ByteCount -> (ByteCount -> Integer -> [Word8]) -> a -> Put-putFloat width f v = putByteString $ B.pack words-	where words = f width (floatToMerged width v)+putFloat width f v = putByteString $ B.pack words'+	where words' = f width (floatToMerged width v)  floatComponents :: (RealFloat a) => ByteCount -> a -> (Bool, Fraction, Exponent) floatComponents width v = 	case (dFraction, dExponent, biasedE) of 		(0, 0, _) -> (sign, 0, 0) 		(_, _, 0) -> (sign, truncatedFraction + 1, 0)-		otherwise -> (sign, truncatedFraction, biasedE)-	where dFraction   = fst (decodeFloat v)-	      dExponent   = snd (decodeFloat v)-	      eWidth      = exponentWidth (width * 8)-	      fWidth      = (width * 8) - eWidth - 1 -- 1 for sign bit-	      biasedE     = bias (dExponent + fWidth) eWidth+		_         -> (sign, truncatedFraction, biasedE)+	where dFraction   = Fraction $ fst (decodeFloat v)+	      dExponent   = Exponent $ snd (decodeFloat v)+	      eWidth      = exponentWidth (bitCount width)+	      fWidth      = (bitCount width) - eWidth - 1 -- 1 for sign bit+	      biasedE     = bias (dExponent + (fromIntegral fWidth)) eWidth 	      absFraction = abs dFraction 	 	      -- Weird check is for detecting -0.0 	      sign        = (1.0 / v) < 0.0 	 	      -- Fraction needs to be truncated, depending on the exponent-	      truncatedFraction = absFraction - (1 `shiftL` fWidth)+	      truncatedFraction = absFraction - (1 `bitShiftL` fWidth)  floatToMerged :: (RealFloat a) => ByteCount -> a -> Integer floatToMerged width v = mergeFloatBits' (floatComponents width v) 	where mergeFloatBits' (s, f, e) = mergeFloatBits fWidth eWidth s f e-	      eWidth      = exponentWidth (width * 8)-	      fWidth      = (width * 8) - eWidth - 1 -- 1 for sign bit+	      eWidth      = exponentWidth (bitCount width)+	      fWidth      = (bitCount width) - eWidth - 1 -- 1 for sign bit  mergeFloatBits :: BitCount -> BitCount -> Bool -> Fraction -> Exponent -> Integer mergeFloatBits fWidth eWidth s f e = shiftedSign .|. shiftedFrac .|. shiftedExp 	where sBit = (if s then 1 else 0) :: Integer-	      shiftedSign = (sBit `shiftL` (fWidth + eWidth)) :: Integer-	      shiftedExp  = ((fromIntegral e) `shiftL` fWidth) :: Integer-	      shiftedFrac = f+	      shiftedSign = (sBit `bitShiftL` (fWidth + eWidth)) :: Integer+	      shiftedExp  = ((fromIntegral e) `bitShiftL` fWidth) :: Integer+	      shiftedFrac = fromIntegral f  -- |Encode an integer to a list of words, in big-endian format encodeIntBE :: ByteCount -> Integer -> [Word8]-encodeIntBE 0     x = []+encodeIntBE 0     _ = [] encodeIntBE width x = (encodeIntBE (width - 1) (x `shiftR` 8)) ++ [step] 	where step = (fromIntegral x) .&. 0xFF @@ -137,7 +155,7 @@ encodeIntLE :: ByteCount -> Integer -> [Word8] encodeIntLE width x = reverse (encodeIntBE width x) -bias :: (Integral a, Integral b) => a -> b -> a+bias :: Exponent -> BitCount -> Exponent bias e eWidth = e - (1 - (2 `iExp` (eWidth - 1)))  ---------------------------------------------------------------------@@ -147,19 +165,19 @@ 	where merge'  (sign, e, f) = encode' (mergeFloat e f width) * signFactor sign 	      encode' (f, e)       = encodeFloat f e 	      signFactor s         = if s then (-1) else 1-	      width                = length bs * 8+	      width                = bitsInWord8 bs  -- |Considering a byte list as a sequence of bits, slice it from start -- inclusive to end exclusive, and return the resulting bit sequence as an -- integer bitSlice :: [Word8] -> BitCount -> BitCount -> Integer-bitSlice bs = sliceInt (foldl' step 0 bs) bitCount+bitSlice bs = sliceInt (foldl' step 0 bs) bitCount' 	where step acc w     = (shiftL acc 8) + (fromIntegral w)-	      bitCount       = ((length bs) * 8)+	      bitCount'      = bitsInWord8 bs  -- |Slice a single integer by start and end bit location sliceInt :: Integer -> BitCount -> BitCount -> BitCount -> Integer-sliceInt x xBitCount s e = fromIntegral $ (x .&. startMask) `shiftR` (xBitCount - e)+sliceInt x xBitCount s e = fromIntegral $ (x .&. startMask) `bitShiftR` (xBitCount - e) 	where startMask = n1Bits (xBitCount - s) 	      n1Bits n  = (2 `iExp` n) - 1 @@ -167,11 +185,11 @@ -- components have not been processed (unbiased, added significant bit, -- etc). splitRawIEEE754 :: [Word8] -> (Bool, Exponent, Fraction)-splitRawIEEE754 bs = (sign, exp, frac)+splitRawIEEE754 bs = (sign, exp', frac) 	where sign = (head bs .&. 0x80) == 0x80-	      exp  = fromIntegral $ bitSlice bs 1 (1 + w)-	      frac = bitSlice bs (1 + w) (length bs * 8)-	      w    = exponentWidth $ length bs * 8+	      exp' = Exponent (fromIntegral $ bitSlice bs 1 (1 + w))+	      frac = Fraction (bitSlice bs (1 + w) (bitsInWord8 bs))+	      w    = exponentWidth $ bitsInWord8 bs  -- |Unbias an exponent unbias :: Exponent -> BitCount -> Exponent@@ -185,15 +203,15 @@ mergeFloat 0 0 _ = (0, 0)  mergeFloat e f width-	-- Infinity / NaN (TODO+	-- Infinity / NaN (TODO) 	| e == eMax = error "Infinity/NaN not supported" 	 	| otherwise = case e of 		-- Denormalized-		0 -> (f, (-fWidth) + (unbiasedE + 1))+		0 -> (fromIntegral f, (fromIntegral unbiasedE + 1) - (fromIntegral fWidth)) 		 		-- Normalized-		_ -> (f + (1 `shiftL` fWidth), (-fWidth) + unbiasedE)+		_ -> (fromIntegral f + (1 `bitShiftL` fWidth), (fromIntegral unbiasedE) - (fromIntegral fWidth)) 		 		where eWidth    = exponentWidth width 		      fWidth    = width - eWidth - 1@@ -208,17 +226,33 @@ exponentWidth k 	| k == 16         = 5 	| k == 32         = 8-	| k `mod` 32 == 0 = ceiling (4 * (log2 k)) - 13+	| k `mod` 32 == 0 = ceiling (4 * (logBase 2 (fromIntegral k))) - 13 	| otherwise       = error "Invalid length of floating-point value" --- |Base-2 log of an integer-log2 = (logBase 2) . fromIntegral- -- |Integral exponent+iExp :: (Integral a, Integral b, Integral c) => a -> b -> c iExp b e = floor $ (fromIntegral b) ** (fromIntegral e) -type Exponent = Int-type Fraction = Integer-type BitCount = Int-type ByteCount = Int+newtype Exponent = Exponent Int+	deriving (Show, Eq, Num, Ord, Real, Enum, Integral, Bits) +newtype Fraction = Fraction Integer+	deriving (Show, Eq, Num, Ord, Real, Enum, Integral, Bits)++newtype BitCount = BitCount Int+	deriving (Show, Eq, Num, Ord, Real, Enum, Integral)++newtype ByteCount = ByteCount Int+	deriving (Show, Eq, Num, Ord, Real, Enum, Integral)++bitCount :: ByteCount -> BitCount+bitCount (ByteCount x) = BitCount (x * 8)++bitsInWord8 :: [Word8] -> BitCount+bitsInWord8 ws = bitCount (ByteCount (length ws))++bitShiftL :: (Bits a) => a -> BitCount -> a+bitShiftL x (BitCount n) = shiftL x n++bitShiftR :: (Bits a) => a -> BitCount -> a+bitShiftR x (BitCount n) = shiftR x n
data-binary-ieee754.cabal view
@@ -1,15 +1,21 @@-Name: data-binary-ieee754-Version: 0.2-Synopsis: Parser/Serializer for IEEE-754 floating-point values-Description: Convert Float and Decimal values to/from raw octets.-License: GPL-License-file: License.txt-Author: John Millikin+name: data-binary-ieee754+version: 0.3+synopsis: Parser/Serializer for IEEE-754 floating-point values+description: Convert Float and Decimal values to/from raw octets.+license: GPL+license-file: License.txt+author: John Millikin maintainer: jmillikin@gmail.com-Build-Type: Simple-Cabal-Version: >=1.2-Category: Data+build-type: Simple+cabal-version: >=1.6+category: Data+stability: experimental+bug-reports: mailto:jmillikin@gmail.com -Library-  Build-Depends: base >=3 && < 5, binary, bytestring-  Exposed-modules: Data.Binary.IEEE754+source-repository head+  type: bzr+  location: bzr+ssh://bazaar.launchpad.net/~jmillikin/%2Bjunk/data-binary-ieee754/++library+  build-depends: base >=3 && < 5, binary, bytestring+  exposed-modules: Data.Binary.IEEE754