{-# LANGUAGE NamedFieldPuns #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Data.SBV.Utils.CrackNum (
crackNum
) where
import Data.SBV.Core.Concrete
import Data.SBV.Core.Kind
import Data.SBV.Core.SizedFloats
import Data.SBV.Utils.Numeric
import Data.SBV.Utils.PrettyNum (showFloatAtBase)
import Data.Char (intToDigit, toUpper, isSpace)
import Data.Bits
import Data.List
import LibBF hiding (Zero, bfToString)
import Numeric
class CrackNum a where
crackNum :: a -> Maybe String
instance CrackNum CV where
crackNum :: CV -> Maybe String
crackNum CV
cv = case CV -> Kind
forall a. HasKind a => a -> Kind
kindOf CV
cv of
KBool {} -> Maybe String
forall a. Maybe a
Nothing
KUnbounded {} -> Maybe String
forall a. Maybe a
Nothing
KReal {} -> Maybe String
forall a. Maybe a
Nothing
KUserSort {} -> Maybe String
forall a. Maybe a
Nothing
KChar {} -> Maybe String
forall a. Maybe a
Nothing
KString {} -> Maybe String
forall a. Maybe a
Nothing
KList {} -> Maybe String
forall a. Maybe a
Nothing
KSet {} -> Maybe String
forall a. Maybe a
Nothing
KTuple {} -> Maybe String
forall a. Maybe a
Nothing
KMaybe {} -> Maybe String
forall a. Maybe a
Nothing
KEither {} -> Maybe String
forall a. Maybe a
Nothing
KRational {} -> Maybe String
forall a. Maybe a
Nothing
KFloat{} -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ let CFloat Float
f = CV -> CVal
cvVal CV
cv in Float -> String
forall a. HasFloatData a => a -> String
float Float
f
KDouble{} -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ let CDouble Double
d = CV -> CVal
cvVal CV
cv in Double -> String
forall a. HasFloatData a => a -> String
float Double
d
KFP{} -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ let CFP FP
f = CV -> CVal
cvVal CV
cv in FP -> String
forall a. HasFloatData a => a -> String
float FP
f
KBounded Bool
sg Int
sz -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ let CInteger Integer
i = CV -> CVal
cvVal CV
cv in Bool -> Int -> Integer -> String
int Bool
sg Int
sz Integer
i
tab :: String
tab :: String
tab = Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
18 Char
' '
split4 :: Int -> [Int]
split4 :: Int -> [Int]
split4 Int
n
| Int
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = [Int]
rest
| Bool
True = Int
m Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: [Int]
rest
where (Int
d, Int
m) = Int
n Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
4
rest :: [Int]
rest = Int -> Int -> [Int]
forall a. Int -> a -> [a]
replicate Int
d Int
4
getVal :: [Bool] -> Integer
getVal :: [Bool] -> Integer
getVal = (Integer -> Bool -> Integer) -> Integer -> [Bool] -> Integer
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Integer
s Bool
b -> Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
s Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ if Bool
b then Integer
1 else Integer
0) Integer
0
mkHex :: [Bool] -> String
mkHex :: [Bool] -> String
mkHex [Bool]
bin = (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toUpper (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Integer -> String -> String
forall a. (Integral a, Show a) => a -> String -> String
showHex ([Bool] -> Integer
getVal [Bool]
bin) String
""
int :: Bool -> Int -> Integer -> String
int :: Bool -> Int -> Integer -> String
int Bool
signed Int
sz Integer
v = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String]
ruler [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
info
where splits :: [Int]
splits = Int -> [Int]
split4 Int
sz
ruler :: [String]
ruler = (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
tab String -> String -> String
forall a. [a] -> [a] -> [a]
++) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ Int -> [Int] -> [String]
mkRuler Int
sz [Int]
splits
bitRep :: [[Bool]]
bitRep :: [[Bool]]
bitRep = [Int] -> [Bool] -> [[Bool]]
forall a. [Int] -> [a] -> [[a]]
split [Int]
splits [Integer
v Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` Int
i | Int
i <- [Int] -> [Int]
forall a. [a] -> [a]
reverse [Int
0 .. Int
sz Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
flatHex :: String
flatHex = ([Bool] -> String) -> [[Bool]] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [Bool] -> String
mkHex [[Bool]]
bitRep
iprec :: String
iprec
| Bool
signed = String
"Signed " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
sz String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-bit 2's complement integer"
| Bool
True = String
"Unsigned " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
sz String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"-bit word"
signBit :: Bool
signBit = Integer
v Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` (Int
szInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
s :: String
s | Bool
signed Bool -> Bool -> Bool
&& Bool
signBit = String
"-"
| Bool
True = String
""
av :: Integer
av = Integer -> Integer
forall a. Num a => a -> a
abs Integer
v
info :: [String]
info = [ String
" Binary layout: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [(Bool -> String) -> [Bool] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Bool
b -> if Bool
b then String
"1" else String
"0") [Bool]
is | [Bool]
is <- [[Bool]]
bitRep]
, String
" Hex layout: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords ([Int] -> String -> [String]
forall a. [Int] -> [a] -> [[a]]
split (Int -> [Int]
split4 (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
flatHex)) String
flatHex)
, String
" Type: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
iprec
]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
" Sign: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ if Bool
signBit then String
"Negative" else String
"Positive" | Bool
signed]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
" Binary: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"0b" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> (Int -> Char) -> Integer -> String -> String
forall a.
(Integral a, Show a) =>
a -> (Int -> Char) -> a -> String -> String
showIntAtBase Integer
2 Int -> Char
intToDigit Integer
av String
""
, String
" Octal: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"0o" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String -> String
forall a. (Integral a, Show a) => a -> String -> String
showOct Integer
av String
""
, String
" Decimal: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
v
, String
" Hex: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"0x" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String -> String
forall a. (Integral a, Show a) => a -> String -> String
showHex Integer
av String
""
]
data FPKind = Zero Bool
| Infty Bool
| NaN
| Subnormal
| Normal
deriving FPKind -> FPKind -> Bool
(FPKind -> FPKind -> Bool)
-> (FPKind -> FPKind -> Bool) -> Eq FPKind
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FPKind -> FPKind -> Bool
$c/= :: FPKind -> FPKind -> Bool
== :: FPKind -> FPKind -> Bool
$c== :: FPKind -> FPKind -> Bool
Eq
instance Show FPKind where
show :: FPKind -> String
show Zero{} = String
"FP_ZERO"
show Infty{} = String
"FP_INFINITE"
show FPKind
NaN = String
"FP_NAN"
show FPKind
Subnormal = String
"FP_SUBNORMAL"
show FPKind
Normal = String
"FP_NORMAL"
getKind :: RealFloat a => a -> FPKind
getKind :: a -> FPKind
getKind a
fp
| a
fp a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 = Bool -> FPKind
Zero (a -> Bool
forall a. RealFloat a => a -> Bool
isNegativeZero a
fp)
| a -> Bool
forall a. RealFloat a => a -> Bool
isInfinite a
fp = Bool -> FPKind
Infty (a
fp a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0)
| a -> Bool
forall a. RealFloat a => a -> Bool
isNaN a
fp = FPKind
NaN
| a -> Bool
forall a. RealFloat a => a -> Bool
isDenormalized a
fp = FPKind
Subnormal
| Bool
True = FPKind
Normal
showAtBases :: FPKind -> (String, String, String, String) -> Either String (String, String, String, String)
showAtBases :: FPKind
-> (String, String, String, String)
-> Either String (String, String, String, String)
showAtBases FPKind
k (String, String, String, String)
bvs = case FPKind
k of
Zero Bool
False -> (String, String, String, String)
-> Either String (String, String, String, String)
forall a b. b -> Either a b
Right (String
"0b0.0", String
"0o0.0", String
"0.0", String
"0x0")
Zero Bool
True -> (String, String, String, String)
-> Either String (String, String, String, String)
forall a b. b -> Either a b
Right (String
"-0b0.0", String
"-0o0.0", String
"-0.0", String
"-0o0")
Infty Bool
False -> String -> Either String (String, String, String, String)
forall a b. a -> Either a b
Left String
"Infinity"
Infty Bool
True -> String -> Either String (String, String, String, String)
forall a b. a -> Either a b
Left String
"-Infinity"
FPKind
NaN -> String -> Either String (String, String, String, String)
forall a b. a -> Either a b
Left String
"NaN"
FPKind
Subnormal -> (String, String, String, String)
-> Either String (String, String, String, String)
forall a b. b -> Either a b
Right ((String, String, String, String)
-> (String, String, String, String)
dropSuffixes (String, String, String, String)
bvs)
FPKind
Normal -> (String, String, String, String)
-> Either String (String, String, String, String)
forall a b. b -> Either a b
Right ((String, String, String, String)
-> (String, String, String, String)
dropSuffixes (String, String, String, String)
bvs)
where dropSuffixes :: (String, String, String, String)
-> (String, String, String, String)
dropSuffixes (String
a, String
b, String
c, String
d) = (String -> String
bfRemoveRedundantExp String
a, String -> String
bfRemoveRedundantExp String
b, String -> String
bfRemoveRedundantExp String
c, String -> String
bfRemoveRedundantExp String
d)
data FloatData = FloatData { FloatData -> String
prec :: String
, FloatData -> Int
eb :: Int
, FloatData -> Int
sb :: Int
, FloatData -> Integer
bits :: Integer
, FloatData -> FPKind
fpKind :: FPKind
, FloatData -> Either String (String, String, String, String)
fpVals :: Either String (String, String, String, String)
}
class HasFloatData a where
getFloatData :: a -> FloatData
instance HasFloatData Float where
getFloatData :: Float -> FloatData
getFloatData Float
f = FloatData :: String
-> Int
-> Int
-> Integer
-> FPKind
-> Either String (String, String, String, String)
-> FloatData
FloatData {
prec :: String
prec = String
"Single"
, eb :: Int
eb = Int
8
, sb :: Int
sb = Int
24
, bits :: Integer
bits = Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Float -> Word32
floatToWord Float
f)
, fpKind :: FPKind
fpKind = FPKind
k
, fpVals :: Either String (String, String, String, String)
fpVals = FPKind
-> (String, String, String, String)
-> Either String (String, String, String, String)
showAtBases FPKind
k (Int -> Float -> String -> String
forall a. (Show a, RealFloat a) => Int -> a -> String -> String
showFloatAtBase Int
2 Float
f String
"", Int -> Float -> String -> String
forall a. (Show a, RealFloat a) => Int -> a -> String -> String
showFloatAtBase Int
8 Float
f String
"", Float -> String
forall a. Show a => a -> String
show Float
f, Int -> Float -> String -> String
forall a. (Show a, RealFloat a) => Int -> a -> String -> String
showFloatAtBase Int
16 Float
f String
"")
}
where k :: FPKind
k = Float -> FPKind
forall a. RealFloat a => a -> FPKind
getKind Float
f
instance HasFloatData Double where
getFloatData :: Double -> FloatData
getFloatData Double
d = FloatData :: String
-> Int
-> Int
-> Integer
-> FPKind
-> Either String (String, String, String, String)
-> FloatData
FloatData {
prec :: String
prec = String
"Double"
, eb :: Int
eb = Int
11
, sb :: Int
sb = Int
53
, bits :: Integer
bits = Word64 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Double -> Word64
doubleToWord Double
d)
, fpKind :: FPKind
fpKind = FPKind
k
, fpVals :: Either String (String, String, String, String)
fpVals = FPKind
-> (String, String, String, String)
-> Either String (String, String, String, String)
showAtBases FPKind
k (Int -> Double -> String -> String
forall a. (Show a, RealFloat a) => Int -> a -> String -> String
showFloatAtBase Int
2 Double
d String
"", Int -> Double -> String -> String
forall a. (Show a, RealFloat a) => Int -> a -> String -> String
showFloatAtBase Int
8 Double
d String
"", Double -> String
forall a. Show a => a -> String
show Double
d, Int -> Double -> String -> String
forall a. (Show a, RealFloat a) => Int -> a -> String -> String
showFloatAtBase Int
16 Double
d String
"")
}
where k :: FPKind
k = Double -> FPKind
forall a. RealFloat a => a -> FPKind
getKind Double
d
getExponentData :: FloatData -> (Integer, Integer, Integer)
getExponentData :: FloatData -> (Integer, Integer, Integer)
getExponentData FloatData{Int
eb :: Int
eb :: FloatData -> Int
eb, Int
sb :: Int
sb :: FloatData -> Int
sb, Integer
bits :: Integer
bits :: FloatData -> Integer
bits, FPKind
fpKind :: FPKind
fpKind :: FloatData -> FPKind
fpKind} = (Integer
expValue, Integer
expStored, Integer
bias)
where
bias :: Integer
bias :: Integer
bias = (Integer
2 :: Integer) Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ ((Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
eb :: Integer) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1
expStored :: Integer
expStored = [Bool] -> Integer
getVal [Integer
bits Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` Int
i | Int
i <- [Int] -> [Int]
forall a. [a] -> [a]
reverse [Int
sbInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 .. Int
sbInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
ebInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
2]]
expValue :: Integer
expValue = case FPKind
fpKind of
FPKind
Subnormal -> Integer
1 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
bias
FPKind
_ -> Integer
expStored Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
bias
instance HasFloatData FP where
getFloatData :: FP -> FloatData
getFloatData v :: FP
v@(FP Int
eb Int
sb BigFloat
f) = FloatData :: String
-> Int
-> Int
-> Integer
-> FPKind
-> Either String (String, String, String, String)
-> FloatData
FloatData {
prec :: String
prec = case (Int
eb, Int
sb) of
( Int
5, Int
11) -> String
"Half (5 exponent bits, 10 significand bits.)"
( Int
8, Int
24) -> String
"Single (8 exponent bits, 23 significand bits.)"
(Int
11, Int
53) -> String
"Double (11 exponent bits, 52 significand bits.)"
(Int
15, Int
113) -> String
"Quad (15 exponent bits, 112 significand bits.)"
( Int
_, Int
_) -> Int -> String
forall a. Show a => a -> String
show Int
eb String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" exponent bits, " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Int
sbInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" significand bit" String -> String -> String
forall a. [a] -> [a] -> [a]
++ if Int
sb Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
2 then String
"s" else String
""
, eb :: Int
eb = Int
eb
, sb :: Int
sb = Int
sb
, bits :: Integer
bits = BFOpts -> BigFloat -> Integer
bfToBits (Int -> Int -> RoundMode -> BFOpts
forall a. Integral a => a -> a -> RoundMode -> BFOpts
mkBFOpts Int
eb Int
sb RoundMode
NearEven) BigFloat
f
, fpKind :: FPKind
fpKind = FPKind
k
, fpVals :: Either String (String, String, String, String)
fpVals = FPKind
-> (String, String, String, String)
-> Either String (String, String, String, String)
showAtBases FPKind
k (Int -> Bool -> Bool -> FP -> String
bfToString Int
2 Bool
True Bool
True FP
v, Int -> Bool -> Bool -> FP -> String
bfToString Int
8 Bool
True Bool
True FP
v, Int -> Bool -> Bool -> FP -> String
bfToString Int
10 Bool
True Bool
False FP
v, Int -> Bool -> Bool -> FP -> String
bfToString Int
16 Bool
True Bool
True FP
v)
}
where opts :: BFOpts
opts = Int -> Int -> RoundMode -> BFOpts
forall a. Integral a => a -> a -> RoundMode -> BFOpts
mkBFOpts Int
eb Int
sb RoundMode
NearEven
k :: FPKind
k | BigFloat -> Bool
bfIsZero BigFloat
f = Bool -> FPKind
Zero (BigFloat -> Bool
bfIsNeg BigFloat
f)
| BigFloat -> Bool
bfIsInf BigFloat
f = Bool -> FPKind
Infty (BigFloat -> Bool
bfIsNeg BigFloat
f)
| BigFloat -> Bool
bfIsNaN BigFloat
f = FPKind
NaN
| BFOpts -> BigFloat -> Bool
bfIsSubnormal BFOpts
opts BigFloat
f = FPKind
Subnormal
| Bool
True = FPKind
Normal
float :: HasFloatData a => a -> String
float :: a -> String
float a
f = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"\n" ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String]
ruler [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ String
legend String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
info
where fd :: FloatData
fd@FloatData{String
prec :: String
prec :: FloatData -> String
prec, Int
eb :: Int
eb :: FloatData -> Int
eb, Int
sb :: Int
sb :: FloatData -> Int
sb, Integer
bits :: Integer
bits :: FloatData -> Integer
bits, FPKind
fpKind :: FPKind
fpKind :: FloatData -> FPKind
fpKind, Either String (String, String, String, String)
fpVals :: Either String (String, String, String, String)
fpVals :: FloatData -> Either String (String, String, String, String)
fpVals} = a -> FloatData
forall a. HasFloatData a => a -> FloatData
getFloatData a
f
splits :: [Int]
splits = [Int
1, Int
eb, Int
sb]
ruler :: [String]
ruler = (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
tab String -> String -> String
forall a. [a] -> [a] -> [a]
++) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ Int -> [Int] -> [String]
mkRuler (Int
eb Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
sb) [Int]
splits
legend :: String
legend = String
tab String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"S " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> Int -> String
mkTag (Char
'E' Char -> String -> String
forall a. a -> [a] -> [a]
: Int -> String
forall a. Show a => a -> String
show Int
eb) Int
eb String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> Int -> String
mkTag (Char
'S' Char -> String -> String
forall a. a -> [a] -> [a]
: Int -> String
forall a. Show a => a -> String
show (Int
sbInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)) (Int
sbInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
mkTag :: String -> Int -> String
mkTag String
t Int
len = Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
len (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> Char -> String
forall a. Int -> a -> [a]
replicate ((Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
t) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) Char
'-' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
t String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char -> String
forall a. a -> [a]
repeat Char
'-'
allBits :: [Bool]
allBits :: [Bool]
allBits = [Integer
bits Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` Int
i | Int
i <- [Int] -> [Int]
forall a. [a] -> [a]
reverse [Int
0 .. Int
eb Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
sb Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]]
flatHex :: String
flatHex = ([Bool] -> String) -> [[Bool]] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [Bool] -> String
mkHex ([Int] -> [Bool] -> [[Bool]]
forall a. [Int] -> [a] -> [[a]]
split (Int -> [Int]
split4 (Int
eb Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
sb)) [Bool]
allBits)
sign :: Bool
sign = Integer
bits Integer -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` (Int
ebInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
sbInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
(Integer
exponentVal, Integer
storedExponent, Integer
bias) = FloatData -> (Integer, Integer, Integer)
getExponentData FloatData
fd
esInfo :: String
esInfo = String
"Stored: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
storedExponent String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", Bias: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
bias
isSubNormal :: Bool
isSubNormal = case FPKind
fpKind of
FPKind
Subnormal -> Bool
True
FPKind
_ -> Bool
False
info :: [String]
info = [ String
" Binary layout: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [(Bool -> String) -> [Bool] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Bool
b -> if Bool
b then String
"1" else String
"0") [Bool]
is | [Bool]
is <- [Int] -> [Bool] -> [[Bool]]
forall a. [Int] -> [a] -> [[a]]
split [Int]
splits [Bool]
allBits]
, String
" Hex layout: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords ([Int] -> String -> [String]
forall a. [Int] -> [a] -> [[a]]
split (Int -> [Int]
split4 (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
flatHex)) String
flatHex)
, String
" Precision: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
prec
, String
" Sign: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ if Bool
sign then String
"Negative" else String
"Positive"
]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
" Exponent: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
exponentVal String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (Subnormal, with fixed exponent value. " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
esInfo String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")" | Bool
isSubNormal ]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
" Exponent: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> String
forall a. Show a => a -> String
show Integer
exponentVal String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
esInfo String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")" | Bool -> Bool
not Bool
isSubNormal]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
" Classification: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ FPKind -> String
forall a. Show a => a -> String
show FPKind
fpKind]
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (case Either String (String, String, String, String)
fpVals of
Left String
val -> [ String
" Value: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
val]
Right (String
bval, String
oval, String
dval, String
hval) -> [ String
" Binary: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
bval
, String
" Octal: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
oval
, String
" Decimal: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dval
, String
" Hex: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
hval
])
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [ String
" Note: Representation for NaN's is not unique" | FPKind
fpKind FPKind -> FPKind -> Bool
forall a. Eq a => a -> a -> Bool
== FPKind
NaN]
mkRuler :: Int -> [Int] -> [String]
mkRuler :: Int -> [Int] -> [String]
mkRuler Int
n [Int]
splits = (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> String
trimRight (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unwords ([String] -> String) -> (String -> [String]) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> String -> [String]
forall a. [Int] -> [a] -> [[a]]
split [Int]
splits (String -> [String]) -> (String -> String) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Char -> String -> String
trim Maybe Char
forall a. Maybe a
Nothing) ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. [[a]] -> [[a]]
transpose ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (Int -> String) -> [Int] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Int -> String
forall a. Show a => a -> String
pad ([Int] -> [String]) -> [Int] -> [String]
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int]
forall a. [a] -> [a]
reverse [Int
0 .. Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]
where len :: Int
len = String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Int -> String
forall a. Show a => a -> String
show (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1))
pad :: a -> String
pad a
i = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
len (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. [a] -> [a]
reverse (a -> String
forall a. Show a => a -> String
show a
i) String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char -> String
forall a. a -> [a]
repeat Char
'0'
trim :: Maybe Char -> String -> String
trim Maybe Char
_ String
"" = String
""
trim Maybe Char
mbPrev (Char
c:String
cs)
| Maybe Char
mbPrev Maybe Char -> Maybe Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char -> Maybe Char
forall a. a -> Maybe a
Just Char
c = Char
' ' Char -> String -> String
forall a. a -> [a] -> [a]
: Maybe Char -> String -> String
trim Maybe Char
mbPrev String
cs
| Bool
True = Char
c Char -> String -> String
forall a. a -> [a] -> [a]
: Maybe Char -> String -> String
trim (Char -> Maybe Char
forall a. a -> Maybe a
Just Char
c) String
cs
trimRight :: String -> String
trimRight = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse
split :: [Int] -> [a] -> [[a]]
split :: [Int] -> [a] -> [[a]]
split [Int]
_ [] = []
split [] [a]
xs = [[a]
xs]
split (Int
i:[Int]
is) [a]
xs = case Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
i [a]
xs of
([a]
pre, []) -> [[a]
pre]
([a]
pre, [a]
post) -> [a]
pre [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [Int] -> [a] -> [[a]]
forall a. [Int] -> [a] -> [[a]]
split [Int]
is [a]
post