crackNum 1.1 → 1.2
raw patch · 5 files changed
+96/−70 lines, 5 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.Numbers.CrackNum: convertToIEEE :: Precision -> String -> FP
- Data.Numbers.CrackNum: crackFP :: Precision -> Integer -> FP
- Data.Numbers.CrackNum: displayInt :: IPrecision -> Integer -> String
+ Data.Numbers.CrackNum: displayWord :: IPrecision -> Integer -> String
+ Data.Numbers.CrackNum: doubleToFP :: Double -> FP
+ Data.Numbers.CrackNum: floatToFP :: Float -> FP
+ Data.Numbers.CrackNum: instance Show FP
+ Data.Numbers.CrackNum: integerToFP :: Precision -> Integer -> FP
+ Data.Numbers.CrackNum: stringToFP :: Precision -> String -> FP
Files
- CHANGES.md +7/−1
- Data/Numbers/CrackNum.hs +57/−43
- Data/Numbers/CrackNum/Data.hs +6/−0
- Data/Numbers/CrackNum/Main.hs +25/−25
- crackNum.cabal +1/−1
CHANGES.md view
@@ -1,7 +1,13 @@ * Hackage: <http://hackage.haskell.org/package/crackNum> * GitHub: <http://leventerkok.github.com/crackNum/> -* Latest Hackage released version: 1.1, 2015-04-02+* Latest Hackage released version: 1.2, 2015-04-11++### Version 1.2, 2015-04-11++ * Fix the constant qnan values for SP/DP+ * Add conversions from float/double. Much easier to use.+ * Better handling of nan values. ### Version 1.1, 2015-04-02
Data/Numbers/CrackNum.hs view
@@ -9,15 +9,16 @@ -- A library for formatting/analyzing FP and Integer values ----------------------------------------------------------------------------- -{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-} module Data.Numbers.CrackNum ( -- * Internal representation of a Floating-point numbers FP(..), Precision(..), IPrecision(..), Kind(..) -- * Creating FP values- , crackFP, convertToIEEE+ , floatToFP, doubleToFP, stringToFP, integerToFP -- * Displaying FP and Int/Word values- , displayFP, displayInt+ , displayFP, displayWord ) where @@ -34,11 +35,13 @@ import Data.Numbers.CrackNum.Data import Data.Numbers.CrackNum.Utils --- | Crack a Haskell Integer value as the given precision floating value-crackFP :: Precision -> Integer -> FP-crackFP HP = crack HP 15 15 [14, 13 .. 10] [9, 8 .. 0]-crackFP SP = crack SP 127 31 [30, 29 .. 23] [22, 21 .. 0]-crackFP DP = crack DP 1023 63 [62, 61 .. 52] [51, 50 .. 0]+-- | Crack a Haskell Integer value as the given precision floating value. The Integer should+-- be the value corresponding to the bit-pattern as the float is laid out in memory according+-- to the IEEE rules.+integerToFP :: Precision -> Integer -> FP+integerToFP HP = crack HP 15 15 [14, 13 .. 10] [9, 8 .. 0]+integerToFP SP = crack SP 127 31 [30, 29 .. 23] [22, 21 .. 0]+integerToFP DP = crack DP 1023 63 [62, 61 .. 52] [51, 50 .. 0] -- | Use Haskell Float to represent SP spVal :: Bool -> Int -> [Bool] -> Float@@ -85,19 +88,21 @@ Denormal -> vBias - 1 _ -> vBias --- | Display a Floating-point number in a nicely formatted way+-- | Display a Floating-point number in a nicely formatted way. (This function is also available+-- through the 'Show' instance for 'FP', but is provided here for symmetry with 'displayWord'.) displayFP :: FP -> String displayFP FP{intVal, prec, sign, stExpt, bias, expt, fracBits, bitLayOut, kind} = intercalate "\n" ls- where ls = [ " " ++ inds1- , " " ++ inds2- , " " ++ inds3- , " Binary: " ++ bitLayOut- , " Hex: " ++ hexDisp allBits- , " Precision: " ++ show prec- , " Sign: " ++ if sign then "Negative" else "Positive"- , " Exponent: " ++ show expt ++ " (Stored: " ++ show stExpt ++ ", Bias: " ++ show bias ++ ")"- , " Value: " ++ val- ]+ where ls = [ " " ++ inds1+ , " " ++ inds2+ , " " ++ inds3+ , " Binary: " ++ bitLayOut+ , " Hex: " ++ hexDisp allBits+ , " Precision: " ++ show prec+ , " Sign: " ++ if sign then "Negative" else "Positive"+ , " Exponent: " ++ show expt ++ " (Stored: " ++ show stExpt ++ ", Bias: " ++ show bias ++ ")"+ , " Value: " ++ val+ ]+ ++ [ " Note: Representation for NaN's is not unique." | isNaNKind kind] (inds1, inds2, inds3) = case prec of HP -> (hpInds1, hpInds2, hpInds3) SP -> (spInds1, spInds2, spInds3)@@ -110,10 +115,10 @@ val = case kind of Zero False -> "+0" Zero True -> "-0"- Infty False -> "+Inf"- Infty True -> "-Inf"- SNaN -> "sNaN"- QNaN -> "qNaN"+ Infty False -> "+Infinity"+ Infty True -> "-Infinity"+ SNaN -> "NaN (Screaming)"+ QNaN -> "NaN (Quietized)" Denormal -> nval True ++ " (DENORMAL)" Normal -> nval False ++ " (NORMAL)" nval dn = (if sign then "-" else "+") ++ v@@ -122,9 +127,13 @@ SP -> showGFloat Nothing (spVal dn expt fracBits) "" DP -> showGFloat Nothing (dpVal dn expt fracBits) "" +-- | Show instance for FP+instance Show FP where+ show = displayFP+ -- | Display a Integer (signed/unsigned) number in a nicely formatted way-displayInt :: IPrecision -> Integer -> String-displayInt iprec intVal = intercalate "\n" ls+displayWord :: IPrecision -> Integer -> String+displayWord iprec intVal = intercalate "\n" ls where (sg, sz) = sgSz iprec ls = [ " " ++ fromJust inds1 | isJust inds1] ++ [ " " ++ inds2@@ -140,7 +149,7 @@ 16 -> (Just wInds1, wInds2) 32 -> (Just dInds1, dInds2) 64 -> (Just qInds1, qInds2)- _ -> error $ "displayInt: Unexpected size: " ++ show sz+ _ -> error $ "displayWord: Unexpected size: " ++ show sz allBits = [intVal `testBit` i | i <- [sz-1, sz-2 .. 0]] signBit = head allBits val | not sg = show intVal@@ -149,20 +158,20 @@ I16 -> show $ adjust (0::Int16) I32 -> show $ adjust (0::Int32) I64 -> show $ adjust (0::Int64)- _ -> error $ "displayInt: Unexpected type: " ++ show iprec+ _ -> error $ "displayWord: Unexpected type: " ++ show iprec adjust :: Bits a => a -> a adjust v = foldr (flip setBit) v [i | (i, True) <- zip [0..] (reverse allBits)] -- | Convert the given string to a IEEE number with the required precision-convertToIEEE :: Precision -> String -> FP-convertToIEEE precision input+stringToFP :: Precision -> String -> FP+stringToFP precision input = case precision of- SP -> fromMaybe (error $ "*** convertToIEEE: Cannot read a valid SP number from: " ++ show input) mbF- DP -> fromMaybe (error $ "*** convertToIEEE: Cannot read a valid DP number from: " ++ show input) mbD- _ -> error $ "*** convertToIEEE: Unsupported precision: " ++ show precision+ SP -> fromMaybe (error $ "*** stringToFP: Cannot read a valid SP number from: " ++ show input) mbF+ DP -> fromMaybe (error $ "*** stringToFP: Cannot read a valid DP number from: " ++ show input) mbD+ _ -> error $ "*** stringToFP: Unsupported precision: " ++ show precision where i = map toLower (dropWhile (== '+') input) specials :: [(String, (FP, FP))]- specials = [ (s, (cvtF f, cvtD d))+ specials = [ (s, (floatToFP f, doubleToFP d)) | (s, (f, d)) <- [ ("infinity", ( infinity, infinity)) , ("-infinity", (-infinity, - infinity)) , ("0", ( 0, 0))@@ -172,18 +181,23 @@ , ("min", ( minNormal, minNormal)) , ("-min", (-minNormal, - minNormal)) , ("epsilon", ( epsilon, epsilon))] ]- ++ [ ("ulp", (crackFP SP 1, crackFP DP 1))- , ("snan", (crackFP SP 0x7f800001, crackFP DP 0x7ff0000000000001))- , ("qnan", (crackFP SP 0x7f8c0001, crackFP DP 0x7ff8000000000001))+ ++ [ ("ulp", (integerToFP SP 1, integerToFP DP 1))+ , ("nan", (integerToFP SP 0x7f800001, integerToFP DP 0x7ff0000000000001))+ , ("snan", (integerToFP SP 0x7f800001, integerToFP DP 0x7ff0000000000001))+ , ("qnan", (integerToFP SP 0x7fc00000, integerToFP DP 0x7ff8000000000000)) ]- cvtF :: Float -> FP- cvtF = crackFP SP . fromIntegral . floatToWord- cvtD :: Double -> FP- cvtD = crackFP DP . fromIntegral . doubleToWord mbF, mbD :: Maybe FP (mbF, mbD) = case (i `lookup` specials, reads i, reads i) of (Just (f, d), _ , _ ) -> (Just f, Just d)- (Nothing, [(f, "")], [(d, "")]) -> (Just (cvtF f), Just (cvtD d))- (Nothing, [(f, "")], _ ) -> (Just (cvtF f), Nothing)- (Nothing, _, [(d, "")]) -> (Nothing, Just (cvtD d))+ (Nothing, [(f, "")], [(d, "")]) -> (Just (floatToFP f), Just (doubleToFP d))+ (Nothing, [(f, "")], _ ) -> (Just (floatToFP f), Nothing)+ (Nothing, _, [(d, "")]) -> (Nothing, Just (doubleToFP d)) _ -> (Nothing, Nothing)++-- | Turn a Haskell float to the internal detailed FP representation+floatToFP :: Float -> FP+floatToFP = integerToFP SP . toInteger . floatToWord++-- | Turn a Haskell double to the internal detailed FP representation+doubleToFP :: Double -> FP+doubleToFP = integerToFP DP . toInteger . doubleToWord
Data/Numbers/CrackNum/Data.hs view
@@ -36,6 +36,12 @@ | Denormal -- ^ Denormalized number, i.e., leading bit is not 1 | Normal -- ^ Normal value. +-- | Determine if we have a NaN value+isNaNKind :: Kind -> Bool+isNaNKind SNaN = True+isNaNKind QNaN = True+isNaNKind _ = False+ -- | Show instance for integer-precisions instance Show IPrecision where show W8 = "Unsigned Byte"
Data/Numbers/CrackNum/Main.hs view
@@ -80,11 +80,11 @@ putStrLn " - You can use _,- or space as a digit to improve readability." putStrLn " - You can give input for multiple lanes, we will guess the #of lanes for you." putStrLn " Or, you can specify number of lanes with the -l option."- putStrLn " - For \"toIEEE\" option:"+ putStrLn " - For \"toIEEE\" option (case doesn't matter):" putStrLn " - You can enter a number in decimal notation (like 2.3)" putStrLn " - OR, enter one of the following:" putStrLn " * infinity, -infinity: Positive/Negative infinities"- putStrLn " * snan, qnan: Not-A-Number; screaming/quiet"+ putStrLn " * nan, snan, qnan: Not-A-Number; screaming/quiet" putStrLn " * 0, -0: Both kinds of zeros" putStrLn " * max : The maximum finite positive value" putStrLn " * -max: The minimum finite negative value"@@ -111,7 +111,7 @@ = do putStrLn $ pn ++ " v" ++ showVersion version ++ ", " ++ copyRight usage pn | Just v <- listToMaybe [s | ToIEEE s <- os], null rs, Just (FPType p) <- mbPrec- = putStrLn $ displayFP $ convertToIEEE p v+ = putStrLn $ displayFP $ stringToFP p v | all isDigit lcs && lc > 0, Just p <- mbPrec = lane pn lc p rs | True@@ -196,28 +196,28 @@ unpack :: String -> Flag -> String -> IO () unpack pn prec orig = case (prec, length s, allHex, allBin) of- (FPType HP, 4, True, _ ) -> putStrLn $ displayFP $ crackFP HP hexVal- (FPType HP, 16, _ , True) -> putStrLn $ displayFP $ crackFP HP binVal- (FPType SP, 8, True, _ ) -> putStrLn $ displayFP $ crackFP SP hexVal- (FPType SP, 32, _ , True) -> putStrLn $ displayFP $ crackFP SP binVal- (FPType DP, 16, True, _ ) -> putStrLn $ displayFP $ crackFP DP hexVal- (FPType DP, 64, _ , True) -> putStrLn $ displayFP $ crackFP DP binVal- (IType I8, 2, True, _ ) -> putStrLn $ displayInt I8 hexVal- (IType I8, 8, _ , True) -> putStrLn $ displayInt I8 binVal- (IType W8, 2, True, _ ) -> putStrLn $ displayInt W8 hexVal- (IType W8, 8, _ , True) -> putStrLn $ displayInt W8 binVal- (IType I16, 4, True, _ ) -> putStrLn $ displayInt I16 hexVal- (IType I16, 16, _ , True) -> putStrLn $ displayInt I16 binVal- (IType W16, 4, True, _ ) -> putStrLn $ displayInt W16 hexVal- (IType W16, 16, _ , True) -> putStrLn $ displayInt W16 binVal- (IType I32, 8, True, _ ) -> putStrLn $ displayInt I32 hexVal- (IType I32, 32, _ , True) -> putStrLn $ displayInt I32 binVal- (IType W32, 8, True, _ ) -> putStrLn $ displayInt W32 hexVal- (IType W32, 32, _ , True) -> putStrLn $ displayInt W32 binVal- (IType I64, 16, True, _ ) -> putStrLn $ displayInt I64 hexVal- (IType I64, 64, _ , True) -> putStrLn $ displayInt I64 binVal- (IType W64, 16, True, _ ) -> putStrLn $ displayInt W64 hexVal- (IType W64, 64, _ , True) -> putStrLn $ displayInt W64 binVal+ (FPType HP, 4, True, _ ) -> putStrLn $ displayFP $ integerToFP HP hexVal+ (FPType HP, 16, _ , True) -> putStrLn $ displayFP $ integerToFP HP binVal+ (FPType SP, 8, True, _ ) -> putStrLn $ displayFP $ integerToFP SP hexVal+ (FPType SP, 32, _ , True) -> putStrLn $ displayFP $ integerToFP SP binVal+ (FPType DP, 16, True, _ ) -> putStrLn $ displayFP $ integerToFP DP hexVal+ (FPType DP, 64, _ , True) -> putStrLn $ displayFP $ integerToFP DP binVal+ (IType I8, 2, True, _ ) -> putStrLn $ displayWord I8 hexVal+ (IType I8, 8, _ , True) -> putStrLn $ displayWord I8 binVal+ (IType W8, 2, True, _ ) -> putStrLn $ displayWord W8 hexVal+ (IType W8, 8, _ , True) -> putStrLn $ displayWord W8 binVal+ (IType I16, 4, True, _ ) -> putStrLn $ displayWord I16 hexVal+ (IType I16, 16, _ , True) -> putStrLn $ displayWord I16 binVal+ (IType W16, 4, True, _ ) -> putStrLn $ displayWord W16 hexVal+ (IType W16, 16, _ , True) -> putStrLn $ displayWord W16 binVal+ (IType I32, 8, True, _ ) -> putStrLn $ displayWord I32 hexVal+ (IType I32, 32, _ , True) -> putStrLn $ displayWord I32 binVal+ (IType W32, 8, True, _ ) -> putStrLn $ displayWord W32 hexVal+ (IType W32, 32, _ , True) -> putStrLn $ displayWord W32 binVal+ (IType I64, 16, True, _ ) -> putStrLn $ displayWord I64 hexVal+ (IType I64, 64, _ , True) -> putStrLn $ displayWord I64 binVal+ (IType W64, 16, True, _ ) -> putStrLn $ displayWord W64 hexVal+ (IType W64, 64, _ , True) -> putStrLn $ displayWord W64 binVal _ -> if not (null orig) then do case prec of FPType HP -> putStrLn $ "ERROR: HP format requires 4 hex or 16 bin digits, received: " ++ what
crackNum.cabal view
@@ -1,5 +1,5 @@ Name: crackNum-Version: 1.1+Version: 1.2 Synopsis: Crack various integer, floating-point data formats Description: Crack HP, SP and DP floats and 8, 16, 32, 64 bit words and integers. License: BSD3