module Data.BooleanList where
import Data.List
import Data.Word
import qualified Data.ByteString
import Control.Arrow
import Control.Monad
import Data.Maybe
boolsRequiredForInteger n = length $ integerToBooleanList n
maximumIntegerForBools n = booleanListToInteger $ replicate n True
integerToBooleanList :: Integral a => a -> [Bool]
integerToBooleanList 0 = []
integerToBooleanList n = integerToBooleanList div ++ [toEnum (fromIntegral rem)]
where (div,rem) = divMod n 2
booleanListToInteger :: Integral a => [Bool] -> a
booleanListToInteger (x:[]) = fromIntegral (fromEnum x)
booleanListToInteger (x:xs) = ((2 * fromIntegral (fromEnum x)) ^ (length xs)) + rest
where rest = booleanListToInteger xs
booleanListToInteger [] = 0
integerToBooleanListBigEndian = integerToBooleanList
bigEndianBooleanListToInteger = booleanListToInteger
integerToBooleanList' True = integerToBooleanListBigEndian
integerToBooleanList' False = integerToBooleanListLittleEndian
integerToBooleanListLittleEndian = toLittleEndian . integerToBooleanList
littleEndianBooleanListToInteger = booleanListToInteger . fromLittleEndian
booleanListToInteger' True = bigEndianBooleanListToInteger
booleanListToInteger' False = littleEndianBooleanListToInteger
toLittleEndian = reverse
fromLittleEndian = reverse
overlayRight :: [a] -> [a] -> [a]
overlayRight xs ys = reverse . map head . transpose . map reverse $ [ys,xs]
overlayLeft :: [b] -> [b] -> [b]
overlayLeft xs ys = map head . transpose $ [ys,xs]
padBooleanListLeft :: Int -> [Bool] -> [Bool]
padBooleanListLeft p xs = overlayRight (replicate p False) xs
padBooleanListRight :: Int -> [Bool] -> [Bool]
padBooleanListRight p xs = overlayLeft (replicate p False) xs
padBooleanList' :: Bool -> Int -> [Bool] -> [Bool]
padBooleanList' True = padBooleanListLeft
padBooleanList' False = padBooleanListRight
padBooleanList = padBooleanListLeft
integerToBooleanListPadded :: Integral a => Int -> a -> [Bool]
integerToBooleanListPadded p x = padBooleanListLeft p (integerToBooleanList x)
integerToBooleanListPadded'' :: Bool -> Int -> Integer -> [Bool]
integerToBooleanListPadded'' e p x = padBooleanList' e p (integerToBooleanList' e x)
integerToBigEndianBooleanListPadded = integerToBooleanListPadded'' True
integerToLittleEndianBooleanListPadded = integerToBooleanListPadded'' False
takeIntegerFromBooleanList = takeIntegerFromBooleanList' True
takeIntegerFromBooleanList' b length xs = (booleanListToInteger' b h,rest)
where (h,rest) = splitAt length xs
takeIntegerFromBooleanListLittleEndian = takeIntegerFromBooleanList' False
takeIntegerFromBooleanListBigEndian = takeIntegerFromBooleanList' True
booleanListToIntegers = booleanListToIntegers' True
bigEndianBooleanListToIntegers = booleanListToIntegers' True
littleEndianBooleanListToIntegers = booleanListToIntegers' False
booleanListToIntegers' = booleanListToIntegers'' False
booleanListLittleEndianToIntegersTerminated = booleanListToIntegers'' True False
booleanListToIntegersTerminated = booleanListToIntegers'' True True
booleanListToByteString = Data.ByteString.pack . map fromIntegral . booleanListToIntegersTerminated 8
booleanListToIntegers'' t e p xs | null xs = []
| lastChunk && t = booleanListToIntegers'' False e p (xs ++ (take (bitsToGo + p) terminator))
| bitsLeftOver = (op(2^bitsToGo) int) : []
| otherwise = int : booleanListToIntegers'' t e p rest
where (int,rest) = takeIntegerFromBooleanList' e p xs
bitsLeftOver = listLengthIsSmallerThanOrEqualTo (p1) xs
lastChunk = listLengthIsSmallerThanOrEqualTo p xs
bitsToGo = (p length xs) `rem` p
terminator = (False:repeat True)
op = if e then (*) else flip const
isTerminator p xs | listLengthIsSmallerThanOrEqualTo (2*p) xs = isTerminator' xs
| otherwise = False
isTerminator' (False:xs) = all (==True) xs
isTerminator' _ = False
takeWhileRest p xs@(x:xs') = if p xs then x : takeWhileRest p xs' else []
takeWhileRest p [] = []
listLengthIsSmallerThanOrEqualTo x xs = null $ drop x xs
integersToBooleanListPadded = integersToBooleanListPadded' True
integersToBooleanListTerminated = integersToBooleanListPaddedTerminated' True
integersToBooleanLists = map integerToBooleanList
integersToBooleanListsPadded = integersToBooleanListsPadded' True
integersToBigEndianBooleanListPadded = integersToBooleanListPadded' True
integersToLittleEndianBooleanListPadded = integersToBooleanListPadded' False
integersToBooleanListPadded' = integersToBooleanListPadded'' False
integersToBooleanListPaddedTerminated' = integersToBooleanListPadded'' True
integersToBooleanListPadded'' t e p xs = (if t then takeWhileRest (not . isTerminator p) else id) (concat (integersToBooleanListsPadded' e p xs))
integersToBooleanListsPadded' e p xs = map (integerToBooleanListPadded'' e p) xs
byteStringToBooleanList = integersToBooleanListTerminated 8 . map fromIntegral . Data.ByteString.unpack
listOfPaddedIntegersToBooleanList pSize xs = concatMap integerToBooleanList $ booleanListToIntegers pSize xs
toBoolean8s xs = integersToBooleanListPadded 8 xs
precedentalEncoding xs = concat $ zipWith (\ x y -> integerToBooleanListPadded (ceiling . logBase 2 $ (fromIntegral x)) y) (scanl1 max xs) xs
int8Chunks xs = booleanListToIntegers 8 xs
word8Chunks xs = map (fromIntegral :: Integral a => a -> Word8) . int8Chunks $ xs
toByteString xs = Data.ByteString.pack (word8Chunks xs)
allBooleanLists = concat $ map (\x -> replicateM x [False,True] ) [1..]
pruneBooleanList = dropWhile (==False)
encodeBooleanListInInteger' x = allBooleanLists !! x
encodeIntegerInBooleanList' xs = fromJust (elemIndex xs allBooleanLists)
encodeBooleanListInInteger x = integerToBooleanListPadded (baseComponent x) (x ((2^(baseComponent x)) 2))
where baseComponent x = floor (logBase 2 (fromIntegral (x+2)))
encodeIntegerInBooleanList xs = (2 ^ (length xs) 2) + (booleanListToInteger xs)