-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBitlist.hs
More file actions
64 lines (52 loc) · 1.71 KB
/
Copy pathBitlist.hs
File metadata and controls
64 lines (52 loc) · 1.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
module Bitlist where
import qualified Data.Bits as Bits
import qualified Data.List as List
import qualified Data.Word as Word
type Bitlist = ([Word.Word8], Int)
empty :: Bitlist
empty = ([], 0)
size :: Bitlist -> Int
size (_,n) = n
null :: Bitlist -> Bool
null bl = (size bl) == 0
trimToLength :: Int -> [a] -> [a]
trimToLength n xs = drop ((length xs) - n) xs
bitify :: Bool -> Word.Word8
bitify f = (if f then 1 else 0) :: Word.Word8
packWord :: [Bool] -> (Word.Word8, [Bool])
packWord fs = (out, drop 8 fs)
where
fs' = take 8 fs
lshift wrd = wrd `Bits.shiftL` 1
out = foldl (\acc f -> (lshift acc) + (bitify f)) (0 :: Word.Word8) fs'
packBits :: [Bool] -> Bitlist
packBits fs = (handleWord [] fs, length fs)
where
handleWord ret [] = reverse ret
handleWord ret rest = handleWord (wrd:ret) nextRest
where
(wrd,nextRest) = packWord rest
revAppend :: [a] -> [a] -> [a]
revAppend acc [] = acc
revAppend acc (x:xs) = revAppend (x:acc) xs
unpackWord :: [Bool] -> Word.Word8 -> [Bool]
unpackWord acc wrd = handleBit acc 8 wrd
where
rshift wrd = wrd `Bits.shiftR` 1
boolify wrd = (wrd Bits..&. 0x1) > 0
handleBit ret 0 wrd = ret
handleBit ret count wrd =
seq ret' $ handleBit ret' (count - 1) (rshift wrd)
where
bit = boolify wrd
ret' = seq bit $ bit:ret
unpackBits :: Bitlist -> [Bool]
unpackBits (wrds, nbits) =
if (nbits `mod` 8) /= 0 then unpacked else alt
where
(start,last) = splitAt ((length wrds) - 1) $ wrds
front = List.foldl' unpackWord [] $ reverse start
lastWordBits = unpackWord [] (head last)
back = trimToLength (nbits `mod` 8) lastWordBits
unpacked = front ++ back
alt = List.foldl' unpackWord [] $ reverse wrds