module Codec.Binary.Gray
(
binaryToGray, grayToBinary
, bitsToBinary, binaryToBits
, showBinary
) where
import Data.Bits (Bits, testBit, shiftR, bitSize)
xor :: Bool -> Bool -> Bool
xor p q = (p && not q) || (not p && q)
binaryToGray :: [Bool] -> [Bool]
binaryToGray (b:c:bs) = b `xor` c : binaryToGray (c:bs)
binaryToGray [b] = [b]
binaryToGray [] = []
grayToBinary :: [Bool] -> [Bool]
grayToBinary = foldr go []
where go c [] = [c]
go c bs@(b:_) = b `xor` c : bs
bitsToBinary :: (Bits b) => b -> [Bool]
bitsToBinary 0 = []
bitsToBinary i
| signum i == (1) =
let b = map not . bitsToBinary $ negate i 1
in b ++ (take (bitSize i length b) $ repeat True)
| otherwise =
let rest = bitsToBinary $ shiftR i 1
in (testBit i 0 : rest)
binaryToBits :: (Bits a) => [Bool] -> a
binaryToBits = sum . map fst . filter snd . zip (map (2^) [0..])
showBinary :: [Bool] -> String
showBinary [] = "0"
showBinary bs = map (\b -> if b then '1' else '0') . reverse $ bs