encoding/Data/Map/Static/Builder.hs
2020-02-22 20:47:54 +01:00

43 lines
1.9 KiB
Haskell

module Data.Map.Static.Builder where
import Data.Static
import Data.Array.Static.Builder
import Data.List
import Data.Ord
import Data.Bits
buildStaticMap :: (StaticElement i,StaticElement e,Ord i) => [(i,e)] -> String
buildStaticMap lst = let step :: Int -> [(i,e)] -> [(Int,(i,e))]
step n chunk = let ss = findSplitSize (genericLength chunk)
(h,d:t) = genericSplitAt ss chunk
in if null chunk
then []
else (n,d):((step (n*2) h)++(step (n*2+1) t))
checkHeap n [] = []
checkHeap n ((c,x):xs) = if c == n
then x:checkHeap (n+1) xs
else error $ "Heap is not consistent: Should be "++show n++" but is "++show c
uheap = sortBy (comparing fst) (step 1 slst)
slst = sortBy (comparing fst) lst
heap = checkHeap 1 $ sortBy (comparing fst) (step 1 slst)
len = length heap
in "StaticMap ("++buildStaticArray (1,len) (map fst heap)++") ("++buildStaticArray (1,len) (map snd heap)++")"
maxSize :: Integer -> Integer
maxSize d = (floor $ 2^^d) - 1
treeDepth :: Integer -> Integer
treeDepth sz = find' [0..]
where
find' (x:xs) = if (floor $ 2^^x) > sz
then x
else find' xs
findSplitSize :: Integer -> Integer
findSplitSize len = let depth = treeDepth len
free = (maxSize depth) - len
in if free <= (floor $ 2 ^^ (depth - 2))
then maxSize (depth - 1)
else len - (maxSize (depth - 2)) - 1