packages feed

gray-code 0.1 → 0.2

raw patch · 5 files changed

+203/−89 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Codec.Binary.Gray: binaryToBits :: (Bits a) => [Bool] -> a
- Codec.Binary.Gray: binaryToGray :: [Bool] -> [Bool]
- Codec.Binary.Gray: bitsToBinary :: (Bits b) => b -> [Bool]
- Codec.Binary.Gray: grayToBinary :: [Bool] -> [Bool]
- Codec.Binary.Gray: showBinary :: [Bool] -> String
+ Codec.Binary.Gray.Bits: binary :: Bits a => a -> a
+ Codec.Binary.Gray.Bits: gray :: Bits a => a -> a
+ Codec.Binary.Gray.Bits: showBits :: Bits a => a -> String
+ Codec.Binary.Gray.List: binary :: [Bool] -> [Bool]
+ Codec.Binary.Gray.List: fromList :: Bits b => [Bool] -> b
+ Codec.Binary.Gray.List: gray :: [Bool] -> [Bool]
+ Codec.Binary.Gray.List: showBits :: [Bool] -> String
+ Codec.Binary.Gray.List: toList :: Bits b => b -> [Bool]

Files

Codec/Binary/Gray.hs view
@@ -1,60 +1,4 @@--- | Gray code is a binary numeral system where two successive numbers--- differ in only one bit. module Codec.Binary.Gray-    (-      -- * List functions (for @[Bool]@)-      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)---- | Takes a list of bits (most significant last) in binary encoding--- and converts them to Gray code.------ Algorithm:---   Haupt, R.L. and Haupt, S.E., Practical Genetic Algorithms,---   Second ed. (2004),  5.4. Gray Codes.-binaryToGray :: [Bool] -> [Bool]-binaryToGray (b:c:bs) = b `xor` c : binaryToGray (c:bs)-binaryToGray [b] = [b]-binaryToGray [] = []---- | Takes a list of bits in Gray code and converts them to binary encoding--- (most significant bit last).------ Algorithm:---   Haupt, R.L. and Haupt, S.E., Practical Genetic Algorithms,---   Second ed. (2004),  5.4. Gray Codes.-grayToBinary :: [Bool] -> [Bool]-grayToBinary = foldr go []-  where go c [] = [c]-        go c bs@(b:_) = b `xor` c : bs---- | Convert a number to a list of bits in usual binary encoding (most--- significant last).--- --- As 'bitSize', 'bitsToBinary' is undefined for types that do not--- have fixed bitsize, like 'Integer'.-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) -- pad major bits-    | otherwise        =-        let rest = bitsToBinary $ shiftR i 1  -- works only for positive i-        in  (testBit i 0 : rest)---- | Convert a list of bits in binary encoding to a number.-binaryToBits :: (Bits a) => [Bool] -> a-binaryToBits = sum . map fst . filter snd . zip (map (2^) [0..])+    ( module Codec.Binary.Gray.Bits ) where --- | Render a list of bits as a 0-1 string.-showBinary :: [Bool] -> String-showBinary [] = "0"-showBinary bs = map (\b -> if b then '1' else '0') . reverse $ bs+import Codec.Binary.Gray.Bits
+ Codec/Binary/Gray/Bits.hs view
@@ -0,0 +1,65 @@+-- | Gray code is a binary numeral system where two successive numbers+-- differ in only one bit.+--+-- This module provides an interface to encode/decode @'Bits'@ types.+--+-- Algorithm:+--   Haupt, R.L. and Haupt, S.E., Practical Genetic Algorithms,+--   Second ed. (2004),  5.4. Gray Codes.+module Codec.Binary.Gray.Bits+    ( gray+    , binary+    , showBits+    ) where++import Data.Bits+    ( Bits, testBit, setBit, clearBit, bitSize+    , shiftL, shiftR, complement, xor, (.&.), (.|.), isSigned)++import qualified Codec.Binary.Gray.List as L+    +-- | Right shift without extension of the sign bit (reset it to zero).+shiftR' :: (Bits a) => a -> Int -> a+shiftR' n 0    = n+shiftR' n s+  | isSigned n && signum n == -1 =+      let n' = clearBit (shiftR n 1) (bitSize n - 1)+      in  shiftR' n' (s-1)+  | otherwise  = shiftR n s++-- | Convert an integer number from binary to Gray code.+-- +-- 'gray' is undefined for negative numbers of types that do not have+-- fixed bitsize, e.g. for negative 'Integer's.+gray :: (Bits a) => a -> a+gray n = n `xor` (shiftR' n 1)++-- | Convert an integer number from Gray code to binary.+-- +-- 'binary' is undefined for types that do not have fixed bitsize,+-- e.g. for 'Integer'.+binary :: (Bits a) => a -> a+binary 0 = 0+binary n =+  binary' mask0 n (copyMSB n)+  where+    sz = bitSize n - 1+    mask0 = let m = setBit 0 sz in  (m, m)+    copyMSB n = (setBit 0 sz) .&. n++binary' (maskReady, maskLast) ngray nbin+  | complement maskReady == 0 = nbin+  | otherwise =+     let+       sz = bitSize ngray - 1+       nReady = maskReady .&. nbin+       maskReady' = setBit (shiftR maskReady 1) sz+       maskLast' = shiftR' maskLast 1+       nNext = (shiftR' (maskLast .&. nReady) 1) `xor` (maskLast' .&. ngray)+     in+       binary' (maskReady', maskLast') ngray (nReady .|. nNext)++-- | Render binary code as a string of @0@s and @1@s.+-- For example, @(42::Int8)@ is formatted as @101010@.+showBits :: (Bits a) => a -> String+showBits = L.showBits . L.toList
+ Codec/Binary/Gray/List.hs view
@@ -0,0 +1,57 @@+-- | Gray code is a binary numeral system where two successive numbers+-- differ in only one bit.+--+-- This module provides an interface to encode/decode numbers+-- represented as lists of @Bool@.+--+-- Algorithm:+--   Haupt, R.L. and Haupt, S.E., Practical Genetic Algorithms,+--   Second ed. (2004),  5.4. Gray Codes.+module Codec.Binary.Gray.List+    ( gray, binary+    , toList, fromList+    , showBits+    ) where++import Data.Bits (Bits, testBit, bitSize, shiftR, isSigned)++boolXOR :: Bool -> Bool -> Bool+boolXOR p q = (p && not q) || (not p && q)++-- | Take a list of bits (most significant last) in binary encoding+-- and convert them to Gray code.+gray :: [Bool] -> [Bool]+gray (b:c:bs) = b `boolXOR` c : gray (c:bs)+gray [b] = [b]+gray [] = []++-- | Take a list of bits in Gray code and convert them to binary encoding+-- (most significant bit last).+binary :: [Bool] -> [Bool]+binary = foldr go []+  where go c [] = [c]+        go c bs@(b:_) = b `boolXOR` c : bs++-- | Convert a number to a list of bits in usual binary encoding (most+-- significant last).+-- +-- This function is undefined for negative numbers of types that do not+-- have fixed bitsize, like 'Integer'.+toList :: (Bits b) => b -> [Bool]+toList 0 = []+toList i+  | isSigned i && signum i == (-1) =+      let b = map not . toList $ negate i - 1+      in  b ++ (take (bitSize i - length b) $ repeat True) -- pad major bits+  | otherwise        =+      let rest = toList $ shiftR i 1  -- works only for positive i+      in  (testBit i 0 : rest)++-- | Convert a list of bits in binary encoding to a number.+fromList :: (Bits b) => [Bool] -> b+fromList = sum . map fst . filter snd . zip (map (2^) [0..])++-- | Render a list of bits as a string of @0@s and @1@s.+showBits :: [Bool] -> String+showBits [] = "0"+showBits bs = map (\b -> if b then '1' else '0') . reverse $ bs
Codec/Binary/Gray_props.hs view
@@ -2,46 +2,52 @@ module Codec.Binary.Gray_props where  import Test.QuickCheck-import Codec.Binary.Gray+import qualified Codec.Binary.Gray.Bits as B+import qualified Codec.Binary.Gray.List as L  import Data.Bits (testBit, bitSize, Bits)+import Data.Function (on) -prop_num2bin2num_id_Int =-  label "binaryToBits . bitsToBinary == id [Int]" $+---+--- Properties of list-based functions+---++prop_lists_num2bin_id_Int =+  label "fromList . toList == id [Int]" $   forAll (arbitrary :: Gen Int) $ \i ->-      i == (binaryToBits . bitsToBinary $ i)+      i == (L.fromList . L.toList $ i) -prop_num2bin2num_id_Integer =-  label "binaryToBits . bitsToBinary == id [Integer+]" $-  let i = (arbitrary :: Gen Integer) `suchThat` (>= 0)-  in  forAll i (\i -> i == (binaryToBits . bitsToBinary $ i))+prop_lists_num2bin_id_Integer =+  label "fromList . toList == id [Integer+]" $+  let i = (arbitrary :: Gen (NonNegative Integer))+  in  forAll i (\(NonNegative i) -> i == (L.fromList . L.toList $ i)) -prop_correct_bits_Int =-  label "bitsToBinary is correct [Int]" $+prop_lists_correct_bits_Int =+  label "toList is correct [Int]" $   forAll (arbitrary :: Gen Int) $ \i ->       let bts = map (testBit i) [0..(bitSize i)-1]-          padded = (bitsToBinary i) ++ (repeat False)+          padded = (L.toList i) ++ (repeat False)       in  all id $ zipWith (==) bts padded -prop_bin2gray2bin_id =-  label "grayToBinary . binaryToGray == binaryToGray . grayToBinary == id" $+prop_lists_bin2gray_id =+  label "binary . gray == gray . binary == id" $   forAll (listOf $ (arbitrary :: Gen Bool)) $ \bs ->-      bs == (grayToBinary . binaryToGray $ bs) &&-      bs == (binaryToGray . grayToBinary $ bs)+      bs == (L.binary . L.gray $ bs) &&+      bs == (L.gray . L.binary $ bs) -prop_gray_succ_Integer =-  label "Two successive numbers differ in only one bit [Integer+]" $-  let i = (arbitrary :: Gen Integer) `suchThat` (>= 0)-  in  forAll i succ_test+prop_lists_gray_succ_Integer =+  label "hamming x (x+1) == 1 [Integer+]" $+  let i = (arbitrary :: Gen (NonNegative Integer))+  in  forAll i $ \(NonNegative i) -> succ_test i -prop_gray_succ_Int =-  label "Two successive numbers differ in only one bit [Int]" $+prop_lists_gray_succ_Int =+  label "hamming x (x+1) == 1 [Int]" $   let i = (arbitrary :: Gen Int)   in  forAll i succ_test  succ_test :: (Bits a) => a -> Bool succ_test = \i ->-      let n2g = binaryToGray . bitsToBinary+      let n2g = L.gray . L.toList           g1 = n2g i           g2 = n2g (i+1)       in  hamming g1 g2 == 1@@ -57,10 +63,46 @@            then go d xs ys            else go (d+1) xs ys +---+--- Properties of functions for Bits types+---+prop_bits_id = label "binary . gray == gray . binary == id" $+  forAll (arbitrary :: Gen Int) $ \i ->+      (B.binary . B.gray $ i) == i && (B.gray . B.binary $ i) == i++prop_bits_same_as_lists =+  label "bitsToBinary . gray == binaryToGray . bitsToBinary [Int]" $+  forAll (arbitrary :: Gen Int) $ \i ->+      (L.gray . L.toList $ i) == (L.toList . B.gray $ i)++prop_bits_gray_succ_Int = label "hamming x (x+1) == 1 [Int]" $+  forAll (arbitrary :: Gen Int) $ \i ->+      (hammingBits `on` B.gray) i (i+1) == 1+     +prop_bits_gray_succ_Integer = label "hamming x (x+1) == 1 [Integer]" $+  forAll (arbitrary :: Gen (NonNegative Integer)) $ \(NonNegative i) ->+      (hammingBits `on` B.gray) i (i+1) == 1+     +hammingBits :: (Bits a) => a -> a -> Int+hammingBits = hamming `on` L.toList++---+--- Test groups+---++prop_lists = label "[Bool]" $+  prop_lists_num2bin_id_Int .&.+  prop_lists_num2bin_id_Integer .&.+  prop_lists_correct_bits_Int .&.+  prop_lists_bin2gray_id .&.+  prop_lists_gray_succ_Int .&.+  prop_lists_gray_succ_Integer++prop_bits = label "Bits" $+  prop_bits_id .&.+  prop_bits_same_as_lists .&.+  prop_bits_gray_succ_Int .&.+  prop_bits_gray_succ_Integer+ all_props =-  prop_num2bin2num_id_Int .&.-  prop_num2bin2num_id_Integer .&.-  prop_correct_bits_Int .&.-  prop_bin2gray2bin_id .&.-  prop_gray_succ_Int .&.-  prop_gray_succ_Integer+  prop_lists .&. prop_bits
gray-code.cabal view
@@ -7,7 +7,7 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.1+Version:             0.2  -- A short (one-line) description of the package. Synopsis:            Gray code encoder/decoder.@@ -15,8 +15,12 @@ -- A longer description of the package. Description:    Gray code is a binary numeral system where two successive numbers-   differ in only one bit. This package allows to convert Haskell-   numbers to one of the possible Gray codes and back.+   differ in only one bit.+   .+   This package allows to convert numbers to one of the possible Gray+   codes and back. Two binary representations of a number are supported:+   @[Bool]@ and types of @Bits@ type class.+   @Bits@ is the default implementation.  -- URL for the project homepage or repository. Homepage:            http://bitbucket.org/jetxee/hs-gray-code@@ -57,6 +61,8 @@   -- Modules exported by the library.   Exposed-modules:      Codec.Binary.Gray+     , Codec.Binary.Gray.Bits+     , Codec.Binary.Gray.List    -- Packages needed in order to build this package.   Build-depends: