module Data.Numbers.CrackNum.Utils where
import Data.Char (toLower)
import Data.List (genericIndex)
import Numeric
import Data.Numbers.CrackNum.Data (Precision(..), IPrecision(..))
all0 :: [Bool] -> Bool
all0 = all not
all1 :: [Bool] -> Bool
all1 = and
any1 :: [Bool] -> Bool
any1 = (True `elem`)
layOut :: [[Bool]] -> String
layOut = unwords . map b2s
b2s :: [Bool] -> String
b2s bs = concat [if b then "1" else "0" | b <- bs]
isBinDigit :: Char -> Bool
isBinDigit = (`elem` "01")
binDigit :: Char -> Int
binDigit '0' = 0
binDigit '1' = 1
binDigit c = error $ "binDigit: recevied: " ++ show c
readB16 :: String -> Integer
readB16 s = case readHex s of
[(v, "")] -> v
_ -> error $ "Invalid hex input: " ++ show s
readB2 :: String -> Integer
readB2 s = case readInt 2 isBinDigit binDigit s of
[(v, "")] -> v
_ -> error $ "Invalid binary input: " ++ show s
binDisp :: [Bool] -> String
binDisp = grpBy4 . b2s
grpBy4 :: String -> String
grpBy4 = grp False
where grp _ [] = []
grp sep xs = let (f, r) = splitAt 4 xs in (if sep then " " else "") ++ f ++ grp True r
hexDisp :: [Bool] -> String
hexDisp = grpBy4 . chunkHex
where chunkHex [] = []
chunkHex xs = let (f, r) = splitAt 4 xs in (letters `genericIndex` (bv f :: Int)) : chunkHex r
letters = ['0' .. '9'] ++ ['A' .. 'F']
cluster :: Int -> [a] -> [[a]]
cluster n is = go is
where s = length is `div` n
go [] = []
go xs = let (f, r) = splitAt s xs in f : go r
bv :: Num a => [Bool] -> a
bv = foldr (\b a -> 2 * a + b2i b) 0 . reverse
where b2i b = if b then 1 else 0
cleanUp :: String -> String
cleanUp = map toLower . filter (not . ignorable)
where ignorable = (`elem` " _-")
hpInds1 :: String
hpInds2 :: String
hpInds3 :: String
hpInds1 = "1 0"
hpInds2 = "5 43210 9876543210"
hpInds3 = "S -E5-- ---F10----"
spInds1 :: String
spInds2 :: String
spInds3 :: String
spInds1 = "3 2 1 0"
spInds2 = "1 09876543 21098765432109876543210"
spInds3 = "S ---E8--- ----------F23----------"
dpInds1 :: String
dpInds2 :: String
dpInds3 :: String
dpInds1 = "6 5 4 3 2 1 0"
dpInds2 = "3 21098765432 1098765432109876543210987654321098765432109876543210"
dpInds3 = "S ----E11---- ------------------------F52-------------------------"
bInds2 :: String
bInds2 = "7654 3210"
wInds1 :: String
wInds2 :: String
wInds1 = "1 0"
wInds2 = "5432 1098 7654 3210"
dInds1 :: String
dInds2 :: String
dInds1 = "3 2 1 0"
dInds2 = "1098 7654 3210 9876 5432 1098 7654 3210"
qInds1 :: String
qInds2 :: String
qInds1 = "6 5 4 3 2 1 0"
qInds2 = "3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210"
fpSz :: Precision -> Int
fpSz HP = 16
fpSz SP = 32
fpSz DP = 64
sgSz :: IPrecision -> (Bool, Int)
sgSz W8 = (False, 8)
sgSz I8 = (True, 8)
sgSz W16 = (False, 16)
sgSz I16 = (True, 16)
sgSz W32 = (False, 32)
sgSz I32 = (True, 32)
sgSz W64 = (False, 64)
sgSz I64 = (True, 64)