-- | Manipulation de bits. module Htirage.Bits where import Data.Bool import Data.Eq (Eq(..)) import Data.Int (Int) import Data.List ((++), foldr, length, splitAt, tail) import Data.Ord (Ord(..)) import Prelude (Integer, Integral(..), Num(..), error, undefined) import Text.Show (Show(..)) -- | @bitSize n@ retourne le nombre de bits servant à encoder 'n'. bitSize :: Integer -> Int bitSize n | 0<=n = go n | otherwise = undefined where go 0 = 0 go i = 1 + go (i`div`2) -- | @integerOfBits bs@ retourne le nombre encodé par les bits 'bs'. integerOfBits :: [Bool] -> Integer integerOfBits [] = 0 integerOfBits (b:bs) = integerOfBits bs * 2 + (if b then 1 else 0) -- | @bitsOfInteger m n@ retourne les 'm' premiers bits de poids faible -- encodant le nombre 'n'. bitsOfInteger :: Int -> Integer -> [Bool] bitsOfInteger m n | 0<=m,0<=n = go m n | otherwise = undefined where go 0 _ = [] go i j = (r==1) : go (i-1) q where (q,r) = j`divMod`2 -- | @interleaveBits bs@ retourne les bits de @bs@ -- en consommant un bit de chaque liste à chaque passe. interleaveBits :: [[Bool]] -> [Bool] interleaveBits [] = [] interleaveBits bss = let (hs,ts) = unzip bss in hs ++ interleaveBits ts where unzip = foldr (\bits ~(hs,ts) -> case bits of [] -> (hs,ts) b:bs -> (b:hs,bs:ts) ) ([], []) -- | @randomIntOfBits n bs@ retourne le premier entier 'i' formé par les bits 'bs' -- qui a le potentiel d’atteindre un entier dans @[0..n-1]@, -- ou recommence en ignorant le premier bit si @n <= i@. randomIntegerOfBits :: Integer -> [Bool] -> Integer randomIntegerOfBits n bs | given < enough = error (show (enough - given) ++ " bits missing") | n <= i = randomIntegerOfBits n (tail bits ++ bs') | otherwise = i where (bits, bs') = splitAt enough bs i = integerOfBits bits given = length bits enough = bitSize (n - 1)