bv-little 1.1.1 → 1.3.0
raw patch · 19 files changed
+3008/−2756 lines, 19 filesdep +binarydep −transformersdep ~QuickCheckdep ~basedep ~criterionPVP ok
version bump matches the API change (PVP)
Dependencies added: binary
Dependencies removed: transformers
Dependency ranges changed: QuickCheck, base, criterion, deepseq, hashable, integer-gmp, keys, mono-traversable, mono-traversable-keys, primitive, smallcheck, tasty, tasty-hunit, tasty-quickcheck, tasty-smallcheck, text-show
API changes (from Hackage documentation)
- Data.BitVector.LittleEndian: instance Control.DeepSeq.NFData Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.Bits.Bits Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.Bits.FiniteBits Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.Data.Data Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.Hashable.Class.Hashable Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoAdjustable Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoFoldableWithKey Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoIndexable Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoKeyed Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoLookup Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoTraversableWithKey Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoZip Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.Keys.MonoZipWithKey Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.MonoFoldable Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.MonoFunctor Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Data.MonoTraversable.MonoTraversable Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance GHC.Base.Monoid Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance GHC.Base.Semigroup Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance GHC.Classes.Eq Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance GHC.Classes.Ord Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance GHC.Generics.Generic Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance GHC.Show.Show Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Test.QuickCheck.Arbitrary.Arbitrary Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance Test.QuickCheck.Arbitrary.CoArbitrary Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: instance TextShow.Classes.TextShow Data.BitVector.LittleEndian.BitVector
- Data.BitVector.LittleEndian: data BitVector
+ Data.BitVector.LittleEndian: data () => BitVector
Files
- README.md +6/−7
- bench/Benchmarks.hs +152/−125
- bench/HeapStack.hs +71/−266
- bv-little.cabal +291/−166
- changelog.md +30/−10
- src/Data/BitVector/LittleEndian.hs +54/−1341
- src/core/Data/BitVector/LittleEndian/Internal.hs +831/−0
- src/full/Data/BitVector/LittleEndian/Instances.hs +22/−0
- src/keys/Data/BitVector/LittleEndian/MonoKeyed.hs +236/−0
- src/libs/Data/BitVector/LittleEndian/Binary.hs +33/−0
- src/libs/Data/BitVector/LittleEndian/MonoTraversable.hs +296/−0
- src/libs/Data/BitVector/LittleEndian/QuickCheck.hs +80/−0
- src/libs/Data/BitVector/LittleEndian/TextShow.hs +29/−0
- stack.yaml +8/−3
- test/Data/BitVector/Visual.hs +78/−68
- test/TestSuite.hs +483/−513
- util/Operator/Binary/Comparison.hs +45/−29
- util/Operator/Binary/Logical.hs +181/−161
- util/Operator/Unary/Logical.hs +82/−67
README.md view
@@ -1,6 +1,7 @@ ## Efficient little-endian bit vector Haskell library [](https://travis-ci.org/recursion-ninja/bv-little)+[](https://github.com/recursion-ninja/bv-little/actions) [](https://coveralls.io/github/recursion-ninja/bv-little?branch=master) [](http://opensource.org/licenses/BSD-3-Clause) @@ -11,31 +12,29 @@ [](http://stackage.org/nightly/package/bv-little) -This package contains an efficient implementation of *little-endian, immutable* bit vectors. It implements most applicable typeclasses and also conversions to and from signed or unsigned numbers.+This package contains an efficient implementation of *little-endian, immutable* bit vectors. It implements most applicable type-classes and also conversions to and from signed or unsigned numbers. For an implementation of *big-endian, immutable* bit vectors, use the [`bv`](https://hackage.haskell.org/package/bv) package. For an implementation of *little-endian, mutable* bit vectors, use the [`bitvec`](https://hackage.haskell.org/package/bitvec) package. + #### Tests -The test suite ensures that all typeclass instances are "lawful" and that data-structure–specific functionality is well defined.+The test suite ensures that all type-class instances are "lawful" and that data-structure–specific functionality is well defined. The `TestSuite.hs` file contains the specification. It can be run by invoking any of the following commands: - * `cabal new-test`- * `cabal test` * `stack test` + #### Benchmarks The benchmarks provide an empyrical check for the asymptotic complexity of data structure operations and also provide easy metrics for detecting performance regressions. -The `Benchmaks.hs` file contains these metrics. It can be run by invoking any of the following commands:-- * `cabal new-bench`+The `Benchmarks.hs` file contains these metrics. It can be run by invoking any of the following commands: * `cabal bench`
bench/Benchmarks.hs view
@@ -1,31 +1,46 @@-{-# LANGUAGE BangPatterns #-}+{-| -module Main (main) where+Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable +-}++{-# Language BangPatterns #-}++module Main+ ( main+ ) where+ import Control.DeepSeq import Criterion.Main-import Data.Bits import Data.BitVector.LittleEndian-import Data.List (nubBy)+import Data.BitVector.LittleEndian.Instances ()+import Data.Bits import Data.Hashable+import Data.List (nubBy) import Data.MonoTraversable-import Data.Semigroup import Operator.Binary.Logical import Operator.Unary.Logical +{-|+Complete /runtime/ benchmarking suite for the 'BitVector' type.+-} main :: IO ()-main = defaultMain [ benchmarks ]+main = defaultMain [benchmarks] benchmarks :: Benchmark-benchmarks = bgroup "BitVector"+benchmarks = bgroup+ "BitVector" [ toBitsBench , fromBitsBench , fromNumberBench , toSignedNumberBench , toUnsignedNumberBench- , dimmensionBench+ , dimensionBench , isZeroVectorBench , zeroPopCountBench , subRangeBench@@ -66,7 +81,8 @@ -- -- ceiling ( log_2 (pi * 10^100) ) === 334 largeNumber :: Integer-largeNumber = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679+largeNumber =+ 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 -- |@@ -74,7 +90,8 @@ -- -- ceiling ( log_2 (√2 * 10^200) ) === 665 hugeNumber :: Integer-hugeNumber = 14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605715+hugeNumber =+ 14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605715 toBitsBench :: Benchmark@@ -83,17 +100,19 @@ fromBitsBench :: Benchmark fromBitsBench = constantNumberTimeBenchmark "fromBits" id g- where- g int n = let !bitCount = fromEnum $ logBase2Word int- bitStream = force $ foldMap (\i -> [testBit n i]) [0 .. bitCount - 1]- in fromBits bitStream+ where+ g :: Bits b => Integer -> b -> BitVector+ g int n =+ let !bitCount = fromEnum $ logBase2Word int+ bitStream = force $ foldMap (\i -> [testBit n i]) [0 .. bitCount - 1]+ in fromBits bitStream fromNumberBench :: Benchmark fromNumberBench = constantNumberTimeBenchmark "fromNumber" id g- where- g int = let !bitCount = logBase2Word int- in fromNumber bitCount+ where+ g :: Integral i => Integer -> i -> BitVector+ g int = let !bitCount = logBase2Word int in fromNumber bitCount toSignedNumberBench :: Benchmark@@ -104,50 +123,59 @@ toUnsignedNumberBench = unaryBenchmark "toUnsignedNumber" (toUnsignedNumber :: BitVector -> Integer) -dimmensionBench :: Benchmark-dimmensionBench = constantNumberTimeBenchmark "dimmension" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- in dimension bitVector- +dimensionBench :: Benchmark+dimensionBench = constantNumberTimeBenchmark "dimension" id g+ where+ g :: Integer -> a -> Word+ g int _ =+ let !bitCount = logBase2Word int+ !bitVector = fromNumber bitCount int+ in dimension bitVector + isZeroVectorBench :: Benchmark isZeroVectorBench = constantNumberTimeBenchmark "isZeroVector" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- in isZeroVector bitVector- + where+ g :: Integer -> a -> Bool+ g int _ =+ let !bitCount = logBase2Word int+ !bitVector = fromNumber bitCount int+ in isZeroVector bitVector + zeroPopCountBench :: Benchmark zeroPopCountBench = constantNumberTimeBenchmark "popCount is zero" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- in ((0==) . popCount) bitVector- + where+ g :: Integer -> a -> Bool+ g int _ =+ let !bitCount = logBase2Word int+ !bitVector = fromNumber bitCount int+ in ((0 ==) . popCount) bitVector + subRangeBench :: Benchmark subRangeBench = constantNumberTimeBenchmark "subRange" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- !lowerBound = bitCount `div` 4- !upperBound = (bitCount * 3) `div` 4- in (lowerBound, upperBound) `subRange` bitVector- + where+ g :: Integer -> a -> BitVector+ g int _ =+ let !bitCount = logBase2Word int+ !bitVector = fromNumber bitCount int+ !lowerBound = bitCount `div` 4+ !upperBound = (bitCount * 3) `div` 4+ in (lowerBound, upperBound) `subRange` bitVector + bitsBench :: Benchmark-bitsBench = bgroup "Bits"- [ binaryBenchmark "(.|.)" (.|.)- , binaryBenchmark "(.&.)" (.&.)- , binaryBenchmark "xor" xor- , unaryBenchmark "complement" complement+bitsBench = bgroup+ "Bits"+ [ binaryBenchmark "(.|.)" (.|.)+ , binaryBenchmark "(.&.)" (.&.)+ , binaryBenchmark "xor" xor+ , unaryBenchmark "complement" complement -- , unaryBenchmark "bitSize" bitSize- , unaryBenchmark "bitSizeMaybe" bitSizeMaybe- , unaryBenchmark "isSigned" isSigned- , unaryBenchmark "popCount" popCount+ , unaryBenchmark "bitSizeMaybe" bitSizeMaybe+ , unaryBenchmark "isSigned" isSigned+ , unaryBenchmark "popCount" popCount , indexingBenchmark "shift" shift , indexingBenchmark "shiftL" shiftL , indexingBenchmark "shiftR" shiftR@@ -162,7 +190,8 @@ finiteBitsBench :: Benchmark-finiteBitsBench = bgroup "FiniteBits"+finiteBitsBench = bgroup+ "FiniteBits" [ unaryBenchmark "finiteBitSize" finiteBitSize , unaryBenchmark "countLeadingZeros" countLeadingZeros , unaryBenchmark "countTrailingZeros" countLeadingZeros@@ -170,108 +199,106 @@ hashableBench :: Benchmark-hashableBench = bgroup "Hashable"- [ unaryBenchmark "hash" hash- , indexingBenchmark "hashWithSalt" (flip hashWithSalt)- ]- +hashableBench =+ bgroup "Hashable" [unaryBenchmark "hash" hash, indexingBenchmark "hashWithSalt" (flip hashWithSalt)] + semigroupBench :: Benchmark-semigroupBench = bgroup "Semigroup"- [ binaryBenchmark "(<>)" (<>)- ]- +semigroupBench = bgroup "Semigroup" [binaryBenchmark "(<>)" (<>)] + monoFoldableBench :: Benchmark-monoFoldableBench = bgroup "MonoFoldable"+monoFoldableBench = bgroup+ "MonoFoldable" [ fold1Benchmark "ofoldr1Ex" ofoldr1Ex , fold1Benchmark "ofoldl1Ex'" ofoldl1Ex'- , mapBenchmark "omap" omap- , queryBenchmark "oall" oall - , queryBenchmark "oany" oany + , mapBenchmark "omap" omap+ , queryBenchmark "oall" oall+ , queryBenchmark "oany" oany ] -constantNumberTimeBenchmark :: (NFData a, NFData b) => String -> (Integer -> a) -> (Integer -> a -> b) -> Benchmark-constantNumberTimeBenchmark label f g = bgroup label $ generateBenchmark <$> magicNumbers- where- generateBenchmark (intLabel, intValue) = bench intLabel $ nf app target- where- !target = force $ f intValue- !app = g intValue+constantNumberTimeBenchmark+ :: (NFData a, NFData b) => String -> (Integer -> a) -> (Integer -> a -> b) -> Benchmark+constantNumberTimeBenchmark label f g = bgroup label $ generateBenchmark <$> magicNumbers+ where+ generateBenchmark (intLabel, intValue) = bench intLabel $ nf app target+ where+ !target = force $ f intValue+ !app = g intValue - + unaryBenchmark :: NFData a => String -> (BitVector -> a) -> Benchmark unaryBenchmark label f = bgroup label $ generateBenchmark <$> magicNumbers- where- generateBenchmark (intLabel, intValue) = bench intLabel $ nf f target- where- !target = bvGen intValue+ where+ generateBenchmark (intLabel, intValue) = bench intLabel $ nf f target where !target = bvGen intValue - + binaryBenchmark :: NFData a => String -> (BitVector -> BitVector -> a) -> Benchmark binaryBenchmark label op = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel1, intValue1, intLabel2, intValue2) = bench message $ nf id target- where- message = unwords [intLabel1, "`op`", intLabel2]- !lhs = bvGen intValue1- !rhs = bvGen intValue2- target = lhs `op` rhs- combinations = [ (a,b,c,d) | (a,b) <- magicNumbers, (c,d) <- magicNumbers, b < d ]+ where+ generateBenchmark (intLabel1, intValue1, intLabel2, intValue2) = bench message $ nf id target+ where+ message = unwords [intLabel1, "`op`", intLabel2]+ !lhs = bvGen intValue1+ !rhs = bvGen intValue2+ target = lhs `op` rhs+ combinations = [ (a, b, c, d) | (a, b) <- magicNumbers, (c, d) <- magicNumbers, b < d ] indexingBenchmark :: NFData a => String -> (BitVector -> Int -> a) -> Benchmark indexingBenchmark label op = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, idxLabel, idxValue) = bench message $ nf app target- where- message = unwords [intLabel, "@", idxLabel <> ":" <> show idxValue]- !target = bvGen intValue- app = (`op` idxValue)+ where+ generateBenchmark (intLabel, intValue, idxLabel, idxValue) = bench message $ nf app target+ where+ message = unwords [intLabel, "@", idxLabel <> ":" <> show idxValue]+ !target = bvGen intValue+ app = (`op` idxValue) - combinations = do- (a, b) <- magicNumbers- let bitCount = fromEnum $ logBase2Word b- (c, d) <- nubBy (\x y -> snd x == snd y) [("first", 0), ("middle", bitCount `div` 2), ("last", bitCount - 1)]- let e = force (a,b,c,d)- [e]+ combinations = do+ (a, b) <- magicNumbers+ let bitCount = fromEnum $ logBase2Word b+ (c, d) <- nubBy+ (\x y -> snd x == snd y)+ [("first", 0), ("middle", bitCount `div` 2), ("last", bitCount - 1)]+ let e = force (a, b, c, d)+ [e] fold1Benchmark :: String -> ((Bool -> Bool -> Bool) -> BitVector -> Bool) -> Benchmark fold1Benchmark label fold1Fun = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target- where- message = unwords ["fold1", getBinaryLogicalSymbol lOp, intLabel]- !op = getBinaryLogicalOperator lOp- !bv = bvGen intValue- target = fold1Fun op bv- combinations = [ (a,b, op) | (a,b) <- magicNumbers, op <- [minBound .. maxBound] ]+ where+ generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target+ where+ message = unwords ["fold1", getBinaryLogicalSymbol lOp, intLabel]+ !op = getBinaryLogicalOperator lOp+ !bv = bvGen intValue+ target = fold1Fun op bv+ combinations = [ (a, b, op) | (a, b) <- magicNumbers, op <- [minBound .. maxBound] ] mapBenchmark :: String -> ((Bool -> Bool) -> BitVector -> BitVector) -> Benchmark mapBenchmark label mapFun = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target- where- message = unwords ["map", getUnaryLogicalSymbol lOp, intLabel]- !op = getUnaryLogicalOperator lOp- !bv = bvGen intValue- target = mapFun op bv- combinations = [ (a,b, op) | (a,b) <- magicNumbers, op <- [minBound .. maxBound] ]+ where+ generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target+ where+ message = unwords ["map", getUnaryLogicalSymbol lOp, intLabel]+ !op = getUnaryLogicalOperator lOp+ !bv = bvGen intValue+ target = mapFun op bv+ combinations = [ (a, b, op) | (a, b) <- magicNumbers, op <- [minBound .. maxBound] ] queryBenchmark :: String -> ((Bool -> Bool) -> BitVector -> Bool) -> Benchmark queryBenchmark label mapFun = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target- where- message = unwords ["query", getUnaryLogicalSymbol lOp, intLabel]- !op = getUnaryLogicalOperator lOp- !bv = bvGen intValue- target = mapFun op bv- combinations = [ (a,b, op) | (a,b) <- magicNumbers, op <- [minBound .. maxBound] ]+ where+ generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target+ where+ message = unwords ["query", getUnaryLogicalSymbol lOp, intLabel]+ !op = getUnaryLogicalOperator lOp+ !bv = bvGen intValue+ target = mapFun op bv+ combinations = [ (a, b, op) | (a, b) <- magicNumbers, op <- [minBound .. maxBound] ] bvGen :: Integer -> BitVector@@ -284,10 +311,10 @@ magicNumbers :: [(String, Integer)] magicNumbers =- [ ("zero" , 0)- , ("tiny" , tinyNumber)- , ("small" , smallNumber)+ [ ("zero" , 0)+ , ("tiny" , tinyNumber)+ , ("small" , smallNumber) , ("medium", mediumNumber)- , ("large" , largeNumber)- , ("huge" , hugeNumber)+ , ("large" , largeNumber)+ , ("huge" , hugeNumber) ]
bench/HeapStack.hs view
@@ -1,287 +1,89 @@-{-# LANGUAGE BangPatterns #-}+{-| -module Main (main) where+Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable +-}++{-# Language BangPatterns #-}++module Main+ ( main+ ) where+ import Control.DeepSeq import Control.Exception-import Criterion.Main-import Data.Bits import Data.BitVector.LittleEndian+import Data.BitVector.LittleEndian.Instances ()+import Data.Bits import Data.Foldable import Data.List (nubBy)-import Data.Hashable-import Data.MonoTraversable-import Data.Semigroup import Numeric.Natural-import Operator.Binary.Logical-import Operator.Unary.Logical +{-|+Complete /memory/ benchmarking suite for the 'BitVector' type.+-} main :: IO ()-main = sequenceA_- [ traverse_ (evaluate . force) actions- , traverse_ (evaluate . force) other- ]+main = sequenceA_ [traverse_ (evaluate . force) actions, traverse_ (evaluate . force) other] other :: [[[Word]]]-other =- [ pure <$> indexingBenchmarkW rank- , toList <$> indexingBenchmarkW select- ]+other = [pure <$> indexingBenchmarkW rank, toList <$> indexingBenchmarkW select] -actions :: [[ BitVector ]]-actions = fold $ replicate (10^7)- [ indexingBenchmark shift- , indexingBenchmark shiftL- , indexingBenchmark shiftR- , indexingBenchmark rotate- , indexingBenchmark rotateL- , indexingBenchmark rotateR- , indexingBenchmark setBit- , indexingBenchmark clearBit+actions :: [[BitVector]]+actions = fold $ replicate+ (10 ^ 7)+ [ indexingBenchmark shift+ , indexingBenchmark shiftL+ , indexingBenchmark shiftR+ , indexingBenchmark rotate+ , indexingBenchmark rotateL+ , indexingBenchmark rotateR+ , indexingBenchmark setBit+ , indexingBenchmark clearBit , indexingBenchmark complementBit -- , indexingBenchmark testBit ] --benchmarks :: Benchmark-benchmarks = bgroup "BitVector"- [ toBitsBench- , fromBitsBench- , fromNumberBench- , toSignedNumberBench- , toUnsignedNumberBench- , dimmensionBench- , isZeroVectorBench- , zeroPopCountBench- , subRangeBench--- , bitsBench- , finiteBitsBench- , hashableBench- , semigroupBench- , monoFoldableBench- ]---indexingBenchmark' :: NFData a => String -> (BitVector -> Int -> a) -> Benchmark-indexingBenchmark' = undefined---toBitsBench :: Benchmark-toBitsBench = unaryBenchmark "toBitsNumber" toBits---fromBitsBench :: Benchmark-fromBitsBench = constantNumberTimeBenchmark "fromBits" id g- where- g int n = let !bitCount = fromEnum $ logBase2Word int- bitStream = force $ foldMap (\i -> [testBit n i]) [0 .. bitCount - 1]- in fromBits bitStream---fromNumberBench :: Benchmark-fromNumberBench = constantNumberTimeBenchmark "fromNumber" id g- where- g int = let !bitCount = logBase2Word int- in fromNumber bitCount---toSignedNumberBench :: Benchmark-toSignedNumberBench = unaryBenchmark "toSignedNumber" (toSignedNumber :: BitVector -> Natural)---toUnsignedNumberBench :: Benchmark-toUnsignedNumberBench = unaryBenchmark "toUnsignedNumber" (toUnsignedNumber :: BitVector -> Natural)---dimmensionBench :: Benchmark-dimmensionBench = constantNumberTimeBenchmark "dimmension" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- in dimension bitVector- --isZeroVectorBench :: Benchmark-isZeroVectorBench = constantNumberTimeBenchmark "isZeroVector" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- in isZeroVector bitVector- --zeroPopCountBench :: Benchmark-zeroPopCountBench = constantNumberTimeBenchmark "popCount is zero" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- in ((0==) . popCount) bitVector- --subRangeBench :: Benchmark-subRangeBench = constantNumberTimeBenchmark "subRange" id g- where- g int _ = let !bitCount = logBase2Word int- !bitVector = fromNumber bitCount int- !lowerBound = bitCount `div` 4- !upperBound = (bitCount * 3) `div` 4- in (lowerBound, upperBound) `subRange` bitVector- --{--bitsBench :: Benchmark-bitsBench = bgroup "Bits"- [ binaryBenchmark "(.|.)" (.|.)- , binaryBenchmark "(.&.)" (.&.)- , binaryBenchmark "xor" xor- , unaryBenchmark "complement" complement--- , unaryBenchmark "bitSize" bitSize- , unaryBenchmark "bitSizeMaybe" bitSizeMaybe- , unaryBenchmark "isSigned" isSigned- , unaryBenchmark "popCount" popCount- , indexingBenchmark "shift" shift- , indexingBenchmark "shiftL" shiftL- , indexingBenchmark "shiftR" shiftR- , indexingBenchmark "rotate" rotate- , indexingBenchmark "rotateL" rotateL- , indexingBenchmark "rotateR" rotateR- , indexingBenchmark "setBit" setBit- , indexingBenchmark "clearBit" clearBit- , indexingBenchmark "complementBit" complementBit- , indexingBenchmark "testBit" testBit- ]--}---finiteBitsBench :: Benchmark-finiteBitsBench = bgroup "FiniteBits"- [ unaryBenchmark "finiteBitSize" finiteBitSize- , unaryBenchmark "countLeadingZeros" countLeadingZeros- , unaryBenchmark "countTrailingZeros" countLeadingZeros- ]---hashableBench :: Benchmark-hashableBench = bgroup "Hashable"- [ unaryBenchmark "hash" hash- , indexingBenchmark' "hashWithSalt" (flip hashWithSalt)- ]- --semigroupBench :: Benchmark-semigroupBench = bgroup "Semigroup"- [ binaryBenchmark "(<>)" (<>)- ]- --monoFoldableBench :: Benchmark-monoFoldableBench = bgroup "MonoFoldable"- [ fold1Benchmark "ofoldr1Ex" ofoldr1Ex- , fold1Benchmark "ofoldl1Ex'" ofoldl1Ex'- , mapBenchmark "omap" omap- , queryBenchmark "oall" oall - , queryBenchmark "oany" oany - ]---constantNumberTimeBenchmark :: (NFData a, NFData b) => String -> (Natural -> a) -> (Natural -> a -> b) -> Benchmark-constantNumberTimeBenchmark label f g = bgroup label $ generateBenchmark <$> magicNumbers- where- generateBenchmark (intLabel, intValue) = bench intLabel $ nf app target- where- !target = force $ f intValue- !app = g intValue-- -unaryBenchmark :: NFData a => String -> (BitVector -> a) -> Benchmark-unaryBenchmark label f = bgroup label $ generateBenchmark <$> magicNumbers- where- generateBenchmark (intLabel, intValue) = bench intLabel $ nf f target- where- !target = bvGen intValue-- -binaryBenchmark :: NFData a => String -> (BitVector -> BitVector -> a) -> Benchmark-binaryBenchmark label op = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel1, intValue1, intLabel2, intValue2) = bench message $ nf id target- where- message = unwords [intLabel1, "`op`", intLabel2]- !lhs = bvGen intValue1- !rhs = bvGen intValue2- target = lhs `op` rhs- combinations = [ (a,b,c,d) | (a,b) <- magicNumbers, (c,d) <- magicNumbers, b < d ]---indexingBenchmark :: NFData a => (BitVector -> Int -> a) -> [a]+indexingBenchmark :: (BitVector -> Int -> a) -> [a] indexingBenchmark op = generateBenchmark <$> combinations- where- generateBenchmark (intValue, idxValue) = app target- where- !target = bvGen intValue- app = (`op` idxValue)+ where+ generateBenchmark (intValue, idxValue) = app target+ where+ !target = bvGen intValue+ app = (`op` idxValue) - combinations = do- (_, b) <- magicNumbers- let bitCount = fromEnum $ logBase2Word b- (_, d) <- nubBy (\x y -> snd x == snd y) [("first", 0), ("middle", bitCount `div` 2), ("last", bitCount - 1)]- let e = force (b,d)- [e]+ combinations = do+ (_, b) <- magicNumbers+ let bitCount = fromEnum $ logBase2Word b+ (_, d) <- nubBy+ (\x y -> snd x == snd y)+ [("first", 0), ("middle", bitCount `div` 2), ("last", bitCount - 1)]+ let e = force (b, d)+ [e] -indexingBenchmarkW :: NFData a => (BitVector -> Word -> a) -> [a]+indexingBenchmarkW :: (BitVector -> Word -> a) -> [a] indexingBenchmarkW op = generateBenchmark <$> combinations- where- generateBenchmark (intValue, idxValue) = app target- where- !target = bvGen intValue- app = (`op` idxValue)-- combinations = do- (_, b) <- magicNumbers- let bitCount = fromEnum $ logBase2Word b- (_, d) <- nubBy (\x y -> snd x == snd y) [("first", 0), ("middle", bitCount `div` 2), ("last", bitCount - 1)]- let e = force (b, toEnum d)- [e]---fold1Benchmark :: String -> ((Bool -> Bool -> Bool) -> BitVector -> Bool) -> Benchmark-fold1Benchmark label fold1Fun = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target- where- message = unwords ["fold1", getBinaryLogicalSymbol lOp, intLabel]- !op = getBinaryLogicalOperator lOp- !bv = bvGen intValue- target = fold1Fun op bv- combinations = [ (a,b, op) | (a,b) <- magicNumbers, op <- [minBound .. maxBound] ]---mapBenchmark :: String -> ((Bool -> Bool) -> BitVector -> BitVector) -> Benchmark-mapBenchmark label mapFun = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target- where- message = unwords ["map", getUnaryLogicalSymbol lOp, intLabel]- !op = getUnaryLogicalOperator lOp- !bv = bvGen intValue- target = mapFun op bv- combinations = [ (a,b, op) | (a,b) <- magicNumbers, op <- [minBound .. maxBound] ]-+ where+ generateBenchmark (intValue, idxValue) = app target+ where+ !target = bvGen intValue+ app = (`op` idxValue) -queryBenchmark :: String -> ((Bool -> Bool) -> BitVector -> Bool) -> Benchmark-queryBenchmark label mapFun = bgroup label $ generateBenchmark <$> combinations- where- generateBenchmark (intLabel, intValue, lOp) = bench message $ nf id target- where- message = unwords ["query", getUnaryLogicalSymbol lOp, intLabel]- !op = getUnaryLogicalOperator lOp- !bv = bvGen intValue- target = mapFun op bv- combinations = [ (a,b, op) | (a,b) <- magicNumbers, op <- [minBound .. maxBound] ]+ combinations = do+ (_, b) <- magicNumbers+ let bitCount = fromEnum $ logBase2Word b+ (_, d) <- nubBy+ (\x y -> snd x == snd y)+ [("first", 0), ("middle", bitCount `div` 2), ("last", bitCount - 1)]+ let e = force (b, toEnum d)+ [e] bvGen :: Natural -> BitVector@@ -294,12 +96,12 @@ magicNumbers :: [(String, Natural)] magicNumbers =- [ ("zero" , 0)- , ("tiny" , tinyNumber)- , ("small" , smallNumber)- , ("medium", mediumNumber)- , ("large" , largeNumber)- , ("huge" , hugeNumber)+ [ ("zero" , 0)+ , ("tiny" , tinyNumber)+ , ("small" , smallNumber)+ , ("medium" , mediumNumber)+ , ("large" , largeNumber)+ , ("huge" , hugeNumber) , ("colossal", colossalNumber) ] @@ -333,7 +135,8 @@ -- -- ceiling ( log_2 (pi * 10^100) ) === 334 largeNumber :: Natural-largeNumber = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679+largeNumber =+ 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 -- |@@ -341,10 +144,12 @@ -- -- ceiling ( log_2 (√2 * 10^200) ) === 665 hugeNumber :: Natural-hugeNumber = 14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605715+hugeNumber =+ 14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605715 -- | -- This number is colossal. colossalNumber :: Natural-colossalNumber = 1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678566722796619885782794848855834397518744545512965634434803966420557982936804352202770984294232533022576341807039476994159791594530069752148293366555661567873640053666564165473217043903521329543529169414599041608753201868379370234888689479151071637852902345292440773659495630510074210871426134974595615138498713757047101787957310422969066670214498637464595280824369445789772330048764765241339075920434019634039114732023380715095222010682563427471646024335440051521266932493419673977041595683753555166730273900749729736354964533288869844061196496162773449518273695588220757355176651589855190986665393549481068873206859907540792342402300925900701731960362254756478940647548346647760411463233905651343306844953979070903023460461470961696886885014083470405460742958699138296682468185710318879065287036650832431974404771855678934823089431068287027228097362480939962706074726455399253994428081137369433887294063079261595995462624629707062594845569034711972996409089418059534393251236235508134949004364278527138315912568989295196427287573946914272534366941532361004537304881985517065941217352462589548730167600298865925786628561249665523533829428785425340483083307016537228563559152534784459818313411290019992059813522051173365856407826484942764411376393866924803118364453698589175442647399882284621844900877769776312795722672655562596282542765318300134070922334365779160128093179401718598599933849235495640057099558561134980252499066984233017350358044081168552653117099570899427328709258487894436460050410892266917835258707859512983441729535195378855345737426085902908176515578039059464087350612322611200937310804854852635722825768203416050484662775045003126200800799804925485346941469775164932709504934639382432227188515974054702148289711177792376122578873477188196825462981268685817050740272550263329044976277894423621674119186269439650671515779586756482399391760426017633870454990176143641204692182370764887834196896861181558158736062938603810171215855272668300823834046564758804051380801633638874216371406435495561868964112282140753302655100424104896783528588290243670904887118190909494533144218287661810310073547705498159680772009474696134360928614849417850171807793068108546900094458995279424398139213505586422196483491512639012803832001097738680662877923971801461343244572640097374257007359210031541508936793008169980536520276007277496745840028362405346037263416554259027601834840306811381855105979705664007509426087885735796037324514146786703688098806097164258497595138069309449401515422221943291302173912538355915031003330325111749156969174502714943315155885403922164097229101129035521815762823283182342548326111912800928252561902052630163911477247331485739107775874425387611746578671169414776421441111263583553871361011023267987756410246824032264834641766369806637857681349204530224081972785647198396308781543221166912246415911776732253264335686146186545222681268872684459684424161078540167681420808850280054143613146230821025941737562389942075713627516745731891894562835257044133543758575342698699472547031656613991999682628247270641336222178923903176085428943733935618891651250424404008952719837873864805847268954624388234375178852014395600571048119498842390606136957342315590796703461491434478863604103182350736502778590897578272731305048893989009923913503373250855982655867089242612429473670193907727130706869170926462548423240748550366080136046689511840093668609546325002145852930950000907151058236267293264537382104938724996699339424685516483261134146110680267446637334375340764294026682973865220935701626384648528514903629320199199688285171839536691345222444708045923966028171565515656661113598231122506289058549145097157553900243931535190902107119457300243880176615035270862602537881797519478061013715004489917210022201335013106016391541589578037117792775225978742891917915522417189585361680594741234193398420218745649256443462392531953135103311476394911995072858430658361935369329699289837914941939406085724863968836903265564364216644257607914710869984315733749648835292769328220762947282381537409961545598798259891093717126218283025848112389011968221429457667580718653806506487026133892822994972574530332838963818439447707794022843598834100358385423897354243956475556840952248445541392394100016207693636846776413017819659379971557468541946334893748439129742391433659360410035234377706588867781139498616478747140793263858738624732889645643598774667638479466504074111825658378878454858148962961273998413442726086061872455452360643153710112746809778704464094758280348769758948328241239292960582948619196670918958089833201210318430340128495116203534280144127617285830243559830032042024512072872535581195840149180969253395075778400067465526031446167050827682772223534191102634163157147406123850425845988419907611287258059113935689601431668283176323567325417073420817332230462987992804908514094790368878687894930546955703072619009502076433493359106024545086453628935456862958531315337183868265617862273637169757741830239860065914816164049449650117321313895747062088474802365371031150898427992754426853277974311395143574172219759799359685252285745263796289612691572357986620573408375766873884266405990993505000813375432454635967504844235284874701443545419576258473564216198134073468541117668831186544893776979566517279662326714810338643913751865946730024434500544995399742372328712494834706044063471606325830649829795510109541836235030309453097335834462839476304775645015008507578949548931393944899216125525597701436858943585877526379625597081677643800125436502371412783467926101995585224717220177723700417808419423948725406801556035998390548985723546745642390585850216719031395262944554391316631345308939062046784387785054239390524731362012947691874975191011472315289326772533918146607300089027768963114810902209724520759167297007850580717186381054967973100167870850694207092232908070383263453452038027860990556900134137182368370991949516489600755049341267876436746384902063964019766685592335654639138363185745698147196210841080961884605456039038455343729141446513474940784884423772175154334260306698831768331001133108690421939031080143784334151370924353013677631084913516156422698475074303297167469640666531527035325467112667522460551199581831963763707617991919203579582007595605302346267757943936307463056901080114942714100939136913810725813781357894005599500183542511841721360557275221035268037357265279224173736057511278872181908449006178013889710770822931002797665935838758909395688148560263224393726562472776037890814458837855019702843779362407825052704875816470324581290878395232453237896029841669225489649715606981192186584926770403956481278102179913217416305810554598801300484562997651121241536374515005635070127815926714241342103301566165356024733807843028655257222753049998837015348793008062601809623815161366903341111386538510919367393835229345888322550887064507539473952043968079067086806445096986548801682874343786126453815834280753061845485903798217994599681154419742536344399602902510015888272164745006820704193761584547123183460072629339550548239557137256840232268213012476794522644820910235647752723082081063518899152692889108455571126603965034397896278250016110153235160519655904211844949907789992007329476905868577878720982901352956613978884860509786085957017731298155314951681467176959760994210036183559138777817698458758104466283998806006162298486169353373865787735983361613384133853684211978938900185295691967804554482858483701170967212535338758621582310133103877668272115726949518179589754693992642197915523385766231676275475703546994148929041301863861194391962838870543677743224276809132365449485366768000001065262485473055861598999140170769838548318875014293890899506854530765116803337322265175662207526951791442252808165171667766727930354851542040238174608923283917032754257508676551178593950027933895920576682789677644531840404185540104351348389531201326378369283580827193783126549617459970567450718332065034556644034490453627560011250184335607361222765949278393706478426456763388188075656121689605041611390390639601620221536849410926053876887148379895599991120991646464411918568277004574243434021672276445589330127781586869525069499364610175685060167145354315814801054588605645501332037586454858403240298717093480910556211671546848477803944756979804263180991756422809873998766973237695737015808068229045992123661689025962730430679316531149401764737693873514093361833216142802149763399189835484875625298752423873077559555955465196394401821840998412489826236737714672260616336432964063357281070788758164043814850188411431885988276944901193212968271588841338694346828590066640806314077757725705630729400492940302420498416565479736705485580445865720227637840466823379852827105784319753541795011347273625774080213476826045022851579795797647467022840999561601569108903845824502679265942055503958792298185264800706837650418365620945554346135134152570065974881916341359556719649654032187271602648593049039787489589066127250794828276938953521753621850796297785146188432719223223810158744450528665238022532843891375273845892384422535472653098171578447834215822327020690287232330053862163479885094695472004795231120150432932266282727632177908840087861480221475376578105819702226309717495072127248479478169572961423658595782090830733233560348465318730293026659645013718375428897557971449924654038681799213893469244741985097334626793321072686870768062639919361965044099542167627840914669856925715074315740793805323925239477557441591845821562518192155233709607483329234921034514626437449805596103307994145347784574699992128599999399612281615219314888769388022281083001986016549416542616968586788372609587745676182507275992950893180521872924610867639958916145855058397274209809097817293239301067663868240401113040247007350857828724627134946368531815469690466968693925472519413992914652423857762550047485295476814795467007050347999588867695016124972282040303995463278830695976249361510102436555352230690612949388599015734661023712235478911292547696176005047974928060721268039226911027772261025441492215765045081206771735712027180242968106203776578837166909109418074487814049075517820385653909910477594141321543284406250301802757169650820964273484146957263978842560084531214065935809041271135920041975985136254796160632288736181367373244506079244117639975974619383584574915988097667447093006546342423460634237474666080431701260052055928493695941434081468529815053947178900451835755154125223590590687264878635752541911288877371766374860276606349603536794702692322971868327717393236192007774522126247518698334951510198642698878471719396649769070825217423365662725928440620430214113719922785269984698847702323823840055655517889087661360130477098438611687052310553149162517283732728676007248172987637569816335415074608838663640693470437206688651275688266149730788657015685016918647488541679154596507234287730699853713904300266530783987763850323818215535597323530686043010675760838908627049841888595138091030423595782495143988590113185835840667472370297149785084145853085781339156270760356390763947311455495832266945702494139831634332378975955680856836297253867913275055542524491943589128405045226953812179131914513500993846311774017971512283785460116035955402864405902496466930707769055481028850208085800878115773817191741776017330738554758006056014337743299012728677253043182519757916792969965041460706645712588834697979642931622965520168797300035646304579308840327480771811555330909887025505207680463034608658165394876951960044084820659673794731680864156456505300498816164905788311543454850526600698230931577765003780704661264706021457505793270962047825615247145918965223608396645624105195510522357239739512881816405978591427914816542632892004281609136937773722299983327082082969955737727375667615527113922588055201898876201141680054687365580633471603734291703907986396522961312801782679717289822936070288069087768660593252746378405397691848082041021944719713869256084162451123980620113184541244782050110798760717155683154078865439041210873032402010685341947230476666721749869868547076781205124736792479193150856444775379853799732234456122785843296846647513336573692387201464723679427870042503255589926884349592876124007558756946413705625140011797133166207153715436006876477318675587148783989081074295309410605969443158477539700943988394914432353668539209946879645066533985738887866147629443414010498889931600512076781035886116602029611936396821349607501116498327856353161451684576956871090029997698412632665023477167286573785790857466460772283415403114415294188047825438761770790430001566986776795760909966936075594965152736349811896413043311662774712338817406037317439705406703109676765748695358789670031925866259410510533584384656023391796749267844763708474978333655579007384191473198862713525954625181604342253729962863267496824058060296421146386436864224724887283434170441573482481833301640566959668866769563491416328426414974533349999480002669987588815935073578151958899005395120853510357261373640343675347141048360175464883004078464167452167371904831096767113443494819262681110739948250607394950735031690197318521195526356325843390998224986240670310768318446607291248747540316179699411397387765899868554170318847788675929026070043212666179192235209382278788809886335991160819235355570464634911320859189796132791319756490976000139962344455350143464268604644958624769094347048293294140411146540923988344435159133201077394411184074107684981066347241048239358274019449356651610884631256785297769734684303061462418035852933159734583038455410337010916767763742762102137013548544509263071901147318485749233181672072137279355679528443925481560913728128406333039373562420016045664557414588166052166608738748047243391212955877763906969037078828527753894052460758496231574369171131761347838827194168606625721036851321566478001476752310393578606896111259960281839309548709059073861351914591819510297327875571049729011487171897180046961697770017913919613791417162707018958469214343696762927459109940060084983568425201915593703701011049747339493877885989417433031785348707603221982970579751191440510994235883034546353492349826883624043327267415540301619505680654180939409982020609994140216890900708213307230896621197755306659188141191577836272927461561857103721724710095214236964830864102592887457999322374955191221951903424452307535133806856807354464995127203174487195403976107308060269906258076020292731455252078079914184290638844373499681458273372072663917670201183004648190002413083508846584152148991276106513741539435657211390328574918769094413702090517031487773461652879848235338297260136110984514841823808120540996125274580881099486972216128524897425555516076371675054896173016809613803811914361143992106380050832140987604599309324851025168294467260666138151745712559754953580239983146982203613380828499356705575524712902745397762140493182014658008021566536067765508783804304134310591804606800834591136640834887408005741272586704792258319127415739080914383138456424150940849133918096840251163991936853225557338966953749026620923261318855891580832455571948453875628786128859004106006073746501402627824027346962528217174941582331749239683530136178653673760642166778137739951006589528877427662636841830680190804609849809469763667335662282915132352788806157768278159588669180238940333076441912403412022316368577860357276941541778826435238131905028087018575047046312933353757285386605888904583111450773942935201994321971171642235005644042979892081594307167019857469273848653833436145794634175922573898588001698014757420542995801242958105456510831046297282937584161162532562516572498078492099897990620035936509934721582965174135798491047111660791587436986541222348341887722929446335178653856731962559852026072947674072616767145573649812105677716893484917660771705277187601199908144113058645577910525684304811440261938402322470939249802933550731845890355397133088446174107959162511714864874468611247605428673436709046678468670274091881014249711149657817724279347070216688295610877794405048437528443375108828264771978540006509704033021862556147332117771174413350281608840351781452541964320309576018694649088681545285621346988355444560249556668436602922195124830910605377201980218310103270417838665447181260397190688462370857518080035327047185659499476124248110999288679158969049563947624608424065930948621507690314987020673533848349550836366017848771060809804269247132410009464014373603265645184566792456669551001502298330798496079949882497061723674493612262229617908143114146609412341593593095854079139087208322733549572080757165171876599449856937956238755516175754380917805280294642004472153962807463602113294255916002570735628126387331060058910652457080244749375431841494014821199962764531068006631183823761639663180931444671298615527598201451410275600689297502463040173514891945763607893528555053173314164570504996443890936308438744847839616840518452732884032345202470568516465716477139323775517294795126132398229602394548579754586517458787713318138752959809412174227300352296508089177705068259248822322154938048371454781647213976820963320508305647920482085920475499857320388876391601995240918938945576768749730856955958010659526503036266159750662225084067428898265907510637563569968211510949669744580547288693631020367823250182323708459790111548472087618212477813266330412076216587312970811230758159821248639807212407868878114501655825136178903070860870198975889807456643955157415363193191981070575336633738038272152798849350397480015890519420879711308051233933221903466249917169150948541401871060354603794643379005890957721180804465743962806186717861017156740967662080295766577051291209907944304632892947306159510430902221439371849560634056189342513057268291465783293340524635028929175470872564842600349629611654138230077313327298305001602567240141851520418907011542885799208121984493156999059182011819733500126187728036812481995877070207532406361259313438595542547781961142935163561223496661522614735399674051584998603552953329245752388810136202347624669055816438967863097627365504724348643071218494373485300606387644566272186661701238127715621379746149861328744117714552444708997144522885662942440230184791205478498574521634696448973892062401943518310088283480249249085403077863875165911302873958787098100772718271874529013972836614842142871705531796543076504534324600536361472618180969976933486264077435199928686323835088756683595097265574815431940195576850437248001020413749831872259677387154958399718444907279141965845930083942637020875635398216962055324803212267498911402678528599673405242031091797899905718821949391320753431707980023736590985375520238911643467185582906853711897952626234492483392496342449714656846591248918556629589329909035239233333647435203707701010843880032907598342170185542283861617210417603011645918780539367447472059985023582891833692922337323999480437108419659473162654825748099482509991833006976569367159689364493348864744213500840700660883597235039532340179582557036016936990988671132109798897070517280755855191269930673099250704070245568507786790694766126298082251633136399521170984528092630375922426742575599892892783704744452189363203489415521044597261883800300677617931381399162058062701651024458869247649246891924612125310275731390840470007143561362316992371694848132554200914530410371354532966206392105479824392125172540132314902740585892063217589494345489068463993137570910346332714153162232805522972979538018801628590735729554162788676498274186164218789885741071649069191851162815285486794173638906653885764229158342500673612453849160674137340173572779956341043326883569507814931378007362354180070619180267328551191942676091221035987469241172837493126163395001239599240508454375698507957046222664619000103500490183034153545842833764378111988556318777792537201166718539541835984438305203762819440761594106820716970302285152250573126093046898423433152732131361216582808075212631547730604423774753505952287174402666389148817173086436111389069420279088143119448799417154042103412190847094080254023932942945493878640230512927119097513536000921971105412096683111516328705423028470073120658032626417116165957613272351566662536672718998534199895236884830999302757419916463841427077988708874229277053891227172486322028898425125287217826030500994510824783572905691988555467886079462805371227042466543192145281760741482403827835829719301017888345674167811398954750448339314689630763396657226727043393216745421824557062524797219978668542798977992339579057581890622525473582205236424850783407110144980478726691990186438822932305382318559732869780922253529591017341407334884761005564018242392192695062083183814546983923664613639891012102177095976704908305081854704194664371312299692358895384930136356576186106062228705599423371631021278457446463989738188566746260879482018647487672727222062676465338099801966883680994159075776852639865146253336312450536402610569605513183813174261184420189088853196356986962795036738424313011331753305329802016688817481342988681585577810343231753064784983210629718425184385534427620128234570716988530518326179641178579608888150329602290705614476220915094739035946646916235396809201394578175891088931992112260073928149169481615273842736264298098234063200244024495894456129167049508235812487391799648641133480324757775219708932772262349486015046652681439877051615317026696929704928316285504212898146706195331970269507214378230476875280287354126166391708245925170010714180854800636923259462019002278087409859771921805158532147392653251559035410209284665925299914353791825314545290598415817637058927906909896911164381187809435371521332261443625314490127454772695739393481546916311624928873574718824071503995009446731954316193855485207665738825139639163576723151005556037263394867208207808653734942440115799667507360711159351331959197120948964717553024531364770942094635696982226673775209945168450643623824211853534887989395673187806606107885440005508276570305587448541805778891719207881423351138662929667179643468760077047999537883387870348718021842437342112273940255717690819603092018240188427057046092622564178375265263358324240661253311529423457965569502506810018310900411245379015332966156970522379210325706937051090830789479999004999395322153622748476603613677697978567386584670936679588583788795625946464891376652199588286933801836011932368578558558195556042156250883650203322024513762158204618106705195330653060606501054887167245377942831338871631395596905832083416898476065607118347136218123246227258841990286142087284956879639325464285343075301105285713829643709990356948885285190402956047346131138263878897551788560424998748316382804046848618938189590542039889872650697620201995548412650005394428203930127481638158530396439925470201672759328574366661644110962566337305409219519675148328734808957477775278344221091073111351828046036347198185655572957144747682552857863349342858423118749440003229690697758315903858039353521358860079600342097547392296733310649395601812237812854584317605561733861126734780745850676063048229409653041118306671081893031108871728167519579675347188537229309616143204006381322465841111157758358581135018569047815368938137718472814751998350504781297718599084707621974605887423256995828892535041937958260616211842368768511418316068315867994601652057740529423053601780313357263267054790338401257305912339601880137825421927094767337191987287385248057421248921183470876629667207272325650565129333126059505777727542471241648312832982072361750574673870128209575544305968395555686861188397135522084452852640081252027665557677495969626612604565245684086139238265768583384698499778726706555191854468698469478495734622606294219624557085371272776523098955450193037732166649182578154677292005212667143463209637891852323215018976126034373684067194193037746880999296877582441047878123266253181845960453853543839114496775312864260925211537673258866722604042523491087026958099647595805794663973419064010036361904042033113579336542426303561457009011244800890020801478056603710154122328891465722393145076071670643556827437743965789067972687438473076346451677562103098604092717090951280863090297385044527182892749689212106670081648583395537735919136950153162018908887484210798706899114804669270650940762046502772528650728905328548561433160812693005693785417861096969202538865034577183176686885923681488475276498468821949739729707737187188400414323127636504814531122850990020742409255859252926103021067368154347015252348786351643976235860419194129697690405264832347009911154242601273438022089331096686367898694977994001260164227609260823493041180643829138347354679725399262338791582998486459271734059225620749105308531537182911681637219395188700957788181586850464507699343940987433514431626330317247747486897918209239480833143970840673084079589358108966564775859905563769525232653614424780230826811831037735887089240613031336477371011628214614661679404090518615260360092521947218890918107335871964142144478654899528582343947050079830388538860831035719306002771194558021911942899922722353458707566246926177663178855144350218287026685610665003531050216318206017609217984684936863161293727951873078972637353717150256378733579771808184878458866504335824377004147710414934927438457587107159731559439426412570270965125108115548247939403597681188117282472158250109496096625393395380922195591918188552678062149923172763163218339896938075616855911752998450132067129392404144593862398809381240452191484831646210147389182510109096773869066404158973610476436500068077105656718486281496371118832192445663945814491486165500495676982690308911185687986929470513524816091743243015383684707292898982846022237301452655679898627767968091469798378268764311598832109043715611299766521539635464420869197567370005738764978437686287681792497469438427465256316323005551304174227341646455127812784577772457520386543754282825671412885834544435132562054464241011037955464190581168623059644769587054072141985212106734332410756767575818456990693046047522770167005684543969234041711089888993416350585157887353430815520811772071880379104046983069578685473937656433631979786803671873079693924236321448450354776315670255390065423117920153464977929066241508328858395290542637687668968805033317227800185885069736232403894700471897619347344308437443759925034178807972235859134245813144049847701732361694719765715353197754997162785663119046912609182591249890367654176979903623755286526375733763526969344354400473067198868901968147428767790866979688522501636949856730217523132529265375896415171479559538784278499866456302878831962099830494519874396369070682762657485810439112232618794059941554063270131989895703761105323606298674803779153767511583043208498720920280929752649812569163425000522908872646925284666104665392171482080130502298052637836426959733707053922789153510568883938113249757071331029504430346715989448786847116438328050692507766274500122003526203709466023414648998390252588830148678162196775194583167718762757200505439794412459900771152051546199305098386982542846407255540927403132571632640792934183342147090412542533523248021932277075355546795871638358750181593387174236061551171013123525633485820365146141870049205704372018261733194715700867578539336078622739558185797587258744102542077105475361294047460100094095444959662881486915903899071865980563617137692227290764197755177720104276496949611056220592502420217704269622154958726453989227697660310524980855759471631075870133208861463266412591148633881220284440694169488261529577625325019870359870674380469821942056381255833436421949232275937221289056420943082352544084110864545369404969271494003319782861318186188811118408257865928757426384450059944229568586460481033015388911499486935436030221810943466764000022362550573631294626296096198760564259963946138692330837196265954739234624134597795748524647837980795693198650815977675350553918991151335252298736112779182748542008689539658359421963331502869561192012298889887006079992795411188269023078913107603617634779489432032102773359416908650071932804017163840644987871753756781185321328408216571107549528294974936214608215583205687232185574065161096274874375098092230211609982633033915469494644491004515280925089745074896760324090768983652940657920198315265410658136823791984090645712468948470209357761193139980246813405200394781949866202624008902150166163813538381515037735022966074627952910384068685569070157516624192987244482719429331004854824454580718897633003232525821581280327467962002814762431828622171054352898348208273451680186131719593324711074662228508710666117703465352839577625997744672185715816126411143271794347885990892808486694914139097716736900277758502686646540565950394867841110790116104008572744562938425494167594605487117235946429105850909950214958793112196135908315882620682332156153086833730838173279328196983875087083483880463884784418840031847126974543709373298362402875197920802321878744882872843727378017827008058782410749357514889978911739746129320351081432703251409030487462262942344327571260086642508333187688650756429271605525289544921537651751492196367181049435317858383453865255656640657251363575064353236508936790431702597878177190314867963840828810209461490079715137717099061954969640070867667102330048672631475510537231757114322317411411680622864206388906210192355223546711662137499693269321737043105987225039456574924616978260970253359475020913836673772894438696400028110344026084712899000746807764844088711341352503367877316797709372778682166117865344231732264637847697875144332095340001650692130546476890985050203015044880834261845208730530973189492916425322933612431514306578264070283898409841602950309241897120971601649265613413433422298827909921786042679812457285345801338260995877178113102167340256562744007296834066198480676615805021691833723680399027931606420436812079900316264449146190219458229690992122788553948783538305646864881655562294315673128274390826450611628942803501661336697824051770155219626522725455850738640585299830379180350432876703809252167907571204061237596327685674845079151147313440001832570344920909712435809447900462494313455028900680648704293534037436032625820535790118395649089354345101342969617545249573960621490288728932792520696535386396443225388327522499605986974759882329916263545973324445163755334377492928990581175786355555626937426910947117002165411718219750519831787137106051063795558588905568852887989084750915764639074693619881507814685262133252473837651192990156109189777922008705793396463827490680698769168197492365624226087154176100430608904377976678519661891404144925270480881971498801542057787006521594009289777601330756847966992955433656139847738060394368895887646054983871478968482805384701730871117761159663505039979343869339119789887109156541709133082607647406305711411098839388095481437828474528838368079418884342666222070438722887413947801017721392281911992365405516395893474263953824829609036900288359327745855060801317988407162446563997948275783650195514221551339281978226984278638391679715091262410548725700924070045488485692950448110738087996547481568913935380943474556972128919827177020766613602489581468119133614121258783895577357194986317210844398901423948496659251731388171602663261931065366535041473070804414939169363262373767777095850313255990095762731957308648042467701212327020533742667053142448208168130306397378736642483672539837487690980602182785786216512738563513290148903509883270617258932575363993979055729175160097615459044771692265806315111028038436017374742152476085152099016158582312571590733421736576267142390478279587281505095633092802668458937649649770232973641319060982740633531089792464242134583740901169391964250459128813403498810635400887596820054408364386516617880557608956896727531538081942077332597917278437625661184319891025007491829086475149794003160703845549465385946027452447466812314687943441610993338908992638411847425257044572517459325738989565185716575961481266020310797628254165590506042479114016957900338356574869252800743025623419498286467914476322774005529460903940177536335655471931000175430047504719144899841040015867946179241610016454716551337074073950260442769538553834397550548871099785205401175169747581344926079433689543783221172450687344231989878844128542064742809735625807066983106979935260693392135685881391214807354728463227784908087002467776303605551232386656295178853719673034634701222939581606792509153217489030840886516061119011498443412350124646928028805996134283511884715449771278473361766285062169778717743824362565711779450064477718370221999106695021656757644044997940765037999954845002710665987813603802314126836905783190460792765297277694043613023051787080546511542469395265127101052927070306673024447125973939950514628404767431363739978259184541176413327906460636584152927019030276017339474866960348694976541752429306040727005059039503148522921392575594845078867977925253931765156416197168443524369794447355964260633391055126826061595726217036698506473281266724521989060549880280782881429796336696744124805982192146339565745722102298677599746738126069367069134081559412016115960190237753525556300606247983261249881288192937343476862689219239777833910733106588256813777172328315329082525092733047850724977139448333892552081175608452966590553940965568541706001179857293813998258319293679100391844099286575605993598910002969864460974714718470101531283762631146774209145574041815908800064943237855839308530828305476076799524357391631221886057549673832243195650655460852881201902363644712703748634421727257879503428486312944916318475347531435041392096108796057730987201352484075057637199253650470908582513936863463863368042891767107602111159828875539940120076013947033661793715396306139863655492213741597905119083588290097656647300733879314678913181465109316761575821351424860442292445304113160652700974330088499034675405518640677342603583409608605533747362760935658853109760994238347382222087292464497684560579562516765574088410321731345627735856052358236389532038534024842273371639123973215995440828421666636023296545694703577184873442034227706653837387506169212768015766181095420097708363604361110592409117889540338021426523948929686439808926114635414571535194342850721353453018315875628275733898268898523557799295727645229391567477566676051087887648453493636068278050564622813598885879259940946446041705204470046315137975431737187756039815962647501410906658866162180038266989961965580587208639721176995219466789857011798332440601811575658074284182910615193917630059194314434605154047710570054339000182453117733718955857603607182860506356479979004139761808955363669603162193113250223851791672055180659263518036251214575926238369348222665895576994660491938112486609099798128571823494006615552196112207203092277646200999315244273589488710576623894693889446495093960330454340842102462401048723328750081749179875543879387381439894238011762700837196053094383940063756116458560943129517597713935396074322792489221267045808183313764165818269562105872892447740035947009268662659651422050630078592002488291860839743732353849083964326147000532423540647042089499210250404726781059083644007466380020870126664209457181702946752278540074508552377720890581683918446592829417018288233014971554235235911774818+colossalNumber =+ 1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275900994657640789512694683983525957098258226205224894077267194782684826014769909026401363944374553050682034962524517493996514314298091906592509372216964615157098583874105978859597729754989301617539284681382686838689427741559918559252459539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125150760694794510965960940252288797108931456691368672287489405601015033086179286809208747609178249385890097149096759852613655497818931297848216829989487226588048575640142704775551323796414515237462343645428584447952658678210511413547357395231134271661021359695362314429524849371871101457654035902799344037420073105785390621983874478084784896833214457138687519435064302184531910484810053706146806749192781911979399520614196634287544406437451237181921799983910159195618146751426912397489409071864942319615679452080951465502252316038819301420937621378559566389377870830390697920773467221825625996615014215030680384477345492026054146659252014974428507325186660021324340881907104863317346496514539057962685610055081066587969981635747363840525714591028970641401109712062804390397595156771577004203378699360072305587631763594218731251471205329281918261861258673215791984148488291644706095752706957220917567116722910981690915280173506712748583222871835209353965725121083579151369882091444210067510334671103141267111369908658516398315019701651511685171437657618351556508849099898599823873455283316355076479185358932261854896321329330898570642046752590709154814165498594616371802709819943099244889575712828905923233260972997120844335732654893823911932597463667305836041428138830320382490375898524374417029132765618093773444030707469211201913020330380197621101100449293215160842444859637669838952286847831235526582131449576857262433441893039686426243410773226978028073189154411010446823252716201052652272111660396665573092547110557853763466820653109896526918620564769312570586356620185581007293606598764861179104533488503461136576867532494416680396265797877185560845529654126654085306143444318586769751456614068007002378776591344017127494704205622305389945613140711270004078547332699390814546646458807972708266830634328587856983052358089330657574067954571637752542021149557615814002501262285941302164715509792592309907965473761255176567513575178296664547791745011299614890304639947132962107340437518957359614589019389713111790429782856475032031986915140287080859904801094121472213179476477726224142548545403321571853061422881375850430633217518297986622371721591607716692547487389866549494501146540628433663937900397692656721463853067360965712091807638327166416274888800786925602902284721040317211860820419000422966171196377921337575114959501566049631862947265473642523081770367515906735023507283540567040386743513622224771589150495309844489333096340878076932599397805419341447377441842631298608099888687413260472156951623965864573021631598193195167353812974167729478672422924654366800980676928238280689964004824354037014163149658979409243237896907069779422362508221688957383798623001593776471651228935786015881617557829735233446042815126272037343146531977774160319906655418763979293344195215413418994854447345673831624993419131814809277771038638773431772075456545322077709212019051660962804909263601975988281613323166636528619326686336062735676303544776280350450777235547105859548702790814356240145171806246436267945612753181340783303362542327839449753824372058353114771199260638133467768796959703098339130771098704085913374641442822772634659470474587847787201927715280731767907707157213444730605700733492436931138350493163128404251219256517980694113528013147013047816437885185290928545201165839341965621349143415956258658655705526904965209858033850722426482939728584783163057777560688876446248246857926039535277348030480290058760758251047470916439613626760449256274204208320856611906254543372131535958450687724602901618766795240616342522577195429162991930645537799140373404328752628889639958794757291746426357455254079091451357111369410911939325191076020825202618798531887705842972591677813149699009019211697173727847684726860849003377024242916513005005168323364350389517029893922334517220138128069650117844087451960121228599371623130171144484640903890644954440061986907548516026327505298349187407866808818338510228334508504860825039302133219715518430635455007668282949304137765527939751754613953984683393638304746119966538581538420568533862186725233402830871123282789212507712629463229563989898935821167456270102183564622013496715188190973038119800497340723961036854066431939509790190699639552453005450580685501956730229219139339185680344903982059551002263535361920419947455385938102343955449597783779023742161727111723643435439478221818528624085140066604433258885698670543154706965747458550332323342107301545940516553790686627333799585115625784322988273723198987571415957811196358330059408730681216028764962867446047746491599505497374256269010490377819868359381465741268049256487985561453723478673303904688383436346553794986419270563872931748723320837601123029911367938627089438799362016295154133714248928307220126901475466847653576164773794675200490757155527819653621323926406160136358155907422020203187277605277219005561484255518792530343513984425322341576233610642506390497500865627109535919465897514131034822769306247435363256916078154781811528436679570611086153315044521274739245449454236828860613408414863776700961207151249140430272538607648236341433462351897576645216413767969031495019108575984423919862916421939949072362346468441173940326591840443780513338945257423995082965912285085558215725031071257012668302402929525220118726767562204154205161841634847565169998116141010029960783869092916030288400269104140792886215078424516709087000699282120660418371806535567252532567532861291042487761825829765157959847035622262934860034158722980534989650226291748788202734209222245339856264766914905562842503912757710284027998066365825488926488025456610172967026640765590429099456815065265305371829412703369313785178609040708667114965583434347693385781711386455873678123014587687126603489139095620099393610310291616152881384379099042317473363948045759314931405297634757481193567091101377517210080315590248530906692037671922033229094334676851422144773793937517034436619910403375111735471918550464490263655128162288244625759163330391072253837421821408835086573917715096828874782656995995744906617583441375223970968340800535598491754173818839994469748676265516582765848358845314277568790029095170283529716344562129640435231176006651012412006597558512761785838292041974844236080071930457618932349229279650198751872127267507981255470958904556357921221033346697499235630254947802490114195212382815309114079073860251522742995818072471625916685451333123948049470791191532673430282441860414263639548000448002670496248201792896476697583183271314251702969234889627668440323260927524960357996469256504936818360900323809293459588970695365349406034021665443755890045632882250545255640564482465151875471196218443965825337543885690941130315095261793780029741207665147939425902989695946995565761218656196733786236256125216320862869222103274889218654364802296780705765615144632046927906821207388377814233562823608963208068222468012248261177185896381409183903673672220888321513755600372798394004152970028783076670944474560134556417254370906979396122571429894671543578468788614445812314593571984922528471605049221242470141214780573455105008019086996033027634787081081754501193071412233908663938339529425786905076431006383519834389341596131854347546495569781038293097164651438407007073604112373599843452251610507027056235266012764848308407611830130527932054274628654036036745328651057065874882256981579367897669742205750596834408697350201410206723585020072452256326513410559240190274216248439140359989535394590944070469120914093870012645600162374288021092764579310657922955249887275846101264836999892256959688159205600101655256375678566722796619885782794848855834397518744545512965634434803966420557982936804352202770984294232533022576341807039476994159791594530069752148293366555661567873640053666564165473217043903521329543529169414599041608753201868379370234888689479151071637852902345292440773659495630510074210871426134974595615138498713757047101787957310422969066670214498637464595280824369445789772330048764765241339075920434019634039114732023380715095222010682563427471646024335440051521266932493419673977041595683753555166730273900749729736354964533288869844061196496162773449518273695588220757355176651589855190986665393549481068873206859907540792342402300925900701731960362254756478940647548346647760411463233905651343306844953979070903023460461470961696886885014083470405460742958699138296682468185710318879065287036650832431974404771855678934823089431068287027228097362480939962706074726455399253994428081137369433887294063079261595995462624629707062594845569034711972996409089418059534393251236235508134949004364278527138315912568989295196427287573946914272534366941532361004537304881985517065941217352462589548730167600298865925786628561249665523533829428785425340483083307016537228563559152534784459818313411290019992059813522051173365856407826484942764411376393866924803118364453698589175442647399882284621844900877769776312795722672655562596282542765318300134070922334365779160128093179401718598599933849235495640057099558561134980252499066984233017350358044081168552653117099570899427328709258487894436460050410892266917835258707859512983441729535195378855345737426085902908176515578039059464087350612322611200937310804854852635722825768203416050484662775045003126200800799804925485346941469775164932709504934639382432227188515974054702148289711177792376122578873477188196825462981268685817050740272550263329044976277894423621674119186269439650671515779586756482399391760426017633870454990176143641204692182370764887834196896861181558158736062938603810171215855272668300823834046564758804051380801633638874216371406435495561868964112282140753302655100424104896783528588290243670904887118190909494533144218287661810310073547705498159680772009474696134360928614849417850171807793068108546900094458995279424398139213505586422196483491512639012803832001097738680662877923971801461343244572640097374257007359210031541508936793008169980536520276007277496745840028362405346037263416554259027601834840306811381855105979705664007509426087885735796037324514146786703688098806097164258497595138069309449401515422221943291302173912538355915031003330325111749156969174502714943315155885403922164097229101129035521815762823283182342548326111912800928252561902052630163911477247331485739107775874425387611746578671169414776421441111263583553871361011023267987756410246824032264834641766369806637857681349204530224081972785647198396308781543221166912246415911776732253264335686146186545222681268872684459684424161078540167681420808850280054143613146230821025941737562389942075713627516745731891894562835257044133543758575342698699472547031656613991999682628247270641336222178923903176085428943733935618891651250424404008952719837873864805847268954624388234375178852014395600571048119498842390606136957342315590796703461491434478863604103182350736502778590897578272731305048893989009923913503373250855982655867089242612429473670193907727130706869170926462548423240748550366080136046689511840093668609546325002145852930950000907151058236267293264537382104938724996699339424685516483261134146110680267446637334375340764294026682973865220935701626384648528514903629320199199688285171839536691345222444708045923966028171565515656661113598231122506289058549145097157553900243931535190902107119457300243880176615035270862602537881797519478061013715004489917210022201335013106016391541589578037117792775225978742891917915522417189585361680594741234193398420218745649256443462392531953135103311476394911995072858430658361935369329699289837914941939406085724863968836903265564364216644257607914710869984315733749648835292769328220762947282381537409961545598798259891093717126218283025848112389011968221429457667580718653806506487026133892822994972574530332838963818439447707794022843598834100358385423897354243956475556840952248445541392394100016207693636846776413017819659379971557468541946334893748439129742391433659360410035234377706588867781139498616478747140793263858738624732889645643598774667638479466504074111825658378878454858148962961273998413442726086061872455452360643153710112746809778704464094758280348769758948328241239292960582948619196670918958089833201210318430340128495116203534280144127617285830243559830032042024512072872535581195840149180969253395075778400067465526031446167050827682772223534191102634163157147406123850425845988419907611287258059113935689601431668283176323567325417073420817332230462987992804908514094790368878687894930546955703072619009502076433493359106024545086453628935456862958531315337183868265617862273637169757741830239860065914816164049449650117321313895747062088474802365371031150898427992754426853277974311395143574172219759799359685252285745263796289612691572357986620573408375766873884266405990993505000813375432454635967504844235284874701443545419576258473564216198134073468541117668831186544893776979566517279662326714810338643913751865946730024434500544995399742372328712494834706044063471606325830649829795510109541836235030309453097335834462839476304775645015008507578949548931393944899216125525597701436858943585877526379625597081677643800125436502371412783467926101995585224717220177723700417808419423948725406801556035998390548985723546745642390585850216719031395262944554391316631345308939062046784387785054239390524731362012947691874975191011472315289326772533918146607300089027768963114810902209724520759167297007850580717186381054967973100167870850694207092232908070383263453452038027860990556900134137182368370991949516489600755049341267876436746384902063964019766685592335654639138363185745698147196210841080961884605456039038455343729141446513474940784884423772175154334260306698831768331001133108690421939031080143784334151370924353013677631084913516156422698475074303297167469640666531527035325467112667522460551199581831963763707617991919203579582007595605302346267757943936307463056901080114942714100939136913810725813781357894005599500183542511841721360557275221035268037357265279224173736057511278872181908449006178013889710770822931002797665935838758909395688148560263224393726562472776037890814458837855019702843779362407825052704875816470324581290878395232453237896029841669225489649715606981192186584926770403956481278102179913217416305810554598801300484562997651121241536374515005635070127815926714241342103301566165356024733807843028655257222753049998837015348793008062601809623815161366903341111386538510919367393835229345888322550887064507539473952043968079067086806445096986548801682874343786126453815834280753061845485903798217994599681154419742536344399602902510015888272164745006820704193761584547123183460072629339550548239557137256840232268213012476794522644820910235647752723082081063518899152692889108455571126603965034397896278250016110153235160519655904211844949907789992007329476905868577878720982901352956613978884860509786085957017731298155314951681467176959760994210036183559138777817698458758104466283998806006162298486169353373865787735983361613384133853684211978938900185295691967804554482858483701170967212535338758621582310133103877668272115726949518179589754693992642197915523385766231676275475703546994148929041301863861194391962838870543677743224276809132365449485366768000001065262485473055861598999140170769838548318875014293890899506854530765116803337322265175662207526951791442252808165171667766727930354851542040238174608923283917032754257508676551178593950027933895920576682789677644531840404185540104351348389531201326378369283580827193783126549617459970567450718332065034556644034490453627560011250184335607361222765949278393706478426456763388188075656121689605041611390390639601620221536849410926053876887148379895599991120991646464411918568277004574243434021672276445589330127781586869525069499364610175685060167145354315814801054588605645501332037586454858403240298717093480910556211671546848477803944756979804263180991756422809873998766973237695737015808068229045992123661689025962730430679316531149401764737693873514093361833216142802149763399189835484875625298752423873077559555955465196394401821840998412489826236737714672260616336432964063357281070788758164043814850188411431885988276944901193212968271588841338694346828590066640806314077757725705630729400492940302420498416565479736705485580445865720227637840466823379852827105784319753541795011347273625774080213476826045022851579795797647467022840999561601569108903845824502679265942055503958792298185264800706837650418365620945554346135134152570065974881916341359556719649654032187271602648593049039787489589066127250794828276938953521753621850796297785146188432719223223810158744450528665238022532843891375273845892384422535472653098171578447834215822327020690287232330053862163479885094695472004795231120150432932266282727632177908840087861480221475376578105819702226309717495072127248479478169572961423658595782090830733233560348465318730293026659645013718375428897557971449924654038681799213893469244741985097334626793321072686870768062639919361965044099542167627840914669856925715074315740793805323925239477557441591845821562518192155233709607483329234921034514626437449805596103307994145347784574699992128599999399612281615219314888769388022281083001986016549416542616968586788372609587745676182507275992950893180521872924610867639958916145855058397274209809097817293239301067663868240401113040247007350857828724627134946368531815469690466968693925472519413992914652423857762550047485295476814795467007050347999588867695016124972282040303995463278830695976249361510102436555352230690612949388599015734661023712235478911292547696176005047974928060721268039226911027772261025441492215765045081206771735712027180242968106203776578837166909109418074487814049075517820385653909910477594141321543284406250301802757169650820964273484146957263978842560084531214065935809041271135920041975985136254796160632288736181367373244506079244117639975974619383584574915988097667447093006546342423460634237474666080431701260052055928493695941434081468529815053947178900451835755154125223590590687264878635752541911288877371766374860276606349603536794702692322971868327717393236192007774522126247518698334951510198642698878471719396649769070825217423365662725928440620430214113719922785269984698847702323823840055655517889087661360130477098438611687052310553149162517283732728676007248172987637569816335415074608838663640693470437206688651275688266149730788657015685016918647488541679154596507234287730699853713904300266530783987763850323818215535597323530686043010675760838908627049841888595138091030423595782495143988590113185835840667472370297149785084145853085781339156270760356390763947311455495832266945702494139831634332378975955680856836297253867913275055542524491943589128405045226953812179131914513500993846311774017971512283785460116035955402864405902496466930707769055481028850208085800878115773817191741776017330738554758006056014337743299012728677253043182519757916792969965041460706645712588834697979642931622965520168797300035646304579308840327480771811555330909887025505207680463034608658165394876951960044084820659673794731680864156456505300498816164905788311543454850526600698230931577765003780704661264706021457505793270962047825615247145918965223608396645624105195510522357239739512881816405978591427914816542632892004281609136937773722299983327082082969955737727375667615527113922588055201898876201141680054687365580633471603734291703907986396522961312801782679717289822936070288069087768660593252746378405397691848082041021944719713869256084162451123980620113184541244782050110798760717155683154078865439041210873032402010685341947230476666721749869868547076781205124736792479193150856444775379853799732234456122785843296846647513336573692387201464723679427870042503255589926884349592876124007558756946413705625140011797133166207153715436006876477318675587148783989081074295309410605969443158477539700943988394914432353668539209946879645066533985738887866147629443414010498889931600512076781035886116602029611936396821349607501116498327856353161451684576956871090029997698412632665023477167286573785790857466460772283415403114415294188047825438761770790430001566986776795760909966936075594965152736349811896413043311662774712338817406037317439705406703109676765748695358789670031925866259410510533584384656023391796749267844763708474978333655579007384191473198862713525954625181604342253729962863267496824058060296421146386436864224724887283434170441573482481833301640566959668866769563491416328426414974533349999480002669987588815935073578151958899005395120853510357261373640343675347141048360175464883004078464167452167371904831096767113443494819262681110739948250607394950735031690197318521195526356325843390998224986240670310768318446607291248747540316179699411397387765899868554170318847788675929026070043212666179192235209382278788809886335991160819235355570464634911320859189796132791319756490976000139962344455350143464268604644958624769094347048293294140411146540923988344435159133201077394411184074107684981066347241048239358274019449356651610884631256785297769734684303061462418035852933159734583038455410337010916767763742762102137013548544509263071901147318485749233181672072137279355679528443925481560913728128406333039373562420016045664557414588166052166608738748047243391212955877763906969037078828527753894052460758496231574369171131761347838827194168606625721036851321566478001476752310393578606896111259960281839309548709059073861351914591819510297327875571049729011487171897180046961697770017913919613791417162707018958469214343696762927459109940060084983568425201915593703701011049747339493877885989417433031785348707603221982970579751191440510994235883034546353492349826883624043327267415540301619505680654180939409982020609994140216890900708213307230896621197755306659188141191577836272927461561857103721724710095214236964830864102592887457999322374955191221951903424452307535133806856807354464995127203174487195403976107308060269906258076020292731455252078079914184290638844373499681458273372072663917670201183004648190002413083508846584152148991276106513741539435657211390328574918769094413702090517031487773461652879848235338297260136110984514841823808120540996125274580881099486972216128524897425555516076371675054896173016809613803811914361143992106380050832140987604599309324851025168294467260666138151745712559754953580239983146982203613380828499356705575524712902745397762140493182014658008021566536067765508783804304134310591804606800834591136640834887408005741272586704792258319127415739080914383138456424150940849133918096840251163991936853225557338966953749026620923261318855891580832455571948453875628786128859004106006073746501402627824027346962528217174941582331749239683530136178653673760642166778137739951006589528877427662636841830680190804609849809469763667335662282915132352788806157768278159588669180238940333076441912403412022316368577860357276941541778826435238131905028087018575047046312933353757285386605888904583111450773942935201994321971171642235005644042979892081594307167019857469273848653833436145794634175922573898588001698014757420542995801242958105456510831046297282937584161162532562516572498078492099897990620035936509934721582965174135798491047111660791587436986541222348341887722929446335178653856731962559852026072947674072616767145573649812105677716893484917660771705277187601199908144113058645577910525684304811440261938402322470939249802933550731845890355397133088446174107959162511714864874468611247605428673436709046678468670274091881014249711149657817724279347070216688295610877794405048437528443375108828264771978540006509704033021862556147332117771174413350281608840351781452541964320309576018694649088681545285621346988355444560249556668436602922195124830910605377201980218310103270417838665447181260397190688462370857518080035327047185659499476124248110999288679158969049563947624608424065930948621507690314987020673533848349550836366017848771060809804269247132410009464014373603265645184566792456669551001502298330798496079949882497061723674493612262229617908143114146609412341593593095854079139087208322733549572080757165171876599449856937956238755516175754380917805280294642004472153962807463602113294255916002570735628126387331060058910652457080244749375431841494014821199962764531068006631183823761639663180931444671298615527598201451410275600689297502463040173514891945763607893528555053173314164570504996443890936308438744847839616840518452732884032345202470568516465716477139323775517294795126132398229602394548579754586517458787713318138752959809412174227300352296508089177705068259248822322154938048371454781647213976820963320508305647920482085920475499857320388876391601995240918938945576768749730856955958010659526503036266159750662225084067428898265907510637563569968211510949669744580547288693631020367823250182323708459790111548472087618212477813266330412076216587312970811230758159821248639807212407868878114501655825136178903070860870198975889807456643955157415363193191981070575336633738038272152798849350397480015890519420879711308051233933221903466249917169150948541401871060354603794643379005890957721180804465743962806186717861017156740967662080295766577051291209907944304632892947306159510430902221439371849560634056189342513057268291465783293340524635028929175470872564842600349629611654138230077313327298305001602567240141851520418907011542885799208121984493156999059182011819733500126187728036812481995877070207532406361259313438595542547781961142935163561223496661522614735399674051584998603552953329245752388810136202347624669055816438967863097627365504724348643071218494373485300606387644566272186661701238127715621379746149861328744117714552444708997144522885662942440230184791205478498574521634696448973892062401943518310088283480249249085403077863875165911302873958787098100772718271874529013972836614842142871705531796543076504534324600536361472618180969976933486264077435199928686323835088756683595097265574815431940195576850437248001020413749831872259677387154958399718444907279141965845930083942637020875635398216962055324803212267498911402678528599673405242031091797899905718821949391320753431707980023736590985375520238911643467185582906853711897952626234492483392496342449714656846591248918556629589329909035239233333647435203707701010843880032907598342170185542283861617210417603011645918780539367447472059985023582891833692922337323999480437108419659473162654825748099482509991833006976569367159689364493348864744213500840700660883597235039532340179582557036016936990988671132109798897070517280755855191269930673099250704070245568507786790694766126298082251633136399521170984528092630375922426742575599892892783704744452189363203489415521044597261883800300677617931381399162058062701651024458869247649246891924612125310275731390840470007143561362316992371694848132554200914530410371354532966206392105479824392125172540132314902740585892063217589494345489068463993137570910346332714153162232805522972979538018801628590735729554162788676498274186164218789885741071649069191851162815285486794173638906653885764229158342500673612453849160674137340173572779956341043326883569507814931378007362354180070619180267328551191942676091221035987469241172837493126163395001239599240508454375698507957046222664619000103500490183034153545842833764378111988556318777792537201166718539541835984438305203762819440761594106820716970302285152250573126093046898423433152732131361216582808075212631547730604423774753505952287174402666389148817173086436111389069420279088143119448799417154042103412190847094080254023932942945493878640230512927119097513536000921971105412096683111516328705423028470073120658032626417116165957613272351566662536672718998534199895236884830999302757419916463841427077988708874229277053891227172486322028898425125287217826030500994510824783572905691988555467886079462805371227042466543192145281760741482403827835829719301017888345674167811398954750448339314689630763396657226727043393216745421824557062524797219978668542798977992339579057581890622525473582205236424850783407110144980478726691990186438822932305382318559732869780922253529591017341407334884761005564018242392192695062083183814546983923664613639891012102177095976704908305081854704194664371312299692358895384930136356576186106062228705599423371631021278457446463989738188566746260879482018647487672727222062676465338099801966883680994159075776852639865146253336312450536402610569605513183813174261184420189088853196356986962795036738424313011331753305329802016688817481342988681585577810343231753064784983210629718425184385534427620128234570716988530518326179641178579608888150329602290705614476220915094739035946646916235396809201394578175891088931992112260073928149169481615273842736264298098234063200244024495894456129167049508235812487391799648641133480324757775219708932772262349486015046652681439877051615317026696929704928316285504212898146706195331970269507214378230476875280287354126166391708245925170010714180854800636923259462019002278087409859771921805158532147392653251559035410209284665925299914353791825314545290598415817637058927906909896911164381187809435371521332261443625314490127454772695739393481546916311624928873574718824071503995009446731954316193855485207665738825139639163576723151005556037263394867208207808653734942440115799667507360711159351331959197120948964717553024531364770942094635696982226673775209945168450643623824211853534887989395673187806606107885440005508276570305587448541805778891719207881423351138662929667179643468760077047999537883387870348718021842437342112273940255717690819603092018240188427057046092622564178375265263358324240661253311529423457965569502506810018310900411245379015332966156970522379210325706937051090830789479999004999395322153622748476603613677697978567386584670936679588583788795625946464891376652199588286933801836011932368578558558195556042156250883650203322024513762158204618106705195330653060606501054887167245377942831338871631395596905832083416898476065607118347136218123246227258841990286142087284956879639325464285343075301105285713829643709990356948885285190402956047346131138263878897551788560424998748316382804046848618938189590542039889872650697620201995548412650005394428203930127481638158530396439925470201672759328574366661644110962566337305409219519675148328734808957477775278344221091073111351828046036347198185655572957144747682552857863349342858423118749440003229690697758315903858039353521358860079600342097547392296733310649395601812237812854584317605561733861126734780745850676063048229409653041118306671081893031108871728167519579675347188537229309616143204006381322465841111157758358581135018569047815368938137718472814751998350504781297718599084707621974605887423256995828892535041937958260616211842368768511418316068315867994601652057740529423053601780313357263267054790338401257305912339601880137825421927094767337191987287385248057421248921183470876629667207272325650565129333126059505777727542471241648312832982072361750574673870128209575544305968395555686861188397135522084452852640081252027665557677495969626612604565245684086139238265768583384698499778726706555191854468698469478495734622606294219624557085371272776523098955450193037732166649182578154677292005212667143463209637891852323215018976126034373684067194193037746880999296877582441047878123266253181845960453853543839114496775312864260925211537673258866722604042523491087026958099647595805794663973419064010036361904042033113579336542426303561457009011244800890020801478056603710154122328891465722393145076071670643556827437743965789067972687438473076346451677562103098604092717090951280863090297385044527182892749689212106670081648583395537735919136950153162018908887484210798706899114804669270650940762046502772528650728905328548561433160812693005693785417861096969202538865034577183176686885923681488475276498468821949739729707737187188400414323127636504814531122850990020742409255859252926103021067368154347015252348786351643976235860419194129697690405264832347009911154242601273438022089331096686367898694977994001260164227609260823493041180643829138347354679725399262338791582998486459271734059225620749105308531537182911681637219395188700957788181586850464507699343940987433514431626330317247747486897918209239480833143970840673084079589358108966564775859905563769525232653614424780230826811831037735887089240613031336477371011628214614661679404090518615260360092521947218890918107335871964142144478654899528582343947050079830388538860831035719306002771194558021911942899922722353458707566246926177663178855144350218287026685610665003531050216318206017609217984684936863161293727951873078972637353717150256378733579771808184878458866504335824377004147710414934927438457587107159731559439426412570270965125108115548247939403597681188117282472158250109496096625393395380922195591918188552678062149923172763163218339896938075616855911752998450132067129392404144593862398809381240452191484831646210147389182510109096773869066404158973610476436500068077105656718486281496371118832192445663945814491486165500495676982690308911185687986929470513524816091743243015383684707292898982846022237301452655679898627767968091469798378268764311598832109043715611299766521539635464420869197567370005738764978437686287681792497469438427465256316323005551304174227341646455127812784577772457520386543754282825671412885834544435132562054464241011037955464190581168623059644769587054072141985212106734332410756767575818456990693046047522770167005684543969234041711089888993416350585157887353430815520811772071880379104046983069578685473937656433631979786803671873079693924236321448450354776315670255390065423117920153464977929066241508328858395290542637687668968805033317227800185885069736232403894700471897619347344308437443759925034178807972235859134245813144049847701732361694719765715353197754997162785663119046912609182591249890367654176979903623755286526375733763526969344354400473067198868901968147428767790866979688522501636949856730217523132529265375896415171479559538784278499866456302878831962099830494519874396369070682762657485810439112232618794059941554063270131989895703761105323606298674803779153767511583043208498720920280929752649812569163425000522908872646925284666104665392171482080130502298052637836426959733707053922789153510568883938113249757071331029504430346715989448786847116438328050692507766274500122003526203709466023414648998390252588830148678162196775194583167718762757200505439794412459900771152051546199305098386982542846407255540927403132571632640792934183342147090412542533523248021932277075355546795871638358750181593387174236061551171013123525633485820365146141870049205704372018261733194715700867578539336078622739558185797587258744102542077105475361294047460100094095444959662881486915903899071865980563617137692227290764197755177720104276496949611056220592502420217704269622154958726453989227697660310524980855759471631075870133208861463266412591148633881220284440694169488261529577625325019870359870674380469821942056381255833436421949232275937221289056420943082352544084110864545369404969271494003319782861318186188811118408257865928757426384450059944229568586460481033015388911499486935436030221810943466764000022362550573631294626296096198760564259963946138692330837196265954739234624134597795748524647837980795693198650815977675350553918991151335252298736112779182748542008689539658359421963331502869561192012298889887006079992795411188269023078913107603617634779489432032102773359416908650071932804017163840644987871753756781185321328408216571107549528294974936214608215583205687232185574065161096274874375098092230211609982633033915469494644491004515280925089745074896760324090768983652940657920198315265410658136823791984090645712468948470209357761193139980246813405200394781949866202624008902150166163813538381515037735022966074627952910384068685569070157516624192987244482719429331004854824454580718897633003232525821581280327467962002814762431828622171054352898348208273451680186131719593324711074662228508710666117703465352839577625997744672185715816126411143271794347885990892808486694914139097716736900277758502686646540565950394867841110790116104008572744562938425494167594605487117235946429105850909950214958793112196135908315882620682332156153086833730838173279328196983875087083483880463884784418840031847126974543709373298362402875197920802321878744882872843727378017827008058782410749357514889978911739746129320351081432703251409030487462262942344327571260086642508333187688650756429271605525289544921537651751492196367181049435317858383453865255656640657251363575064353236508936790431702597878177190314867963840828810209461490079715137717099061954969640070867667102330048672631475510537231757114322317411411680622864206388906210192355223546711662137499693269321737043105987225039456574924616978260970253359475020913836673772894438696400028110344026084712899000746807764844088711341352503367877316797709372778682166117865344231732264637847697875144332095340001650692130546476890985050203015044880834261845208730530973189492916425322933612431514306578264070283898409841602950309241897120971601649265613413433422298827909921786042679812457285345801338260995877178113102167340256562744007296834066198480676615805021691833723680399027931606420436812079900316264449146190219458229690992122788553948783538305646864881655562294315673128274390826450611628942803501661336697824051770155219626522725455850738640585299830379180350432876703809252167907571204061237596327685674845079151147313440001832570344920909712435809447900462494313455028900680648704293534037436032625820535790118395649089354345101342969617545249573960621490288728932792520696535386396443225388327522499605986974759882329916263545973324445163755334377492928990581175786355555626937426910947117002165411718219750519831787137106051063795558588905568852887989084750915764639074693619881507814685262133252473837651192990156109189777922008705793396463827490680698769168197492365624226087154176100430608904377976678519661891404144925270480881971498801542057787006521594009289777601330756847966992955433656139847738060394368895887646054983871478968482805384701730871117761159663505039979343869339119789887109156541709133082607647406305711411098839388095481437828474528838368079418884342666222070438722887413947801017721392281911992365405516395893474263953824829609036900288359327745855060801317988407162446563997948275783650195514221551339281978226984278638391679715091262410548725700924070045488485692950448110738087996547481568913935380943474556972128919827177020766613602489581468119133614121258783895577357194986317210844398901423948496659251731388171602663261931065366535041473070804414939169363262373767777095850313255990095762731957308648042467701212327020533742667053142448208168130306397378736642483672539837487690980602182785786216512738563513290148903509883270617258932575363993979055729175160097615459044771692265806315111028038436017374742152476085152099016158582312571590733421736576267142390478279587281505095633092802668458937649649770232973641319060982740633531089792464242134583740901169391964250459128813403498810635400887596820054408364386516617880557608956896727531538081942077332597917278437625661184319891025007491829086475149794003160703845549465385946027452447466812314687943441610993338908992638411847425257044572517459325738989565185716575961481266020310797628254165590506042479114016957900338356574869252800743025623419498286467914476322774005529460903940177536335655471931000175430047504719144899841040015867946179241610016454716551337074073950260442769538553834397550548871099785205401175169747581344926079433689543783221172450687344231989878844128542064742809735625807066983106979935260693392135685881391214807354728463227784908087002467776303605551232386656295178853719673034634701222939581606792509153217489030840886516061119011498443412350124646928028805996134283511884715449771278473361766285062169778717743824362565711779450064477718370221999106695021656757644044997940765037999954845002710665987813603802314126836905783190460792765297277694043613023051787080546511542469395265127101052927070306673024447125973939950514628404767431363739978259184541176413327906460636584152927019030276017339474866960348694976541752429306040727005059039503148522921392575594845078867977925253931765156416197168443524369794447355964260633391055126826061595726217036698506473281266724521989060549880280782881429796336696744124805982192146339565745722102298677599746738126069367069134081559412016115960190237753525556300606247983261249881288192937343476862689219239777833910733106588256813777172328315329082525092733047850724977139448333892552081175608452966590553940965568541706001179857293813998258319293679100391844099286575605993598910002969864460974714718470101531283762631146774209145574041815908800064943237855839308530828305476076799524357391631221886057549673832243195650655460852881201902363644712703748634421727257879503428486312944916318475347531435041392096108796057730987201352484075057637199253650470908582513936863463863368042891767107602111159828875539940120076013947033661793715396306139863655492213741597905119083588290097656647300733879314678913181465109316761575821351424860442292445304113160652700974330088499034675405518640677342603583409608605533747362760935658853109760994238347382222087292464497684560579562516765574088410321731345627735856052358236389532038534024842273371639123973215995440828421666636023296545694703577184873442034227706653837387506169212768015766181095420097708363604361110592409117889540338021426523948929686439808926114635414571535194342850721353453018315875628275733898268898523557799295727645229391567477566676051087887648453493636068278050564622813598885879259940946446041705204470046315137975431737187756039815962647501410906658866162180038266989961965580587208639721176995219466789857011798332440601811575658074284182910615193917630059194314434605154047710570054339000182453117733718955857603607182860506356479979004139761808955363669603162193113250223851791672055180659263518036251214575926238369348222665895576994660491938112486609099798128571823494006615552196112207203092277646200999315244273589488710576623894693889446495093960330454340842102462401048723328750081749179875543879387381439894238011762700837196053094383940063756116458560943129517597713935396074322792489221267045808183313764165818269562105872892447740035947009268662659651422050630078592002488291860839743732353849083964326147000532423540647042089499210250404726781059083644007466380020870126664209457181702946752278540074508552377720890581683918446592829417018288233014971554235235911774818
bv-little.cabal view
@@ -1,15 +1,26 @@-name: bv-little-version: 1.1.1-synopsis: Efficient little-endian bit vector library-category: Data, Bit Vectors-license: BSD3-license-file: LICENSE-author: Alex Washburn-maintainer: hackage@recursion.ninja-homepage: https://github.com/recursion-ninja/bv-little-bug-reports: https://github.com/recursion-ninja/bv-little/issues-copyright: (c) Alex Washburn 2018-description:+Cabal-Version: 3.0+Name: bv-little+Version: 1.3.0+Stability: Stable+Build-Type: Simple+Tested-With:+ GHC == 9.6.2+ GHC == 9.4.5+ GHC == 9.2.8+ GHC == 9.2.3++Author: Alex Washburn+Copyright: (c) Alex Washburn 2020+License: BSD-3-Clause+License-File: LICENSE++Maintainer: hackage@recursion.ninja+Homepage: https://github.com/recursion-ninja/bv-little+Bug-Reports: https://github.com/recursion-ninja/bv-little/issues++Synopsis: Efficient little-endian bit vector library+Category: Data, Bit Vectors+Description: . This package contains a time- and space- efficient implementation of /little-endian, immutable/ bit vectors. Provides implementations of applicable typeclasses and numeric conversions. .@@ -19,211 +30,325 @@ . For an implementation of /little-endian, mutable/ bit vectors, use the <https://hackage.haskell.org/package/bitvec bitvec> package. -build-type: Simple-cabal-version: >= 1.22--tested-with: GHC == 8.8.1- GHC == 8.6.5- GHC == 8.4.4- GHC == 8.2.2- GHC == 8.0.2- GHC == 7.10.3+Extra-Source-Files:+ stack.yaml -extra-source-files: changelog.md- README.md- stack.yaml+Extra-Doc-Files:+ changelog.md+ README.md -source-repository head+Source-repository head type: git location: https://github.com/recursion-ninja/bv-little +Common language -library+ default-extensions:+ NoGeneralizedNewtypeDeriving+ + default-language:+ GHC2021 - build-depends: base >= 4.5.1 && < 5- , deepseq >= 1.4.1.1- , hashable >= 1.2.3.2- , integer-gmp >= 1.0- , keys >= 3.10.1- , mono-traversable >= 1.0.5.0- , mono-traversable-keys >= 0.1.0- , primitive >= 0.6.4.0- , QuickCheck >= 2.8- , text-show >= 3.2.1 - if !impl(ghc >= 8.0)+Library - build-depends: semigroups >= 0.18 && < 1.0+ import:+ language - default-language: Haskell2010+ build-depends:+ base >= 4.16.1 && < 5,+ bv-little:core - exposed-modules: Data.BitVector.LittleEndian+ exposed-modules:+ Data.BitVector.LittleEndian - ghc-options: -O2+ hs-source-dirs:+ src - -- Sanity check warnings- -Wall- -fwarn-dodgy-foreign-imports- -fwarn-incomplete-record-updates- -fwarn-incomplete-uni-patterns- -fwarn-overlapping-patterns - -fwarn-duplicate-exports- -fwarn-identities- -fwarn-incomplete-patterns- -fwarn-incomplete-record-updates- -fwarn-incomplete-uni-patterns- -fwarn-missing-fields- -fwarn-missing-signatures- -fwarn-overlapping-patterns- -fwarn-tabs- -fwarn-unused-binds- -fwarn-unused-do-bind- -fwarn-unused-imports- -fwarn-unused-matches- -fwarn-wrong-do-bind+Library core - if impl(ghc >= 7.8)+ import:+ language - ghc-options: -fwarn-empty-enumerations- -fwarn-overflowed-literals+ build-depends:+ base >= 4.16.1 && < 5,+ deepseq >= 1.4.6 && ^>= 1.4,+ hashable >= 1.3 && ^>= 1.4,+ integer-gmp ^>= 1.1,+ primitive ^>= 0.7.2, - if impl(ghc >= 8.0)+ exposed-modules:+ Data.BitVector.LittleEndian.Internal - ghc-options: -Wcompat- -fwarn-noncanonical-monoid-instances- -fwarn-redundant-constraints- -fwarn-semigroup- -fwarn-unrecognised-warning-flags- -fwarn-unused-foralls+ hs-source-dirs:+ src/core - hs-source-dirs: src+ visibility:+ private -Test-Suite test-suite+Library instances - type: exitcode-stdio-1.0+ import:+ language - main-is: TestSuite.hs+ build-depends:+ bv-little:instances-binary,+ bv-little:instances-mono-traversable,+ bv-little:instances-mono-traversable-keys,+ bv-little:instances-quickcheck,+ bv-little:instances-text-show, - build-depends: base >= 4.5.1 && < 5- , bv-little- , deepseq >= 1.4.1.1- , hashable >= 1.2.3.2- , mono-traversable >= 1.0.5.0- , mono-traversable-keys >= 0.1.0- , QuickCheck >= 2.8- , smallcheck >= 1.1.5- , tasty- , tasty-hunit- , tasty-quickcheck- , tasty-smallcheck- , text-show >= 3.2.1+ exposed-modules:+ Data.BitVector.LittleEndian.Instances - if !impl(ghc >= 8.0)+ hs-source-dirs:+ src/full - build-depends: semigroups >= 0.18 && < 1.0- , transformers+ visibility:+ public - default-language: Haskell2010 - hs-source-dirs: test, util+Library instances-binary - other-modules: Data.BitVector.Visual- Operator.Binary.Comparison- Operator.Binary.Logical- Operator.Unary.Logical- + import:+ language -benchmark benchmark-suite+ build-depends:+ base >= 4.16.1 && < 5,+ binary ^>= 0.8,+ bv-little,+ bv-little:core, - type: exitcode-stdio-1.0+ exposed-modules:+ Data.BitVector.LittleEndian.Binary - main-is: Benchmarks.hs+ hs-source-dirs:+ src/libs - build-depends: base >= 4.5.1 && < 5- , bv-little- , criterion- , deepseq >= 1.4.1.1- , hashable >= 1.2.3.2- , mono-traversable >= 1.0.5.0- , QuickCheck >= 2.8- , smallcheck >= 1.1.5+ visibility:+ public - if !impl(ghc >= 8.0) - build-depends: semigroups >= 0.18 && < 1.0+Library instances-mono-traversable - default-language: Haskell2010+ import:+ language - ghc-options: -O2- -threaded- -fdicts-cheap- -fmax-simplifier-iterations=10- -fno-full-laziness- -fspec-constr-count=6+ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:core,+ mono-traversable >= 1.0.5.0 && ^>= 1.0 - -- Sanity check warnings- -Wall- -fwarn-dodgy-foreign-imports- -fwarn-incomplete-record-updates- -fwarn-incomplete-uni-patterns- -fwarn-overlapping-patterns+ exposed-modules:+ Data.BitVector.LittleEndian.MonoTraversable - -- Turn off type default warnings- -fno-warn-type-defaults+ hs-source-dirs:+ src/libs - hs-source-dirs: bench, util+ visibility:+ public - other-modules: Operator.Binary.Comparison- Operator.Binary.Logical- Operator.Unary.Logical- +Library instances-mono-traversable-keys -benchmark benchmark-heap-stack+ import:+ language - type: exitcode-stdio-1.0+ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:core,+ bv-little:instances-mono-traversable,+ keys ^>= 3.12,+ mono-traversable >= 1.0.5.0 && ^>= 1.0,+ mono-traversable-keys >= 0.2 && ^>= 0.3, - main-is: HeapStack.hs+ exposed-modules:+ Data.BitVector.LittleEndian.MonoKeyed - build-depends: base >= 4.5.1 && < 5- , bv-little- , criterion- , deepseq >= 1.4.1.1- , hashable >= 1.2.3.2- , mono-traversable >= 1.0.5.0- , QuickCheck >= 2.8- , smallcheck >= 1.1.5+ hs-source-dirs:+ src/keys - if !impl(ghc >= 8.0)+ visibility:+ public - build-depends: semigroups >= 0.18 && < 1.0 - default-language: Haskell2010+Library instances-quickcheck - ghc-options: -O2--- -ddump-simpl-stats- -threaded- -fdicts-cheap- -fmax-simplifier-iterations=10- -fno-full-laziness- -fspec-constr-count=6- -rtsopts--- -prof+ import:+ language - -- Sanity check warnings- -Wall- -fwarn-dodgy-foreign-imports- -fwarn-incomplete-record-updates- -fwarn-incomplete-uni-patterns- -fwarn-overlapping-patterns+ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:core,+ QuickCheck >= 2.14.2 && ^>= 2.14 - -- Turn off type default warnings- -fno-warn-type-defaults+ exposed-modules:+ Data.BitVector.LittleEndian.QuickCheck - hs-source-dirs: bench, util+ hs-source-dirs:+ src/libs - other-modules: Operator.Binary.Comparison- Operator.Binary.Logical- Operator.Unary.Logical+ visibility:+ public+++Library instances-text-show++ import:+ language++ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:core,+ text-show >= 3.9 && ^>= 3.10,++ exposed-modules:+ Data.BitVector.LittleEndian.TextShow++ hs-source-dirs:+ src/libs++ visibility:+ public+ ++Test-Suite Test-Suite++ import:+ language++ type:+ exitcode-stdio-1.0++ main-is:+ TestSuite.hs++ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:instances,+ deepseq >= 1.4.6 && ^>= 1.4,+ hashable >= 1.3 && ^>= 1.4,+ mono-traversable >= 1.0.5.0 && ^>= 1.0,+ mono-traversable-keys >= 0.2 && ^>= 0.3,+ QuickCheck >= 2.14.2 && ^>= 2.14.2,+ smallcheck >= 1.1.5 && ^>= 1.2,+ tasty,+ tasty-hunit,+ tasty-quickcheck,+ tasty-smallcheck,+ text-show >= 3.9 && ^>= 3.10,++ hs-source-dirs:+ test,+ util+ + other-modules:+ Data.BitVector.Visual+ Operator.Binary.Comparison+ Operator.Binary.Logical+ Operator.Unary.Logical+++Benchmark Benchmark-suite++ import:+ language++ type:+ exitcode-stdio-1.0++ main-is:+ Benchmarks.hs++ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:instances,+ criterion ^>= 1.6,+ deepseq >= 1.4.6 && ^>= 1.4,+ hashable >= 1.3 && ^>= 1.4,+ mono-traversable >= 1.0.5.0 && ^>= 1.0,+ QuickCheck >= 2.14.2 && ^>= 2.14.2,+ smallcheck >= 1.1.5 && ^>= 1.2,+ tasty ^>= 1.4,+ tasty-hunit ^>= 0.10,+ tasty-quickcheck ^>= 0.10,+ tasty-smallcheck ^>= 0.8,+ text-show >= 3.9 && ^>= 3.10,++ ghc-options:+ -threaded+ -fdicts-cheap+ -fmax-simplifier-iterations=10+ -fno-full-laziness+ -fspec-constr-count=6+ -fwarn-dodgy-foreign-imports+ -fwarn-incomplete-record-updates+ -fwarn-incomplete-uni-patterns+ -fwarn-overlapping-patterns+ -fno-warn-type-defaults++ hs-source-dirs:+ bench,+ util++ other-modules:+ Operator.Binary.Comparison+ Operator.Binary.Logical+ Operator.Unary.Logical+++Benchmark Benchmark-heap-stack++ import:+ language++ type:+ exitcode-stdio-1.0++ main-is: + HeapStack.hs++ build-depends:+ base >= 4.16.1 && < 5,+ bv-little,+ bv-little:instances,+-- criterion ^>= 1.6,+ deepseq >= 1.4.6 && ^>= 1.4,+-- hashable >=1.2.3.2,+-- mono-traversable >=1.0.5.0,+ QuickCheck >= 2.14.2 && ^>= 2.14.2,+ smallcheck >= 1.1.5 && ^>= 1.2,++ if !impl(ghc >=8.0)+ build-depends:+ semigroups >=0.18 && <1.0++ ghc-options:+ -threaded+ -fdicts-cheap+ -fmax-simplifier-iterations=10+ -fno-full-laziness+ -fspec-constr-count=6+ -rtsopts+ -fwarn-dodgy-foreign-imports+ -fwarn-incomplete-record-updates+ -fwarn-incomplete-uni-patterns+ -fwarn-overlapping-patterns+ -fno-warn-type-defaults++ hs-source-dirs:+ bench,+ util++ other-modules:+ Operator.Binary.Comparison+ Operator.Binary.Logical+ Operator.Unary.Logical
changelog.md view
@@ -1,26 +1,45 @@-### Unreleased Changes+`bv-little` *follows semantic versioning [(SemVer)](https://semver.org/).* - * None -### [v1.1.1][6]+## [v1.3.0][7] + * Added back `TextShow` instance++ * Added specializations++ * Dropping support for GHC < 9.2.3+++## v1.2.0++ * Restructuring library to expose instances in a refined, "opt-in" manner++ * Dropped support for GHC < 8.8.1++ * Added `Binary` instance++ * Added `Read` instance+++## [v1.1.1][6]+ * Added more benchmarks * Updated test suite to be more reliable -### [v1.1.0][5]+## [v1.1.0][5] * Added `rank` and `select` functions -### [v1.0.1][4]+## [v1.0.1][4] * Correcting Eq instance to test for value equality and not construction equality * Updated unit tests do not fail when the antecedent of logical implication cannot be satisfied -### [v1.0.0][3]+## [v1.0.0][3] * Added explicit recursion to monomorphic folds to improve time and space performance @@ -47,12 +66,12 @@ * `ozipWith` -### [v0.1.2][2]+## [v0.1.2][2] * Updating to base bounds for GHC 8.6.1 -### [v0.1.1][1]+## [v0.1.1][1] * Updated to well-typed internal representation @@ -67,7 +86,7 @@ * Increased test suite coverage -### [v0.1.0][0]+## [v0.1.0][0] * Created instances of applicable typeclass instances @@ -84,4 +103,5 @@ [3]: https://github.com/recursion-ninja/bv-little/tree/v1.0.0 [4]: https://github.com/recursion-ninja/bv-little/tree/v1.0.1 [5]: https://github.com/recursion-ninja/bv-little/tree/v1.1.0-[5]: https://github.com/recursion-ninja/bv-little/tree/v1.1.1+[6]: https://github.com/recursion-ninja/bv-little/tree/v1.1.1+[7]: https://github.com/recursion-ninja/bv-little/tree/v1.3.0
src/Data/BitVector/LittleEndian.hs view
@@ -1,1341 +1,54 @@--------------------------------------------------------------------------------- |--- Module : Data.BitVector.LittleEndian--- Copyright : (c) Alex Washburn 2018--- License : BSD-style------ Maintainer : github@recursion.ninja--- Stability : provisional--- Portability : portable------ A bit vector similar to @Data.BitVector@ from the--- <https://hackage.haskell.org/package/bv bv>, however the endianness is--- reversed. This module defines /little-endian/ pseudo–size-polymorphic--- bit vectors.------ Little-endian bit vectors are isomorphic to a @[Bool]@ with the /least/--- significant bit at the head of the list and the /most/ significant bit at the--- end of the list. Consequently, the endianness of a bit vector affects the semantics of the--- following typeclasses:------ * 'Bits'--- * 'FiniteBits'--- * 'Semigroup'--- * 'Monoid'--- * 'MonoAdjustable'--- * 'MonoIndexable'--- * 'MonoKeyed'--- * 'MonoLookup'--- * 'MonoFoldable'--- * 'MonoFoldableWithKey'--- * 'MonoTraversable'--- * 'MonoTraversableWithKey'--- * 'MonoZipWithKey'------ For an implementation of bit vectors which are isomorphic to a @[Bool]@ with the /most/--- significant bit at the head of the list and the /least/ significant bit at the--- end of the list, use the--- <https://hackage.haskell.org/package/bv bv> package.------ This module does /not/ define numeric instances for 'BitVector'. This is--- intentional! To interact with a bit vector as an 'Integral' value,--- convert the 'BitVector' using either 'toSignedNumber' or 'toUnsignedNumber'.------ This module defines 'rank' and 'select' operations for 'BitVector' as a--- <https://en.wikipedia.org/wiki/Succinct_data_structure succinct data structure>.--- These operations are not /o(1)/ so 'BitVector' is not a /true/ succinct data--- structure. However, it could potentially be extend to support this in the--- future.--------------------------------------------------------------------------------{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE Trustworthy #-}-{-# LANGUAGE TypeFamilies #-}--module Data.BitVector.LittleEndian- ( BitVector()- -- * Bit-stream conversion- , fromBits- , toBits- -- * Numeric conversion- , fromNumber- , toSignedNumber- , toUnsignedNumber- -- * Queries- , dimension- , isZeroVector- , subRange- -- * Rank / Select- , rank- , select- ) where---import Control.DeepSeq-import Data.Bits-import Data.Data-import Data.Foldable-import Data.Hashable-import Data.Key-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe-import Data.Monoid ()-import Data.MonoTraversable-import Data.MonoTraversable.Keys-import Data.Ord-import Data.Primitive.ByteArray-import Data.Semigroup-import GHC.Exts-import GHC.Generics-import GHC.Integer.GMP.Internals-import GHC.Integer.Logarithms-import GHC.Natural-import Test.QuickCheck (Arbitrary(..), CoArbitrary(..), NonNegative(..), choose, suchThat, variant)-import TextShow (TextShow(showb))----- |--- A little-endian bit vector of non-negative dimension.-data BitVector- = BV- { dim :: {-# UNPACK #-} !Word -- ^ The /dimension/ of a bit vector.- , nat :: !Natural -- ^ The value of a bit vector, as a natural number.- } deriving-#ifdef MIN_VERSION_GLASGOW_HASKELL-#if MIN_VERSION_GLASGOW_HASKELL(8,2,0,0)- ( Data -- ^ @since 0.1.0- , Generic -- ^ @since 0.1.0- , Typeable -- ^ @since 0.1.0- )-#else- ( Data- , Generic- , Typeable- )-#endif-#endif----- |--- @since 0.1.0-type instance Element BitVector = Bool----- |--- @since 1.0.0-type instance MonoKey BitVector = Word----- |--- @since 0.1.0-instance Arbitrary BitVector where-- -- Arbitrary instance distribution weighting:- -- - 2% = (maxBound :: Word)- -- - 2% = (maxBound :: Word) + 1- -- - 8% = all bits on- -- - 8% = all bits off- -- - 80% = any bit configuration- arbitrary = do- -- 1/25 chance of generating the boundary value at which the natural number- -- must use different Natural constructors: NatS# & NatJ# - n <- choose (0, 25 :: Word)- case n of- 0 -> boundaryValue- 1 -> allBitsOn- 2 -> allBitsOn- 3 -> allBitsOff- 4 -> allBitsOff- _ -> anyBitValue- where- allBitsOn = genBitVector $ Just True- allBitsOff = genBitVector $ Just False- anyBitValue = genBitVector Nothing- - boundaryValue = do- let wrdVal = maxBound :: Word- let dimVal = toEnum $ popCount wrdVal- let numVal = wordToNatural wrdVal- -- 50/50 change to generate above or below the constructor boundary- underBoundary <- arbitrary- let (lowerBound, naturalVal)- | underBoundary = (dimVal , numVal )- | otherwise = (dimVal + 1, numVal + 1)- widthVal <- (getNonNegative <$> arbitrary) `suchThat` (>= lowerBound)- pure $ BV widthVal naturalVal-- genBitVector spec = do- dimVal <- getNonNegative <$> arbitrary - let upperBound = shiftL 1 dimVal- -- 1/5 chance all bits on or all bits off- natVal <- case spec of- Just False -> pure $ intToNat 0- Just True -> pure . intToNat $ upperBound - 1- Nothing -> fmap intToNat $- (getNonNegative <$> arbitrary) `suchThat` (< upperBound)- pure $ BV (toEnum dimVal) natVal----- |--- @since 0.1.0-instance Bits BitVector where-- {-# INLINE (.&.) #-}- (BV w1 a) .&. (BV w2 b) = BV (max w1 w2) $ a .&. b-- {-# INLINE (.|.) #-}- (BV w1 a) .|. (BV w2 b) = BV (max w1 w2) $ a .|. b-- {-# INLINE xor #-}- (BV w1 a) `xor` (BV w2 b) = BV (max w1 w2) $ a `xor` b-- {-# INLINE complement #-}- complement (BV w n) = BV w $ shiftL 1 (fromEnum w) - 1 - n-- {-# INLINE zeroBits #-}- zeroBits = BV 0 0-- {-# INLINE bit #-}- bit i = BV (succ $ toEnum i) (shiftL 1 i)-- {-# INLINE clearBit #-}- -- We do this more complicated operation rather than call 'clearBit'- -- because it is undefined for Natural in base < 4.10.0.0- clearBit bv@(BV w n) i- | i < 0 || toEnum i >= w = bv- | otherwise =- let !allBits = pred . shiftL 1 $ fromEnum w- !mask = bit i `xor` allBits- in BV w $ n .&. mask-- {-# INLINE setBit #-}- setBit bv@(BV w n) i- | i < 0 = bv- | otherwise = BV (max w j) $ n `setBit` i- where- !j = toEnum i + 1-- {-# INLINE testBit #-}- testBit (BV w n) i = i >= 0 && toEnum i < w && n `testBit` i-- bitSize (BV w _) = fromEnum w-- {-# INLINE bitSizeMaybe #-}- bitSizeMaybe (BV w _) = Just $ fromEnum w-- {-# INLINE isSigned #-}- isSigned = const False-- {-# INLINE shiftL #-}- shiftL (BV w n) k- | toEnum k > w = BV w 0- | otherwise = BV w $ shiftL n k .&. pred (shiftL 1 (fromEnum w))-- {-# INLINE shiftR #-}- shiftR (BV w n) k- | toEnum k > w = BV w 0- | otherwise = BV w $ shiftR n k-- {-# INLINE rotateL #-}- rotateL bv 0 = bv- rotateL bv@(BV 0 _) _ = bv- rotateL bv@(BV 1 _) _ = bv- rotateL bv@(BV w n) k- | k < 0 = bv- | j >= w = go . fromEnum $ j `mod` w- | otherwise = go k- where- !j = toEnum k- go 0 = bv- go !i = BV w $ h + l- where- !v = fromEnum w- !d = v - i- !m = pred $ shiftL 1 d- !l = n `shiftR` d- !h = (n .&. m) `shiftL` i-- {-# INLINE rotateR #-}- rotateR bv 0 = bv- rotateR bv@(BV 0 _) _ = bv- rotateR bv@(BV 1 _) _ = bv- rotateR bv@(BV w n) k- | k < 0 = bv- | j >= w = go . fromEnum $ j `mod` w- | otherwise = go k- where- !j = toEnum k- go 0 = bv- go !i = BV w $ h + l- where- !v = fromEnum w- !d = v - i- !m = pred $ shiftL 1 i- !l = n `shiftR` i- !h = (n .&. m) `shiftL` d-- {-# INLINE popCount #-}- popCount = popCount . nat----- |--- @since 0.1.0-instance CoArbitrary BitVector where-- coarbitrary bv = variant (dimension bv)----- |--- @since 0.1.0-instance Eq BitVector where-- {-# INLINE (==) #-}- (==) (BV w1 m) (BV w2 n) = w1 == w2 && naturalToBigNat m == naturalToBigNat n- where- naturalToBigNat (NatS# w ) = wordToBigNat w- naturalToBigNat (NatJ# bn) = bn----- |--- @since 0.1.0-instance FiniteBits BitVector where-- {-# INLINE finiteBitSize #-}- finiteBitSize = fromEnum . dim-- {-# INLINE countTrailingZeros #-}- countTrailingZeros (BV w n) = max 0 $ fromEnum w - lastSetBit - 1- where- lastSetBit = I# (integerLog2# (toInteger n))-- {-# INLINE countLeadingZeros #-}- countLeadingZeros (BV w 0) = fromEnum w- countLeadingZeros (BV w natVal) =- case natVal of- NatS# v -> countTrailingZeros $ iMask .|. W# v- NatJ# (BN# v) -> f $ ByteArray v- where- iMask = complement zeroBits `xor` (2 ^ w - 1)- !x = fromEnum w-- f :: ByteArray -> Int- f byteArr = g 0- where- (q, r) = x `quotRem` fromEnum bitsInWord- wMask = complement zeroBits `xor` (2 ^ r - 1) :: Word-- g :: Int -> Int- g !i- | i >= q = countTrailingZeros $ wMask .|. value- | otherwise =- let !v = countTrailingZeros value- in if v == fromEnum bitsInWord- then v + g (i+1)- else v- where- value :: Word- value = byteArr `indexByteArray` i----- |--- @since 0.1.0-instance Hashable BitVector where-- hash (BV w n) = fromEnum w `hashWithSalt` hash n-- hashWithSalt salt bv = salt `hashWithSalt` hash bv----- |--- @since 0.1.0-instance Monoid BitVector where-- {-# INLINE mappend #-}- mappend = (<>)-- {-# INLINE mconcat #-}- mconcat bs =- case bs of- [] -> mempty- x:xs -> sconcat $ x:|xs-- {-# INLINE mempty #-}- mempty = BV 0 0----- |--- @since 1.0.0-instance MonoAdjustable BitVector where-- -- | /O(1)/- {-# INLINE oadjust #-}- oadjust f k bv@(BV w n)- | k >= w = bv- | v == b = bv- | otherwise = bv `complementBit` i- where- !i = fromEnum k- !v = n `testBit` i- !b = f v-- -- | /O(1)/- {-# INLINE oreplace #-}- oreplace k v bv@(BV w _)- | k >= w = bv- | v = bv `setBit` i- | otherwise = bv `clearBit` i- where- !i = fromEnum k----- |--- @since 0.1.0-instance MonoFoldable BitVector where-- {-# INLINE ofoldMap #-}- ofoldMap f (BV w n) = go m- where- !m = fromEnum w- go 0 = mempty- go !c = let !i = m - c- !j = c - 1- !b = n `testBit` i- in f b `mappend` go j- - {-# INLINE ofoldr #-}- ofoldr f e (BV w n) =- let !m = fromEnum w- go 0 acc = acc- go !c acc = let !i = m - c- !j = c - 1- !b = n `testBit` i- in f b $ go j acc- in go m e-- {-# INLINE ofoldl' #-}- ofoldl' f e (BV w n) = go m e- where- !m = fromEnum w- go 0 acc = acc- go !c acc = let !i = m - c- !j = c - 1- !b = n `testBit` i- !a = f acc b- in go j a-- {-# INLINE otoList #-}- otoList = toBits-- -- | /O(1)/- {-# INLINE oall #-}- oall _ (BV 0 _) = True- oall f (BV w n) =- case (f False, f True) of- (False, False) -> False- (True , True ) -> True- (False, True ) -> n == bit (fromEnum w) - 1- (True , False) -> n == 0-- -- | /O(1)/- {-# INLINE oany #-}- oany _ (BV 0 _) = False- oany f (BV w n) =- case (f False, f True) of- (False, False) -> False- (True , True ) -> True- (False, True ) -> n > 0- (True , False) -> n < bit (fromEnum w) - 1-- -- | /O(1)/- {-# INLINE onull #-}- onull = (== 0) . dim-- -- | /O(1)/- {-# INLINE olength #-}- olength = fromEnum . dim-- -- | /O(1)/- {-# INLINE olength64 #-}- olength64 = toEnum . olength-- {-# INLINE otraverse_ #-}- otraverse_ f (BV w n) = go (fromEnum w) - where- go 0 = pure ()- go !c = let !j = c - 1- !a = f (n `testBit` j)- in a *> go j--- {-# INLINE ofoldlM #-}- ofoldlM f e (BV w n) = go (fromEnum w) e- where- go 0 acc = pure acc- go !c acc = let !j = c - 1- !x = f acc (n `testBit` j)- in x >>= go j- - {-# INLINE ofoldMap1Ex #-}- ofoldMap1Ex _ (BV 0 _) = Prelude.error "Data.MonoTraversable.ofoldMap1Ex on an empty BitVector!"- ofoldMap1Ex f (BV w n) = go 0- where- !m = fromEnum w- go !c- | c >= m - 1 = f $ n `testBit` c- | otherwise = let !j = c + 1- !b = n `testBit` c- in f b <> go j-- -- | /O(1)/- {-# INLINE ofoldr1Ex #-}- ofoldr1Ex _ (BV 0 _) = Prelude.error "Data.MonoTraversable.ofoldr1Ex on an empty BitVector!"- ofoldr1Ex _ (BV 1 n) = n > 0- ofoldr1Ex f bv@(BV w n) =- -- See the following entry for explanation:- -- https://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators- --- -- cases of f p q- case (f True True, f True False, f False True, f False False) of- -- Contradiction (Const False)- (False, False, False, False) -> False- -- Logical NOR- (False, False, False, True ) -> let !lzs = toEnum $ countLeadingZeros bv- in if (w - lzs) == 1 || n == 0- then even lzs- else odd lzs- -- Converse non-implication- -- Only True when of the form <0+1>- (False, False, True , False) -> n == bit (fromEnum w - 1)- -- NOT p- (False, False, True , True ) -> not (n `testBit` 0)- -- Logical non-implication- -- Only True when the number of leading ones is even- (False, True , False, False) -> let !los = countLeadingZeros $ complement bv- in odd los- -- NOT q- (False, True , False, True ) -> let !v = n `testBit` (fromEnum w - 1)- in if even w then not v else v- -- Logical XOR- (False, True , True , False) -> odd $ popCount n- -- Logical NAND- (False, True , True , True ) -> let !los = countLeadingZeros $ complement bv- !x = bit (fromEnum w - 1) - 1- !y = bit (fromEnum w ) - 1- in if n == x || n == y- then odd los- else even los- -- Logical AND- (True , False, False, False) -> n == bit (fromEnum w) - 1- -- Logical XNOR- (True , False, False, True ) -> let !pc = popCount n- in if even w- then even pc- else odd pc- -- Const q- (True , False, True , False) -> n `testBit` (fromEnum w - 1)- -- Logical implication- -- only False when of the form <1+0>- (True , False, True , True ) -> let !i = fromEnum w - 1- in n /= bit i - 1- -- Const p- (True , True , False, False) -> n `testBit` 0- -- Converse implication- (True , True , False, True ) -> even $ countLeadingZeros bv- -- Logical OR- (True , True , True , False) -> n > 0- -- Constant True- (True , True , True , True ) -> True-- -- | /O(n)/- {-# INLINE ofoldl1Ex' #-}- ofoldl1Ex' _ (BV 0 _) = Prelude.error "Data.MonoTraversable.ofoldl1Ex' on an empty BitVector!"- ofoldl1Ex' _ (BV 1 n) = n > 0- ofoldl1Ex' f bv@(BV w n) =- -- See the following entry for explanation:- -- https://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators- --- -- cases of f p q- case (f True True, f True False, f False True, f False False) of- -- Contradiction (Const False)- (False, False, False, False) -> False- -- Logical NOR- (False, False, False, True ) -> let !tzs = toEnum $ countTrailingZeros bv- in if (w - tzs) == 1 || n == 0- then even tzs- else odd tzs- -- Converse non-implication- (False, False, True , False) -> let !tzs = countTrailingZeros $ complement bv- in odd tzs- -- NOT p- (False, False, True , True ) -> even w == even n- -- Logical non-implication- (False, True , False, False) -> n == 1- -- NOT q- (False, True , False, True ) -> not $ n `testBit` (fromEnum w - 1)- -- Logical XOR- (False, True , True , False) -> odd $ popCount n- -- Logical NAND- (False, True , True , True ) -> let !tos = countTrailingZeros $ complement bv- !x = bit (fromEnum w) - 1- !y = bit (fromEnum w) - 2- in if n == x || n == y- then odd tos- else even tos- -- Logical AND- (True , False, False, False) -> n == bit (fromEnum w) - 1- -- Logical XNOR- (True , False, False, True ) -> let !pc = popCount n- in if even w- then even pc- else odd pc- -- Const q- (True , False, True , False) -> n `testBit` (fromEnum w - 1)- -- Logical implication- (True , False, True , True ) -> even $ countTrailingZeros bv- -- Const p- (True , True , False, False) -> n `testBit` 0- -- Converse implication- -- only False when of the form <01+>- (True , True , False, True ) -> n /= bit (fromEnum w) - 2- -- Logical OR- (True , True , True , False) -> n > 0- -- Constant True- (True , True , True , True ) -> True-- -- | /O(1)/- {-# INLINE headEx #-}- headEx (BV 0 _) = error "Call to Data.MonoFoldable.headEx on an empty BitVector!"- headEx (BV _ n) = n `testBit` 0-- -- | /O(1)/- {-# INLINE lastEx #-}- lastEx (BV 0 _) = error "Call to Data.MonoFoldable.lastEx on an empty BitVector!"- lastEx (BV w n) = n `testBit` (fromEnum w - 1)-- -- | /O(n)/- {-# INLINE maximumByEx #-}- maximumByEx _ (BV 0 _) = error "Call to Data.MonoFoldable.maximumByEx on an empty BitVector!"- maximumByEx _ (BV 1 n) = n /= 0- maximumByEx f bv = maximumBy f $ toBits bv-- -- | /O(n)/- {-# INLINE minimumByEx #-}- minimumByEx _ (BV 0 _) = error "Call to Data.MonoFoldable.minimumByEx on an empty BitVector!"- minimumByEx _ (BV 1 n) = n /= 0- minimumByEx f bv = minimumBy f $ toBits bv-- -- | /O(1)/- {-# INLINE oelem #-}- oelem _ (BV 0 _) = False- oelem True (BV _ n) = n > 0- oelem False (BV w n) = n < bit (fromEnum w) - 1-- -- | /O(1)/- {-# INLINE onotElem #-}- onotElem e = not . oelem e----- |--- @since 1.0.0-instance MonoFoldableWithKey BitVector where-- -- | /O(n)/- {-# INLINE otoKeyedList #-}- otoKeyedList (BV w n) = - let go 0 = []- go !c = let !k = w - c- !v = n `testBit` fromEnum k- !i = c - 1- in (k, v) : go i- in go w-- -- | /O(n)/- {-# INLINE ofoldMapWithKey #-}- ofoldMapWithKey f (BV w n) =- let go 0 = mempty- go !c = let !k = w - c- !v = n `testBit` fromEnum k- !i = c - 1- !m = f k v- in m `mappend` go i- in go w-- -- | /O(n)/- {-# INLINE ofoldrWithKey #-}- ofoldrWithKey f e (BV w n) =- let go 0 acc = acc- go !c acc = let !k = w - c- !i = c - 1- !b = n `testBit` fromEnum k- in f k b $ go i acc- in go w e-- -- | /O(n)/- {-# INLINE ofoldlWithKey #-}- ofoldlWithKey f e (BV w n) = go w e- where- go 0 acc = acc- go !c acc = let !k = w - c- !i = c - 1- !b = n `testBit` fromEnum k- !a = f acc k b- in go i a----- |--- @since 0.1.0-instance MonoFunctor BitVector where-- -- | /O(1)/- {-# INLINE omap #-}- omap f bv@(BV w n) =- case (f False, f True) of- (False, False) -> BV w 0- (True , True ) -> BV w $ bit (fromEnum w) - 1- (False, True ) -> bv- (True , False) -> let !allOnes = bit (fromEnum w) - 1- in BV w $ n `xor` allOnes----- |--- @since 1.0.0-instance MonoIndexable BitVector where-- -- | /O(1)/- {-# INLINE oindex #-}- oindex bv@(BV w _) i = fromMaybe errorMessage $ i `olookup` bv- where- errorMessage = error $ mconcat- [ "Data.BitVector.LittleEndian.oindex: "- , "The index "- , show i- , " was greater than or equal to the length of the bit vector "- , show w- ] ----- |--- @since 1.0.0-instance MonoKeyed BitVector where-- -- | /O(n)/- {-# INLINE omapWithKey #-}- omapWithKey f (BV w n) =- let go 0 acc = acc- go !c acc = let !k = w - c- !i = fromEnum k- !j = c - 1- !b = n `testBit` i- !a | f k b = acc `setBit` i- | otherwise = acc- in go j a- in go w $ BV w 0----- |--- @since 1.0.0-instance MonoLookup BitVector where-- -- | /O(1)/- {-# INLINE olookup #-}- olookup k (BV w n)- | k <= w = Nothing- | otherwise = Just $ n `testBit` fromEnum k----- |--- @since 0.1.0-instance MonoTraversable BitVector where-- -- | /O(n)/- {-# INLINE otraverse #-}- otraverse f = fmap fromBits . traverse f . toBits-- -- | /O(n)/- {-# INLINE omapM #-}- omapM = otraverse----- |--- @since 1.0.0-instance MonoTraversableWithKey BitVector where-- -- | /O(n)/- {-# INLINE otraverseWithKey #-}- otraverseWithKey f = fmap fromBits . traverseWithKey (f . toEnum) . toBits-- --- |--- @since 1.0.0-instance MonoZip BitVector where-- -- | /O(1)/- {-# INLINE ozipWith #-}- ozipWith f lhs@(BV w1 p) rhs@(BV w2 q) =- let !w0 = min w1 w2- !mask = bit (fromEnum w0) - 1- bv = BV w0 . (mask .&.)- not' = nat . complement- -- See the following entry for explanation:- -- https://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators- --- -- cases of f p q- in case (f True True, f True False, f False True, f False False) of- -- Contradiction (Const False)- (False, False, False, False) -> bv 0- -- Logical NOR- (False, False, False, True ) -> bv $ not' lhs .&. not' rhs- -- Converse non-implication- (False, False, True , False) -> bv $ not' lhs .&. q- -- NOT p- (False, False, True , True ) -> bv $ not' lhs- -- Logical non-implication- (False, True , False, False) -> bv $ p .&. not' rhs- -- NOT q- (False, True , False, True ) -> bv $ not' rhs- -- Logical XOR- (False, True , True , False) -> bv $ p `xor` q- -- Logical NAND- (False, True , True , True ) -> bv $ not' lhs .|. not' rhs- -- Logical AND- (True , False, False, False) -> bv $ p .&. q- -- Logical XNOR- (True , False, False, True ) -> bv $ (p .&. q) .|. (not' lhs .&. not' rhs)- -- Const q- (True , False, True , False) -> bv q- -- Logical implication- (True , False, True , True ) -> bv $ not' lhs .|. q- -- Const p- (True , True , False, False) -> bv p- -- Converse implication- (True , True , False, True ) -> bv $ p .|. not' rhs- -- Logical OR- (True , True , True , False) -> bv $ p .|. q- -- Constant True- (True , True , True , True ) -> bv $ bit (fromEnum w0) - 1-- --- |--- @since 1.0.0-instance MonoZipWithKey BitVector where-- {-# INLINE ozipWithKey #-}- ozipWithKey f (BV w1 n) (BV w2 m) =- let w0 = min w1 w2- go 0 _ = 0- go c e = let !k = w0 - c- !i = fromEnum k- !j = c - 1- !b = f k (n `testBit` i) (m `testBit` i)- !a = e `shiftL` 1- !v = if b then e else 0- in v + go j a- in BV w0 $ go w0 1----- |--- @since 0.1.0-instance NFData BitVector where-- -- Already a strict data type,- -- always in normal form.- {-# INLINE rnf #-}- rnf = const ()----- |--- @since 0.1.0-instance Ord BitVector where-- {-# INLINE compare #-}- compare lhs rhs =- case comparing dim lhs rhs of- EQ -> comparing nat lhs rhs- v -> v----- |--- @since 0.1.0-instance Semigroup BitVector where-- {-# INLINE (<>) #-}- (<>) (BV x m) (BV y n) = BV (x + y) $ (n `shiftL` fromEnum x) + m-- {-# INLINABLE sconcat #-}- sconcat xs = BV w' n'- where- (w', _, n') = foldl' f (0, 0, 0) xs- f (bitCountW, bitCountI, natVal) (BV w n) =- (bitCountW + w, bitCountI + fromEnum w, natVal + (n `shiftL` bitCountI))-- {-# INLINE stimes #-}- stimes 0 _ = mempty- stimes e (BV w n) = BV limit $ go start n- where- !x = fromEnum w- !start = fromEnum $ limit - w- !limit = (toEnum . fromEnum) e * w- go 0 !acc = acc- go !k !acc = go (k-x) $ (n `shiftL` k) + acc----- |--- @since 0.1.0-instance Show BitVector where-- show (BV w n) = mconcat [ "[", show w, "]", show n ]----- |--- @since 1.0.0-instance TextShow BitVector where-- showb (BV w n) = mconcat [ "[", showb w, "]", showb n ]----- |--- Create a bit vector from a /little-endian/ list of bits.------ The following will hold:------ > length . takeWhile not === countLeadingZeros . fromBits--- > length . takeWhile not . reverse === countTrailingZeros . fromBits------ /Time:/ \(\, \mathcal{O} \left( n \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> fromBits [True, False, False]--- [3]1-{-# INLINE fromBits #-}-fromBits :: Foldable f => f Bool -> BitVector-fromBits bs = BV (toEnum n) k- -- NB: 'setBit' is a GMP function, faster than regular addition.- where- (!n, !k) = foldl' go (0, 0) bs- go (!i, !v) b- | b = (i+1, v `setBit` i)- | otherwise = (i+1, v)----- |--- Create a /little-endian/ list of bits from a bit vector.------ The following will hold:------ > length . takeWhile not . toBits === countLeadingZeros--- > length . takeWhile not . reverse . toBits === countTrailingZeros------ /Time:/ \(\, \mathcal{O} \left( n \right) \)------ /Since:/ 0.1.0------ ==== __Examples__------ >>> toBits [4]11--- [True, True, False, True]-{-# INLINE toBits #-}-toBits :: BitVector -> [Bool]-toBits (BV w n) = go (fromEnum w) []- where- go 0 bs = bs- go i bs = let !j = i - 1- in go j $ n `testBit` j : bs----- |--- Create a bit vector of non-negative dimension from an integral value.------ The integral value will be treated as an /signed/ number and the resulting--- bit vector will contain the two's complement bit representation of the number.------ The integral value will be interpreted as /little-endian/ so that the least--- significant bit of the integral value will be the value of the 0th index of--- the resulting bit vector and the most significant bit of the integral value--- will be at index @dimension − 1@.------ Note that if the bit representation of the integral value exceeds the--- supplied dimension, then the most significant bits will be truncated in the--- resulting bit vector.------ /Time:/ \(\, \mathcal{O} \left( 1 \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> fromNumber 8 96--- [8]96------ >>> fromNumber 8 -96--- [8]160------ >>> fromNumber 6 96--- [6]32-{-# INLINE[1] fromNumber #-}-fromNumber- :: Integral v- => Word -- ^ dimension of bit vector- -> v -- ^ /signed, little-endian/ integral value- -> BitVector-fromNumber !dimValue !intValue = BV dimValue . intToNat $ mask .&. v- where- !v | signum int < 0 = negate $ shiftL 1 intBits - int- | otherwise = int-- !int = toInteger intValue- !intBits = I# (integerLog2# int)- !mask = 2 ^ dimValue - 1---{-# RULES-"fromNumber/Natural" forall w (n :: Natural). fromNumber w n = BV w n-"fromNumber/Word" forall w (v :: Word ). fromNumber w v = BV w (wordToNatural v)- #-}----- |--- Two's complement value of a bit vector.------ /Time:/ \(\, \mathcal{O} \left( 1 \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> toSignedNumber [4]0--- 0------ >>> toSignedNumber [4]3--- 3------ >>> toSignedNumber [4]7--- 7------ >>> toSignedNumber [4]8--- -8------ >>> toSignedNumber [4]12--- -4------ >>> toSignedNumber [4]15--- -1-{-# INLINE toSignedNumber #-}-toSignedNumber :: Num a => BitVector -> a-toSignedNumber (BV w n) = fromInteger v- where- !i = toInteger n- !v | n `testBit` (fromEnum w - 1) = negate $ shiftL 1 (fromEnum w) - i- | otherwise = i----- |--- Unsigned value of a bit vector.------ /Time:/ \(\, \mathcal{O} \left( 1 \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> toSignedNumber [4]0--- 0------ >>> toSignedNumber [4]3--- 3------ >>> toSignedNumber [4]7--- 7------ >>> toSignedNumber [4]8--- 8------ >>> toSignedNumber [4]12--- 12------ >>> toSignedNumber [4]15--- 15-{-# INLINE[1] toUnsignedNumber #-}-toUnsignedNumber :: Num a => BitVector -> a-toUnsignedNumber = fromInteger . toInteger . nat---{-# RULES-"toUnsignedNumber/Natural" toUnsignedNumber = nat- #-}----- |--- Get the dimension of a 'BitVector'. Preferable to 'finiteBitSize' as it--- returns a type which cannot represent a non-negative value and a 'BitVector'--- must have a non-negative dimension.------ /Time:/ \(\, \mathcal{O} \left( 1 \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> dimension [2]3--- 2------ >>> dimension [4]12--- 4-{-# INLINE dimension #-}-dimension :: BitVector -> Word-dimension = dim----- |--- Determine if /any/ bits are set in the 'BitVector'.--- Faster than @(0 ==) . popCount@.------ /Time:/ \(\, \mathcal{O} \left( 1 \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> isZeroVector [2]3--- False------ >>> isZeroVector [4]0--- True-{-# INLINE isZeroVector #-}-isZeroVector :: BitVector -> Bool-isZeroVector = (0 ==) . nat----- |--- Get the /inclusive/ range of bits in 'BitVector' as a new 'BitVector'.------ If either of the bounds of the subrange exceed the bit vector's dimension,--- the resulting subrange will append an infinite number of zeroes to the end--- of the bit vector in order to satisfy the subrange request.------ /Time:/ \(\, \mathcal{O} \left( 1 \right) \)------ /Since: 0.1.0/------ ==== __Examples__------ >>> subRange (0,2) [4]7--- [3]7------ >>> subRange (1, 3) [4]7--- [3]3------ >>> subRange (2, 4) [4]7--- [3]1------ >>> subRange (3, 5) [4]7--- [3]0------ >>> subRange (10, 20) [4]7--- [10]0-{-# INLINE subRange #-}-subRange :: (Word, Word) -> BitVector -> BitVector-subRange (!lower, !upper) (BV _ n)- | lower > upper = zeroBits- | otherwise =- case toInt lower of- Nothing -> zeroBits- Just i ->- let b = n `shiftR` i- in case toInt upper of- Nothing ->- let m = toEnum $ maxBound - i + 1- in BV m $ n `shiftR` i- Just j ->- let x = j - i- m | x == maxBound = x- | otherwise = x + 1- in BV (toEnum m) $ b .&. pred (1 `shiftL` m)------ |--- Determine the number of /set/ bits in the 'BitVector' up to, /but not including/, index @k@.------ To determine the number of /unset/ bits in the 'BitVector`, use @k - rank bv k@.------ Uses "broadword programming." Efficient on small 'BitVector's (10^3).------ /Time:/ \(\, \mathcal{O} \left( \frac{n}{w} \right) \), where \(w\) is the number of bits in a 'Word'.------ /Since: 1.1.0/------ ==== __Examples__------ >>> let bv = fromNumber 128 0 `setBit` 0 `setBit` 65------ >>> rank bv 0 -- Count how many ones in the first 0 bits (always returns 0)--- 0------ >>> rank bv 1 -- Count how many ones in the first 1 bits--- 1------ >>> rank bv 2 -- Count how many ones in the first 2 bits--- 1------ >>> rank bv 65 -- Count how many ones in the first 65 bits--- 1------ >>> rank bv 66 -- Count how many ones in the first 66 bits--- 1------ >>> rank bv 128 -- Count how many ones in all 128 bits--- 2------ >>> rank bv 129 -- Out-of-bounds, fails gracefully--- 2-rank- :: BitVector- -> Word -- ^ \(k\), the rank index - -> Word -- ^ Set bits within the rank index-rank _ 0 = 0 -- There can be no set bits /before/ the 0-th bit-rank (BV 0 _) _ = 0 -- There can be no set bits in a bit-vector of length 0-rank (BV w natVal) k =- let j = min k w- in case natVal of- NatS# v -> wordRank (W# v) j- NatJ# (BN# v) -> f (ByteArray v) j- where- f :: ByteArray -> Word -> Word- f byteArr x = g x 0- where- g :: Word -> Int -> Word- g !j !i- | j < bitsInWord = wordRank value j- | otherwise = let !v = toEnum $ popCount value- in v + g (j - bitsInWord) (i+1)- where- value :: Word- value = byteArr `indexByteArray` i----- |--- Find the index of the k-th set bit in the 'BitVector'.------ To find the index of the k-th /unset/ bit in the 'BitVector`, use @select (complement bv) k@.------ Uses "broadword programming." Efficient on small 'BitVector's (10^3).------ /Time:/ \(\, \mathcal{O} \left( \frac{n}{w} \right) \), where \(w\) is the number of bits in a 'Word'.------ /Since: 1.1.0/------ ==== __Examples__------ >>> let bv = fromNumber 128 0 `setBit` 0 `setBit` 65------ >>> select bv 0 -- Find the 0-indexed position of the first one bit--- Just 0------ >>> select bv 1 -- Find the 0-indexed position of the second one bit--- Just 65------ >>> select bv 2 -- There is no 3rd set bit, `select` fails--- Nothing-select- :: BitVector- -> Word -- ^ \(k\), the select index - -> Maybe Word -- ^ index of the k-th set bit-select (BV 0 _) _ = Nothing -- There can be no set bits in a bit-vector of length 0-select (BV w natVal) k =- case natVal of- NatS# v -> let !u = W# v- in if toEnum (popCount u) <= k- then Nothing- else Just $ wordSelect u k- NatJ# (BN# v) -> f (ByteArray v) k- where- f :: ByteArray -> Word -> Maybe Word- f byteArr x = g x 0- where- g :: Word -> Int -> Maybe Word- g !j !i- | toEnum i * bitsInWord >= w = Nothing- | j < ones = Just $ wordSelect value j- | otherwise = (bitsInWord +) <$> g (j - ones) (i+1)- where- ones = toEnum $ popCount value- value :: Word- value = byteArr `indexByteArray` i----- |--- Number of bits in a 'Word'.------ Used for "broadword programming."-{-# INLINE bitsInWord #-}-bitsInWord :: Word-bitsInWord = toEnum $ finiteBitSize (undefined :: Word)----- |--- Clever use of 'popCount' and masking to get the number of set bits up to,--- /but not including/, index "k."-wordRank- :: Word -- ^ Input 'Word'- -> Word -- ^ Index k, upt to which we count all set bits, k in range [ 0, finiteBitCount - 1 ]- -> Word -- ^ THe number of bits set within index "k."-wordRank v x = toEnum . popCount $ suffixOnes .&. v- where- suffixOnes = (1 `shiftL` fromEnum x) - 1----- |--- Perform binary search with 'popCount' to locate the k-th set bit-wordSelect- :: Word -- ^ Input 'Word'- -> Word -- ^ Find the k-th set bit, k in range [ 0, finiteBitCount - 1 ]- -> Word -- ^ The index of the k-th set bit-wordSelect v = go 0 63- where- go :: Word -> Word -> Word -> Word- go lb ub x- | lb + 1 == ub = if x == 0 && v `testBit` fromEnum lb then lb else ub- | otherwise =- let !lowOnes = toEnum . popCount $ lowMask .&. v- in if lowOnes > x- then go lb mb x- else go (mb + 1) ub (x - lowOnes)- where- mb = ((ub - lb) `div` 2) + lb- lowMask = makeMask lb mb-- makeMask i j = wideMask `xor` thinMask- where- thinMask = (1 `shiftL` fromEnum i) - 1- wideMask- | j == bitsInWord - 1 = maxBound :: Word- | otherwise = (1 `shiftL` (fromEnum j + 1)) - 1---toInt :: Word -> Maybe Int-toInt w- | w > maxInt = Nothing- | otherwise = Just $ fromEnum w- where- maxInt = toEnum (maxBound :: Int)----- |--- While similar to the function 'naturalFromInteger' exported from GHC.Natural,--- this function does not throw an exception when an negative valued 'Integer'--- is supplied and is also compatible with base < 4.10.0.0.-{-# INLINE intToNat #-}--- {-# NOINLINE intToNat #-}-intToNat :: Integer -> Natural-intToNat (S# i#) | isTrue# (i# >=# 0#) = NatS# (int2Word# i#)-intToNat (Jp# bn) | isTrue# (sizeofBigNat# bn ==# 1#) = NatS# (bigNatToWord bn)- | otherwise = NatJ# bn-intToNat _ = NatS# (int2Word# 0#)+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++A bit vector similar to @Data.BitVector@ from the+<https://hackage.haskell.org/package/bv bv>, however the endianness is+reversed. This module defines /little-endian/ pseudo–size-polymorphic+bit vectors.++Little-endian bit vectors are isomorphic to a @[Bool]@ with the /least/+significant bit at the head of the list and the /most/ significant bit at the+end of the list. Consequently, the endianness of a bit vector affects the semantics+of many type-classes that have a linear ordering.++For an implementation of bit vectors which are isomorphic to a @[Bool]@ with the /most/+significant bit at the head of the list and the /least/ significant bit at the+end of the list, use the+<https://hackage.haskell.org/package/bv bv> package.++This module does /not/ define numeric instances for 'BitVector'. This is+intentional! To interact with a bit vector as an 'Integral' value,+convert the 'BitVector' using either 'toSignedNumber' or 'toUnsignedNumber'.++This module defines 'rank' and 'select' operations for 'BitVector' as a+<https://en.wikipedia.org/wiki/Succinct_data_structure succinct data structure>.+These operations are not /o(1)/ so 'BitVector' is not a /true/ succinct data+structure. However, it could potentially be extend to support this in the+future.+-}++{-# Language Safe #-}++module Data.BitVector.LittleEndian+ ( BitVector ()+ -- * Bit-stream conversion+ , fromBits+ , toBits+ -- * Numeric conversion+ , fromNumber+ , toSignedNumber+ , toUnsignedNumber+ -- * Queries+ , dimension+ , isZeroVector+ , subRange+ -- * Rank / Select+ , rank+ , select+ ) where++import Data.BitVector.LittleEndian.Internal
+ src/core/Data/BitVector/LittleEndian/Internal.hs view
@@ -0,0 +1,831 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Little-endian bit vectors are isomorphic to a @[Bool]@ with the /least/+significant bit at the head of the list and the /most/ significant bit at the+end of the list. Consequently, the endianness of a bit vector affects the semantics of the+following typeclasses:++ * Bits+ * FiniteBits+ * Semigroup+ * Monoid+ * MonoAdjustable+ * MonoIndexable+ * MonoKeyed+ * MonoLookup+ * MonoFoldable+ * MonoFoldableWithKey+ * MonoTraversable+ * MonoTraversableWithKey+ * MonoZipWithKey++-}++{-# Language BangPatterns #-}+{-# Language CPP #-}+{-# Language DeriveAnyClass #-}+{-# Language DeriveDataTypeable #-}+{-# Language DeriveGeneric #-}+{-# Language DerivingStrategies #-}+{-# Language MagicHash #-}+{-# Language OverloadedStrings #-}+{-# Language Trustworthy #-}+{-# Language TypeFamilies #-}+{-# Language UnicodeSyntax #-}++module Data.BitVector.LittleEndian.Internal+ ( BitVector (..)+ , dimension+ , fromBits+ , fromNumber+ , isZeroVector+ , rank+ , select+ , subRange+ , toBits+ , toSignedNumber+ , toUnsignedNumber+ ) where++import Control.DeepSeq+import Control.Monad (when)+import Data.Bits+import Data.Data+import Data.Foldable+import Data.Hashable+import Data.Int+import Data.List.NonEmpty (NonEmpty(..))+import Data.Monoid ()+import Data.Ord+import Data.Primitive.ByteArray+import Data.Semigroup+import Data.Word+import Foreign.C.Types+import GHC.Exts+import GHC.Generics (Generic)+import GHC.Integer.GMP.Internals+import GHC.Integer.Logarithms+import GHC.Natural+import Text.Read+++{-|+A little-endian bit vector of non-negative dimension.+-}+data BitVector+ = BV+ { dim :: {-# UNPACK #-} !Word+ -- ^ The /dimension/ of a bit vector.+ , nat :: !Natural+ -- ^ The value of a bit vector, as a natural number.+ }+++{-| @since 0.1.0 -}+deriving stock instance Data BitVector+++{-| @since 0.1.0 -}+deriving stock instance Generic BitVector+++{-| @since 0.1.0 -}+deriving anyclass instance NFData BitVector+++{-| @since 0.1.0 -}+instance Bits BitVector where++ {-# INLINE (.&.) #-}+ (BV w1 a) .&. (BV w2 b) = BV (max w1 w2) $ a .&. b++ {-# INLINE (.|.) #-}+ (BV w1 a) .|. (BV w2 b) = BV (max w1 w2) $ a .|. b++ {-# INLINE xor #-}+ (BV w1 a) `xor` (BV w2 b) = BV (max w1 w2) $ a `xor` b++ {-# INLINE complement #-}+ complement (BV w n) = BV w $ shiftL 1 (fromEnum w) - 1 - n++ {-# INLINE zeroBits #-}+ zeroBits = BV 0 0++ {-# INLINE bit #-}+ bit i = BV (succ $ toEnum i) (shiftL 1 i)++ {-# INLINE clearBit #-}+ -- We do this more complicated operation rather than call 'clearBit'+ -- because it is undefined for Natural in base < 4.10.0.0+ clearBit bv@(BV w n) i+ | i < 0 || toEnum i >= w+ = bv+ | otherwise+ = let+ !allBits = pred . shiftL 1 $ fromEnum w+ !mask = bit i `xor` allBits+ in BV w $ n .&. mask++ {-# INLINE setBit #-}+ setBit bv@(BV w n) i+ | i < 0 = bv+ | otherwise = BV (max w j) $ n `setBit` i+ where !j = toEnum i + 1++ {-# INLINE testBit #-}+ testBit (BV w n) i = i >= 0 && toEnum i < w && n `testBit` i++ bitSize (BV w _) = fromEnum w++ {-# INLINE bitSizeMaybe #-}+ bitSizeMaybe (BV w _) = Just $ fromEnum w++ {-# INLINE isSigned #-}+ isSigned = const False++ {-# INLINE shiftL #-}+ shiftL (BV w n) k+ | toEnum k > w = BV w 0+ | otherwise = BV w $ shiftL n k .&. pred (shiftL 1 (fromEnum w))++ {-# INLINE shiftR #-}+ shiftR (BV w n) k+ | toEnum k > w = BV w 0+ | otherwise = BV w $ shiftR n k++ {-# INLINE rotateL #-}+ rotateL bv 0 = bv+ rotateL bv@(BV 0 _) _ = bv+ rotateL bv@(BV 1 _) _ = bv+ rotateL bv@(BV w n) k+ | k < 0 = bv+ | j >= w = go . fromEnum $ j `mod` w+ | otherwise = go k+ where+ !j = toEnum k+ go 0 = bv+ go i = BV w $ h + l+ where+ !v = fromEnum w+ !d = v - i+ !m = pred $ shiftL 1 d+ !l = n `shiftR` d+ !h = (n .&. m) `shiftL` i++ {-# INLINE rotateR #-}+ rotateR bv 0 = bv+ rotateR bv@(BV 0 _) _ = bv+ rotateR bv@(BV 1 _) _ = bv+ rotateR bv@(BV w n) k+ | k < 0 = bv+ | j >= w = go . fromEnum $ j `mod` w+ | otherwise = go k+ where+ !j = toEnum k+ go 0 = bv+ go i = BV w $ h + l+ where+ !v = fromEnum w+ !d = v - i+ !m = pred $ shiftL 1 i+ !l = n `shiftR` i+ !h = (n .&. m) `shiftL` d++ {-# INLINE popCount #-}+ popCount = popCount . nat+++{-| @since 0.1.0 -}+instance Eq BitVector where++ {-# INLINE (==) #-}+ (==) (BV w1 m) (BV w2 n) = w1 == w2 && naturalToBigNat m == naturalToBigNat n+ where+ naturalToBigNat (NatS# w ) = wordToBigNat w+ naturalToBigNat (NatJ# bn) = bn+++{-| @since 0.1.0 -}+instance FiniteBits BitVector where++ {-# INLINE finiteBitSize #-}+ finiteBitSize = fromEnum . dim++ {-# INLINE countTrailingZeros #-}+ countTrailingZeros (BV w 0) = fromEnum w+ countTrailingZeros (BV w n) =+ let lastSetBit = I# (integerLog2# (toInteger n)) in max 0 $ fromEnum w - lastSetBit - 1++ {-# INLINE countLeadingZeros #-}+ countLeadingZeros (BV w natVal) = case natVal of+ NatS# 0## -> fromEnum w+ NatS# v -> let iMask = complement zeroBits `xor` (2 ^ w - 1) in countTrailingZeros $ iMask .|. W# v+ NatJ# (BN# arr) ->+ let byteArr = ByteArray arr+ !x = fromEnum w+ (q, r) = x `quotRem` fromEnum bitsInWord+ wMask = complement zeroBits `xor` (2 ^ r - 1) :: Word++ g :: Int -> Int+ g !i =+ let value :: Word+ value = byteArr `indexByteArray` i+ in if i >= q+ then countTrailingZeros $ wMask .|. value+ else+ let !v = countTrailingZeros value+ in if v == fromEnum bitsInWord then v + g (i + 1) else v+ in g 0+++{-| @since 0.1.0 -}+instance Hashable BitVector where++ hash (BV w n) = fromEnum w `hashWithSalt` hash n++ hashWithSalt salt bv = salt `hashWithSalt` hash bv+++{-| @since 0.1.0 -}+instance Monoid BitVector where++ {-# INLINE mappend #-}+ mappend = (<>)++ {-# INLINE mconcat #-}+ mconcat bs = case bs of+ [] -> mempty+ x : xs -> sconcat $ x :| xs++ {-# INLINE mempty #-}+ mempty = BV 0 0+++{-| @since 0.1.0 -}+instance Ord BitVector where++ {-# INLINE compare #-}+ compare lhs rhs = case comparing dim lhs rhs of+ EQ -> comparing nat lhs rhs+ v -> v+++{-| @since 1.2.0 -}+instance Read BitVector where++ {-# INLINABLE readPrec #-}+ readPrec = do+ Punc "[" <- lexP+ w <- step readPrec+ Punc "]" <- lexP+ n <- step readPrec+ -- Check if n exceeds the bit vector's width+ when (n >= 1 `shiftL` fromEnum w) pfail+ pure $ BV w n++ readListPrec = readListPrecDefault+++{-| @since 0.1.0 -}+instance Semigroup BitVector where++ {-# INLINE (<>) #-}+ (<>) (BV x m) (BV y n) = BV (x + y) $ (n `shiftL` fromEnum x) + m++ {-# INLINABLE sconcat #-}+ sconcat xs = BV w' n'+ where+ (w', _, n') = foldl' f (0, 0, 0) xs+ f (bitCountW, bitCountI, natVal) (BV w n) =+ (bitCountW + w, bitCountI + fromEnum w, natVal + (n `shiftL` bitCountI))++ {-# INLINE stimes #-}+ stimes 0 _ = mempty+ stimes e (BV w n) = BV limit $ go start n+ where+ !x = fromEnum w+ !start = fromEnum $ limit - w+ !limit = (toEnum . fromEnum) e * w+ go 0 !acc = acc+ go k !acc = go (k - x) $ (n `shiftL` k) + acc+++{-| @since 0.1.0 -}+instance Show BitVector where++ show (BV w n) = fold ["[", show w, "]", show n]+++{-|+Create a bit vector from a /little-endian/ list of bits.++The following will hold:++> length . takeWhile not === countLeadingZeros . fromBits+> length . takeWhile not . reverse === countTrailingZeros . fromBits++/Time:/ \(\, \mathcal{O} \left( n \right) \)++/Since: 0.1.0/++==== __Examples__++>>> fromBits [True, False, False]+[3]1+-}+{-# INLINABLE fromBits #-}+fromBits :: Foldable f => f Bool -> BitVector+fromBits bs = BV (toEnum n) k+ -- NB: 'setBit' is a GMP function, faster than regular addition.+ where+ (!n, !k) = foldl' go (0, 0) bs+ go :: Bits b => (Int, b) -> Bool -> (Int, b)+ go (!i, !v) b+ | b = (i + 1, v `setBit` i)+ | otherwise = (i + 1, v)+++{-|+Create a /little-endian/ list of bits from a bit vector.++The following will hold:++> length . takeWhile not . toBits === countLeadingZeros+> length . takeWhile not . reverse . toBits === countTrailingZeros++/Time:/ \(\, \mathcal{O} \left( n \right) \)++/Since:/ 0.1.0++==== __Examples__++>>> toBits [4]11+[True, True, False, True]+-}+{-# INLINABLE toBits #-}+toBits :: BitVector -> [Bool]+toBits (BV w n) = go (fromEnum w) []+ where+ go 0 bs = bs+ go i bs = let !j = i - 1 in go j $ n `testBit` j : bs+++{-|+Create a bit vector of non-negative dimension from an integral value.++The integral value will be treated as an /signed/ number and the resulting+bit vector will contain the two's complement bit representation of the number.++The integral value will be interpreted as /little-endian/ so that the least+significant bit of the integral value will be the value of the 0th index of+the resulting bit vector and the most significant bit of the integral value+will be at index @dimension − 1@.++Note that if the bit representation of the integral value exceeds the+supplied dimension, then the most significant bits will be truncated in the+resulting bit vector.++/Time:/ \(\, \mathcal{O} \left( 1 \right) \)++/Since: 0.1.0/++==== __Examples__++>>> fromNumber 8 96+[8]96++>>> fromNumber 8 -96+[8]160++>>> fromNumber 6 96+[6]32+-}+{-# INLINE [1] fromNumber #-}+{-# SPECIALISE fromNumber :: Word -> CBool -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CChar -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CInt -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CIntMax -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CIntPtr -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CLLong -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CLong -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CPtrdiff -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CSChar -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CShort -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CSigAtomic -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CSize -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CUChar -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CUInt -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CUIntMax -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CUIntPtr -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CULLong -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CULong -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CUShort -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> CWchar -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Int -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Int8 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Int16 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Int32 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Int64 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Integer -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Word8 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Word16 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Word32 -> BitVector #-}+{-# SPECIALISE fromNumber :: Word -> Word64 -> BitVector #-}+fromNumber+ :: Integral v+ => Word -- ^ dimension of bit vector+ -> v -- ^ /signed, little-endian/ integral value+ -> BitVector+fromNumber !dimValue !intValue = BV dimValue . intToNat $ mask .&. v+ where+ !v+ | signum int < 0 = negate $ shiftL 1 intBits - int+ | otherwise = int++ !int = toInteger intValue+ !intBits = I# (integerLog2# int)+ !mask = 2 ^ dimValue - 1+++{-# RULES+"fromNumber/Natural" forall w (n :: Natural). fromNumber w n = BV w n+"fromNumber/Word" forall w (v :: Word ). fromNumber w v = BV w (wordToNatural v)+ #-}+++{-|+Two's complement value of a bit vector.++/Time:/ \(\, \mathcal{O} \left( 1 \right) \)++/Since: 0.1.0/++==== __Examples__++>>> toSignedNumber [4]0+0++>>> toSignedNumber [4]3+3++>>> toSignedNumber [4]7+7++>>> toSignedNumber [4]8+-8++>>> toSignedNumber [4]12+-4++>>> toSignedNumber [4]15+-1+-}+{-# INLINE toSignedNumber #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CBool #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CChar #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CInt #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CIntMax #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CIntPtr #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CLLong #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CLong #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CPtrdiff #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CSChar #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CShort #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CSigAtomic #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CSize #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CUChar #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CUInt #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CUIntMax #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CUIntPtr #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CULLong #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CULong #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CUShort #-}+{-# SPECIALISE toSignedNumber :: BitVector -> CWchar #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Int #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Int8 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Int16 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Int32 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Int64 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Integer #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Natural #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Word #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Word8 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Word16 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Word32 #-}+{-# SPECIALISE toSignedNumber :: BitVector -> Word64 #-}+toSignedNumber :: Num a => BitVector -> a+toSignedNumber (BV w n) = fromInteger v+ where+ !i = toInteger n+ !v+ | n `testBit` (fromEnum w - 1) = (+ 1) . negate $ shiftL 1 (fromEnum w) - i+ | otherwise = i+++{-|+Unsigned value of a bit vector.++/Time:/ \(\, \mathcal{O} \left( 1 \right) \)++/Since: 0.1.0/++==== __Examples__++>>> toUnsignedNumber [4]0+0++>>> toUnsignedNumber [4]3+3++>>> toUnsignedNumber [4]7+7++>>> toUnsignedNumber [4]8+8++>>> toUnsignedNumber [4]12+12++>>> toUnsignedNumber [4]15+15+-}+{-# INLINE [1] toUnsignedNumber #-}+toUnsignedNumber :: Num a => BitVector -> a+toUnsignedNumber = fromInteger . toInteger . nat+++{-# RULES+"toUnsignedNumber/Natural" toUnsignedNumber = nat+ #-}+++{-|+Get the dimension of a 'BitVector'. Preferable to 'finiteBitSize' as it+returns a type which cannot represent a non-negative value and a 'BitVector'+must have a non-negative dimension.++/Time:/ \(\, \mathcal{O} \left( 1 \right) \)++/Since: 0.1.0/++==== __Examples__++>>> dimension [2]3+2++>>> dimension [4]12+4+-}+{-# INLINE dimension #-}+dimension :: BitVector -> Word+dimension = dim+++{-|+Determine if /any/ bits are set in the 'BitVector'.+Faster than @(0 ==) . popCount@.++/Time:/ \(\, \mathcal{O} \left( 1 \right) \)++/Since: 0.1.0/++==== __Examples__++>>> isZeroVector [2]3+False++>>> isZeroVector [4]0+True+-}+{-# INLINE isZeroVector #-}+isZeroVector :: BitVector -> Bool+isZeroVector = (0 ==) . nat+++{-|+Get the /inclusive/ range of bits in 'BitVector' as a new 'BitVector'.++If either of the bounds of the subrange exceed the bit vector's dimension,+the resulting subrange will append an infinite number of zeroes to the end+of the bit vector in order to satisfy the subrange request.++/Time:/ \(\, \mathcal{O} \left( 1 \right) \)++/Since: 0.1.0/++==== __Examples__++>>> subRange (0,2) [4]7+[3]7++>>> subRange (1, 3) [4]7+[3]3++>>> subRange (2, 4) [4]7+[3]1++>>> subRange (3, 5) [4]7+[3]0++>>> subRange (10, 20) [4]7+[10]0+-}+{-# INLINE subRange #-}+subRange :: (Word, Word) -> BitVector -> BitVector+subRange (!lower, !upper) (BV _ n)+ | lower > upper = zeroBits+ | otherwise = case toInt lower of+ Nothing -> zeroBits+ Just i ->+ let b = n `shiftR` i+ in case toInt upper of+ Nothing -> let m = toEnum $ maxBound - i + 1 in BV m $ n `shiftR` i+ Just j ->+ let x = j - i+ m+ | x == maxBound = x+ | otherwise = x + 1+ in BV (toEnum m) $ b .&. pred (1 `shiftL` m)+++{-|+Determine the number of /set/ bits in the 'BitVector' up to, /but not including/, index @k@.++To determine the number of /unset/ bits in the 'BitVector`, use @k - rank bv k@.++Uses "broadword programming." Efficient on small 'BitVector's (10^3).++/Time:/ \(\, \mathcal{O} \left( \frac{n}{w} \right) \), where \(w\) is the number of bits in a 'Word'.++/Since: 1.1.0/++==== __Examples__++>>> let bv = fromNumber 128 0 `setBit` 0 `setBit` 65++>>> rank bv 0 -- Count how many ones in the first 0 bits (always returns 0)+0++>>> rank bv 1 -- Count how many ones in the first 1 bits+1++>>> rank bv 2 -- Count how many ones in the first 2 bits+1++>>> rank bv 65 -- Count how many ones in the first 65 bits+1++>>> rank bv 66 -- Count how many ones in the first 66 bits+1++>>> rank bv 128 -- Count how many ones in all 128 bits+2++>>> rank bv 129 -- Out-of-bounds, fails gracefully+2+-}+rank+ :: BitVector+ -> Word -- ^ \(k\), the rank index+ -> Word -- ^ Set bits within the rank index+rank _ 0 = 0 -- There can be no set bits /before/ the 0-th bit+rank (BV 0 _) _ = 0 -- There can be no set bits in a bit-vector of length 0+rank (BV w natVal) k =+ let j = min k w+ in case natVal of+ NatS# v -> wordRank (W# v) j+ NatJ# (BN# v) -> f (ByteArray v) j+ where+ f :: ByteArray -> Word -> Word+ f byteArr x = g x 0+ where+ g :: Word -> Int -> Word+ g !j !i+ | j < bitsInWord = wordRank value j+ | otherwise = let !v = toEnum $ popCount value in v + g (j - bitsInWord) (i + 1)+ where+ value :: Word+ value = byteArr `indexByteArray` i+++{-|+Find the index of the k-th set bit in the 'BitVector'.++To find the index of the k-th /unset/ bit in the 'BitVector`, use @select (complement bv) k@.++Uses "broadword programming." Efficient on small 'BitVector's (10^3).++/Time:/ \(\, \mathcal{O} \left( \frac{n}{w} \right) \), where \(w\) is the number of bits in a 'Word'.++/Since: 1.1.0/++==== __Examples__++>>> let bv = fromNumber 128 0 `setBit` 0 `setBit` 65++>>> select bv 0 -- Find the 0-indexed position of the first one bit+Just 0++>>> select bv 1 -- Find the 0-indexed position of the second one bit+Just 65++>>> select bv 2 -- There is no 3rd set bit, `select` fails+Nothing+-}+select+ :: BitVector+ -> Word -- ^ \(k\), the select index+ -> Maybe Word -- ^ index of the k-th set bit+select (BV 0 _ ) _ = Nothing -- There can be no set bits in a bit-vector of length 0+select (BV w natVal) k = case natVal of+ NatS# v -> let !u = W# v in if toEnum (popCount u) <= k then Nothing else Just $ wordSelect u k+ NatJ# (BN# v) -> f (ByteArray v) k+ where+ f :: ByteArray -> Word -> Maybe Word+ f byteArr x = g x 0+ where+ g :: Word -> Int -> Maybe Word+ g !j !i+ | toEnum i * bitsInWord >= w = Nothing+ | j < ones = Just $ wordSelect value j+ | otherwise = (bitsInWord +) <$> g (j - ones) (i + 1)+ where+ ones = toEnum $ popCount value+ value :: Word+ value = byteArr `indexByteArray` i+++{-|+Number of bits in a 'Word'.++Used for "broadword programming."+-}+{-# INLINE bitsInWord #-}+bitsInWord :: Word+bitsInWord = toEnum $ finiteBitSize (undefined :: Word)+++{-|+Clever use of 'popCount' and masking to get the number of set bits up to,+/but not including/, index "k."+-}+wordRank+ :: Word -- ^ Input 'Word'+ -> Word -- ^ Index k, up to which we count all set bits, k in range [ 0, finiteBitCount - 1 ]+ -> Word -- ^ THe number of bits set within index "k."+wordRank v x = toEnum . popCount $ suffixOnes .&. v where suffixOnes = (1 `shiftL` fromEnum x) - 1+++{-|+Perform binary search with 'popCount' to locate the k-th set bit+-}+wordSelect+ :: Word -- ^ Input 'Word'+ -> Word -- ^ Find the k-th set bit, k in range [ 0, finiteBitCount - 1 ]+ -> Word -- ^ The index of the k-th set bit+wordSelect v = go 0 63+ where+ go :: Word -> Word -> Word -> Word+ go lb ub x+ | lb + 1 == ub+ = if x == 0 && v `testBit` fromEnum lb then lb else ub+ | otherwise+ = let !lowOnes = toEnum . popCount $ lowMask .&. v+ in if lowOnes > x then go lb mb x else go (mb + 1) ub (x - lowOnes)+ where+ mb = ((ub - lb) `div` 2) + lb+ lowMask = makeMask lb mb++ makeMask :: Enum a => a -> Word -> Word+ makeMask i j = wideMask `xor` thinMask+ where+ thinMask = (1 `shiftL` fromEnum i) - 1+ wideMask+ | j == bitsInWord - 1 = maxBound :: Word+ | otherwise = (1 `shiftL` (fromEnum j + 1)) - 1+++{-|+Convert a 'Word' to an 'Int', but only if the 'Word' value is small enough.+-}+toInt :: Word -> Maybe Int+toInt w+ | w > maxInt = Nothing+ | otherwise = Just $ fromEnum w+ where maxInt = toEnum (maxBound :: Int)+++{-|+While similar to the function 'naturalFromInteger' exported from GHC.Natural,+this function does not throw an exception when an negative valued 'Integer'+is supplied and is also compatible with base < 4.10.0.0.+-}+{-# INLINE intToNat #-}+-- {-# NOINLINE intToNat #-}+intToNat :: Integer -> Natural+intToNat = naturalFromInteger
+ src/full/Data/BitVector/LittleEndian/Instances.hs view
@@ -0,0 +1,22 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Exposes the all the instances for 'Data.BitVector.LittleEndian.BitVector'.++-}++{-# Language NoImplicitPrelude #-}++module Data.BitVector.LittleEndian.Instances+ (+ ) where++import Data.BitVector.LittleEndian.Binary ()+import Data.BitVector.LittleEndian.MonoKeyed ()+import Data.BitVector.LittleEndian.MonoTraversable ()+import Data.BitVector.LittleEndian.QuickCheck ()+import Data.BitVector.LittleEndian.TextShow ()
+ src/keys/Data/BitVector/LittleEndian/MonoKeyed.hs view
@@ -0,0 +1,236 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Exposes the following instances for 'BitVector':++ * 'MonoAdjustable'+ * 'MonoFoldableWithKey'+ * 'MonoIndexable'+ * 'MonoKeyed'+ * 'MonoLookup'+ * 'MonoTraversableWithKey'+ * 'MonoZip'+ * 'MonoZipWithKey'++-}++{-# Language BangPatterns #-}+{-# Language TypeFamilies #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Data.BitVector.LittleEndian.MonoKeyed+ (+ ) where++import Data.BitVector.LittleEndian (BitVector)+import Data.BitVector.LittleEndian.Internal hiding (BitVector)+import Data.BitVector.LittleEndian.MonoTraversable ()+import Data.Bits+import Data.Foldable (fold)+import Data.Key+import Data.Maybe (fromMaybe)+import Data.MonoTraversable ()+import Data.MonoTraversable.Keys+++{-| @since 1.0.0 -}+type instance MonoKey BitVector+ = Word+++{-| @since 1.0.0 -}+instance MonoAdjustable BitVector where++ -- | /O(1)/+ {-# INLINE oadjust #-}+ oadjust f k bv@(BV w n)+ | k >= w = bv+ | v == b = bv+ | otherwise = bv `complementBit` i+ where+ !i = fromEnum k+ !v = n `testBit` i+ !b = f v++ -- | /O(1)/+ {-# INLINE oreplace #-}+ oreplace k v bv@(BV w _)+ | k >= w = bv+ | v = bv `setBit` i+ | otherwise = bv `clearBit` i+ where !i = fromEnum k+++{-| @since 1.0.0 -}+instance MonoFoldableWithKey BitVector where++ -- | /O(n)/+ {-# INLINE otoKeyedList #-}+ otoKeyedList (BV w n) =+ let go 0 = []+ go c =+ let !k = w - c+ !v = n `testBit` fromEnum k+ !i = c - 1+ in (k, v) : go i+ in go w++ -- | /O(n)/+ {-# INLINE ofoldMapWithKey #-}+ ofoldMapWithKey f (BV w n) =+ let go 0 = mempty+ go c =+ let !k = w - c+ !v = n `testBit` fromEnum k+ !i = c - 1+ !m = f k v+ in m `mappend` go i+ in go w++ -- | /O(n)/+ {-# INLINE ofoldrWithKey #-}+ ofoldrWithKey f e (BV w n) =+ let go 0 acc = acc+ go c acc =+ let !k = w - c+ !i = c - 1+ !b = n `testBit` fromEnum k+ in f k b $ go i acc+ in go w e++ -- | /O(n)/+ {-# INLINE ofoldlWithKey #-}+ ofoldlWithKey f e (BV w n) = go w e+ where+ go 0 acc = acc+ go c acc =+ let !k = w - c+ !i = c - 1+ !b = n `testBit` fromEnum k+ !a = f acc k b+ in go i a+++{-| @since 1.0.0 -}+instance MonoIndexable BitVector where++ -- | /O(1)/+ {-# INLINE oindex #-}+ oindex bv@(BV w _) i = fromMaybe errorMessage $ i `olookup` bv+ where+ errorMessage = error $ fold+ [ "Data.BitVector.LittleEndian.oindex: "+ , "The index "+ , show i+ , " was greater than or equal to the length of the bit vector "+ , show w+ ]+++{-| @since 1.0.0 -}+instance MonoKeyed BitVector where++ -- | /O(n)/+ {-# INLINE omapWithKey #-}+ omapWithKey f (BV w n) =+ let go 0 acc = acc+ go c acc =+ let !k = w - c+ !i = fromEnum k+ !j = c - 1+ !b = n `testBit` i+ !a+ | f k b = acc `setBit` i+ | otherwise = acc+ in go j a+ in go w $ BV w 0+++{-| @since 1.0.0 -}+instance MonoLookup BitVector where++ -- | /O(1)/+ {-# INLINE olookup #-}+ olookup k (BV w n)+ | k <= w = Nothing+ | otherwise = Just $ n `testBit` fromEnum k+++{-| @since 1.0.0 -}+instance MonoTraversableWithKey BitVector where++ -- | /O(n)/+ {-# INLINE otraverseWithKey #-}+ otraverseWithKey f = fmap fromBits . traverseWithKey (f . toEnum) . toBits+++{-| @since 1.0.0 -}+instance MonoZip BitVector where++ -- | /O(1)/+ {-# INLINE ozipWith #-}+ ozipWith f lhs@(BV w1 p) rhs@(BV w2 q) =+ let !w0 = min w1 w2+ !mask = bit (fromEnum w0) - 1+ bv = BV w0 . (mask .&.)+ not' = nat . complement+ in case (f True True, f True False, f False True, f False False) of+ -- Contradiction (Const False)+ (False, False, False, False) -> bv 0+ -- Logical NOR+ (False, False, False, True ) -> bv $ not' lhs .&. not' rhs+ -- Converse non-implication+ (False, False, True , False) -> bv $ not' lhs .&. q+ -- NOT p+ (False, False, True , True ) -> bv $ not' lhs+ -- Logical non-implication+ (False, True , False, False) -> bv $ p .&. not' rhs+ -- NOT q+ (False, True , False, True ) -> bv $ not' rhs+ -- Logical XOR+ (False, True , True , False) -> bv $ p `xor` q+ -- Logical NAND+ (False, True , True , True ) -> bv $ not' lhs .|. not' rhs+ -- Logical AND+ (True , False, False, False) -> bv $ p .&. q+ -- Logical XNOR+ (True , False, False, True ) -> bv $ (p .&. q) .|. (not' lhs .&. not' rhs)+ -- Const q+ (True , False, True , False) -> bv q+ -- Logical implication+ (True , False, True , True ) -> bv $ not' lhs .|. q+ -- Const p+ (True , True , False, False) -> bv p+ -- Converse implication+ (True , True , False, True ) -> bv $ p .|. not' rhs+ -- Logical OR+ (True , True , True , False) -> bv $ p .|. q+ -- Constant True+ (True , True , True , True ) -> bv $ bit (fromEnum w0) - 1+ -- See the following entry for explanation:+ -- https://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators+ --+ -- cases of f p q+++{-| @since 1.0.0 -}+instance MonoZipWithKey BitVector where++ {-# INLINE ozipWithKey #-}+ ozipWithKey f (BV w1 n) (BV w2 m) =+ let w0 = min w1 w2+ go 0 _ = 0+ go c e =+ let !k = w0 - c+ !i = fromEnum k+ !j = c - 1+ !b = f k (n `testBit` i) (m `testBit` i)+ !a = e `shiftL` 1+ !v = if b then e else 0+ in v + go j a+ in BV w0 $ go w0 1
+ src/libs/Data/BitVector/LittleEndian/Binary.hs view
@@ -0,0 +1,33 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Exposes the 'Binary' instance for 'BitVector'.++-}++{-# Language CPP #-}+{-# Language Safe #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Data.BitVector.LittleEndian.Binary+ (+ ) where++import Control.Applicative (Applicative(liftA2))+import Data.Binary+import Data.BitVector.LittleEndian (BitVector)+import Data.BitVector.LittleEndian.Internal hiding (BitVector)+#if MIN_VERSION_base(4,18,0)+import Prelude hiding (liftA2)+#endif++{- | @since 1.2.0 -}+instance Binary BitVector where++ put (BV w n) = put w <> put n++ get = liftA2 BV get get
+ src/libs/Data/BitVector/LittleEndian/MonoTraversable.hs view
@@ -0,0 +1,296 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Exposes the following instances for 'BitVector':++ * 'MonoFoldable'+ * 'MonoFunctor'+ * 'MonoTraversable'++-}++{-# Language BangPatterns #-}+{-# Language TypeFamilies #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Data.BitVector.LittleEndian.MonoTraversable+ (+ ) where++import Data.BitVector.LittleEndian (BitVector)+import Data.BitVector.LittleEndian.Internal hiding (BitVector)+import Data.Bits+import Data.Foldable+import Data.MonoTraversable+import Data.Monoid ()+++{-| @since 0.1.0 -}+type instance Element BitVector+ = Bool+++{-| @since 0.1.0 -}+instance MonoFoldable BitVector where++ {-# INLINE ofoldMap #-}+ ofoldMap f (BV w n) = go m+ where+ !m = fromEnum w+ go 0 = mempty+ go c =+ let !i = m - c+ !j = c - 1+ !b = n `testBit` i+ in f b `mappend` go j++ {-# INLINE ofoldr #-}+ ofoldr f e (BV w n) =+ let !m = fromEnum w+ go 0 acc = acc+ go c acc =+ let !i = m - c+ !j = c - 1+ !b = n `testBit` i+ in f b $ go j acc+ in go m e++ {-# INLINE ofoldl' #-}+ ofoldl' f e (BV w n) = go m e+ where+ !m = fromEnum w+ go 0 acc = acc+ go c acc =+ let !i = m - c+ !j = c - 1+ !b = n `testBit` i+ !a = f acc b+ in go j a++ {-# INLINE otoList #-}+ otoList = toBits++ -- | /O(1)/+ {-# INLINE oall #-}+ oall _ (BV 0 _) = True+ oall f (BV w n) = case (f False, f True) of+ (False, False) -> False+ (True , True ) -> True+ (False, True ) -> n == bit (fromEnum w) - 1+ (True , False) -> n == 0++ -- | /O(1)/+ {-# INLINE oany #-}+ oany _ (BV 0 _) = False+ oany f (BV w n) = case (f False, f True) of+ (False, False) -> False+ (True , True ) -> True+ (False, True ) -> n > 0+ (True , False) -> n < bit (fromEnum w) - 1++ -- | /O(1)/+ {-# INLINE onull #-}+ onull = (== 0) . dim++ -- | /O(1)/+ {-# INLINE olength #-}+ olength = fromEnum . dim++ -- | /O(1)/+ {-# INLINE olength64 #-}+ olength64 = toEnum . olength++ {-# INLINE otraverse_ #-}+ otraverse_ f (BV w n) = go (fromEnum w)+ where+ go 0 = pure ()+ go c =+ let !j = c - 1+ !a = f (n `testBit` j)+ in a *> go j++ {-# INLINE ofoldlM #-}+ ofoldlM f e (BV w n) = go (fromEnum w) e+ where+ go 0 acc = pure acc+ go c acc =+ let !j = c - 1+ !x = f acc (n `testBit` j)+ in x >>= go j++ {-# INLINE ofoldMap1Ex #-}+ ofoldMap1Ex _ (BV 0 _) = Prelude.error "Data.MonoTraversable.ofoldMap1Ex on an empty BitVector!"+ ofoldMap1Ex f (BV w n) = go 0+ where+ !m = fromEnum w+ go !c+ | c >= m - 1+ = f $ n `testBit` c+ | otherwise+ = let+ !j = c + 1+ !b = n `testBit` c+ in f b <> go j++ -- | /O(1)/+ {-# INLINE ofoldr1Ex #-}+ ofoldr1Ex _ ( BV 0 _) = Prelude.error "Data.MonoTraversable.ofoldr1Ex on an empty BitVector!"+ ofoldr1Ex _ ( BV 1 n) = n > 0+ ofoldr1Ex f bv@(BV w n) =+ -- See the following entry for explanation:+ -- https://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators+ --+ -- cases of f p q+ case (f True True, f True False, f False True, f False False) of+ -- Contradiction (Const False)+ (False, False, False, False) -> False+ -- Logical NOR+ (False, False, False, True) ->+ let !zeros = toEnum $ countLeadingZeros bv+ in if (w - zeros) == 1 || n == 0 then even zeros else odd zeros+ -- Converse non-implication+ -- Only True when of the form <0+1>+ (False, False, True , False) -> n == bit (fromEnum w - 1)+ -- NOT p+ (False, False, True , True ) -> not (n `testBit` 0)+ -- Logical non-implication+ -- Only True when the number of leading ones is even+ (False, True , False, False) -> let !los = countLeadingZeros $ complement bv in odd los+ -- NOT q+ (False, True , False, True ) -> let !v = n `testBit` (fromEnum w - 1) in if even w then not v else v+ -- Logical XOR+ (False, True , True , False) -> odd $ popCount n+ -- Logical NAND+ (False, True, True, True) ->+ let !los = countLeadingZeros $ complement bv+ !x = bit (fromEnum w - 1) - 1+ !y = bit (fromEnum w) - 1+ in if n == x || n == y then odd los else even los+ -- Logical AND+ (True, False, False, False) -> n == bit (fromEnum w) - 1+ -- Logical XNOR+ (True, False, False, True ) -> let !pc = popCount n in if even w then even pc else odd pc+ -- Const q+ (True, False, True , False) -> n `testBit` (fromEnum w - 1)+ -- Logical implication+ -- only False when of the form <1+0>+ (True, False, True , True ) -> let !i = fromEnum w - 1 in n /= bit i - 1+ -- Const p+ (True, True , False, False) -> n `testBit` 0+ -- Converse implication+ (True, True , False, True ) -> even $ countLeadingZeros bv+ -- Logical OR+ (True, True , True , False) -> n > 0+ -- Constant True+ (True, True , True , True ) -> True++ -- | /O(n)/+ {-# INLINE ofoldl1Ex' #-}+ ofoldl1Ex' _ ( BV 0 _) = Prelude.error "Data.MonoTraversable.ofoldl1Ex' on an empty BitVector!"+ ofoldl1Ex' _ ( BV 1 n) = n > 0+ ofoldl1Ex' f bv@(BV w n) =+ -- See the following entry for explanation:+ -- https://en.wikipedia.org/wiki/Truth_table#Truth_table_for_all_binary_logical_operators+ --+ -- cases of f p q+ case (f True True, f True False, f False True, f False False) of+ -- Contradiction (Const False)+ (False, False, False, False) -> False+ -- Logical NOR+ (False, False, False, True) ->+ let !zeros = toEnum $ countTrailingZeros bv+ in if (w - zeros) == 1 || n == 0 then even zeros else odd zeros+ -- Converse non-implication+ (False, False, True , False) -> let !zeros = countTrailingZeros $ complement bv in odd zeros+ -- NOT p+ (False, False, True , True ) -> even w == even n+ -- Logical non-implication+ (False, True , False, False) -> n == 1+ -- NOT q+ (False, True , False, True ) -> not $ n `testBit` (fromEnum w - 1)+ -- Logical XOR+ (False, True , True , False) -> odd $ popCount n+ -- Logical NAND+ (False, True, True, True) ->+ let !zeros = countTrailingZeros $ complement bv+ !x = bit (fromEnum w) - 1+ !y = bit (fromEnum w) - 2+ in if n == x || n == y then odd zeros else even zeros+ -- Logical AND+ (True, False, False, False) -> n == bit (fromEnum w) - 1+ -- Logical XNOR+ (True, False, False, True ) -> let !count = popCount n in if even w then even count else odd count+ -- Const q+ (True, False, True , False) -> n `testBit` (fromEnum w - 1)+ -- Logical implication+ (True, False, True , True ) -> even $ countTrailingZeros bv+ -- Const p+ (True, True , False, False) -> n `testBit` 0+ -- Converse implication+ -- only False when of the form <01+>+ (True, True , False, True ) -> n /= bit (fromEnum w) - 2+ -- Logical OR+ (True, True , True , False) -> n > 0+ -- Constant True+ (True, True , True , True ) -> True++ -- | /O(1)/+ {-# INLINE headEx #-}+ headEx (BV 0 _) = error "Call to Data.MonoFoldable.headEx on an empty BitVector!"+ headEx (BV _ n) = n `testBit` 0++ -- | /O(1)/+ {-# INLINE lastEx #-}+ lastEx (BV 0 _) = error "Call to Data.MonoFoldable.lastEx on an empty BitVector!"+ lastEx (BV w n) = n `testBit` (fromEnum w - 1)++ -- | /O(n)/+ {-# INLINE maximumByEx #-}+ maximumByEx _ (BV 0 _) = error "Call to Data.MonoFoldable.maximumByEx on an empty BitVector!"+ maximumByEx _ (BV 1 n) = n /= 0+ maximumByEx f bv = maximumBy f $ toBits bv++ -- | /O(n)/+ {-# INLINE minimumByEx #-}+ minimumByEx _ (BV 0 _) = error "Call to Data.MonoFoldable.minimumByEx on an empty BitVector!"+ minimumByEx _ (BV 1 n) = n /= 0+ minimumByEx f bv = minimumBy f $ toBits bv++ -- | /O(1)/+ {-# INLINE oelem #-}+ oelem _ (BV 0 _) = False+ oelem True (BV _ n) = n > 0+ oelem False (BV w n) = n < bit (fromEnum w) - 1++ -- | /O(1)/+ {-# INLINE onotElem #-}+ onotElem e = not . oelem e+++{-| @since 0.1.0 -}+instance MonoFunctor BitVector where++ -- | /O(1)/+ {-# INLINE omap #-}+ omap f bv@(BV w n) = case (f False, f True) of+ (False, False) -> BV w 0+ (True , True ) -> BV w $ bit (fromEnum w) - 1+ (False, True ) -> bv+ (True , False) -> let !allOnes = bit (fromEnum w) - 1 in BV w $ n `xor` allOnes+++{-| @since 0.1.0 -}+instance MonoTraversable BitVector where++ -- | /O(n)/+ {-# INLINE otraverse #-}+ otraverse f = fmap fromBits . traverse f . toBits++ -- | /O(n)/+ {-# INLINE omapM #-}+ omapM = otraverse
+ src/libs/Data/BitVector/LittleEndian/QuickCheck.hs view
@@ -0,0 +1,80 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Exposes the 'Arbitrary' and 'CoArbitrary' instances for 'BitVector'.++-}++{-# Language Safe #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Data.BitVector.LittleEndian.QuickCheck+ (+ ) where++import Data.BitVector.LittleEndian (BitVector)+import Data.BitVector.LittleEndian.Internal hiding (BitVector)+import Data.Bits+import Data.Monoid ()+import GHC.Natural+import Test.QuickCheck (Arbitrary(..), CoArbitrary(..), NonNegative(..), choose, suchThat, variant)+++{-| @since 0.1.0 -}+instance Arbitrary BitVector where++ -- Arbitrary instance distribution weighting:+ -- - 2% = (maxBound :: Word)+ -- - 2% = (maxBound :: Word) + 1+ -- - 8% = all bits on+ -- - 8% = all bits off+ -- - 80% = any bit configuration+ arbitrary = do+ -- 1/25 chance of generating the boundary value at which the natural number+ -- must use different Natural constructors: NatS# & NatJ#+ n <- choose (0, 25 :: Word)+ case n of+ 0 -> boundaryValue+ 1 -> allBitsOn+ 2 -> allBitsOn+ 3 -> allBitsOff+ 4 -> allBitsOff+ _ -> anyBitValue+ where+ allBitsOn = genBitVector $ Just True+ allBitsOff = genBitVector $ Just False+ anyBitValue = genBitVector Nothing++ boundaryValue = do+ let numVal = maxBound :: Word+ let dimVal = toEnum $ popCount numVal+ let natVal = wordToNatural numVal+ -- 50/50 change to generate above or below the constructor boundary+ underBoundary <- arbitrary+ let (lowerBound, naturalVal)+ | underBoundary = (dimVal, natVal)+ | otherwise = (dimVal + 1, natVal + 1)+ widthVal <- (getNonNegative <$> arbitrary) `suchThat` (>= lowerBound)+ pure $ BV widthVal naturalVal++ genBitVector spec = do+ dimVal <- getNonNegative <$> arbitrary+ let upperBound = shiftL 1 dimVal+ -- 1/5 chance all bits on or all bits off+ natVal <- case spec of+ Just False -> pure $ naturalFromInteger 0+ Just True -> pure . naturalFromInteger $ upperBound - 1+ Nothing ->+ fmap naturalFromInteger $ (getNonNegative <$> arbitrary) `suchThat` (< upperBound)+ pure $ BV (toEnum dimVal) natVal+++{-| @since 0.1.0 -}+instance CoArbitrary BitVector where++ coarbitrary bv = variant (dimension bv)
+ src/libs/Data/BitVector/LittleEndian/TextShow.hs view
@@ -0,0 +1,29 @@+{-|++Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++Exposes the 'TextShow' instance for 'BitVector'.++-}++{-# Language OverloadedStrings #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Data.BitVector.LittleEndian.TextShow+ (+ ) where++import Data.BitVector.LittleEndian (BitVector)+import Data.BitVector.LittleEndian.Internal hiding (BitVector)+import Data.Foldable (fold)+import TextShow (TextShow(showb))+++{-| @since 1.0.0 -}+instance TextShow BitVector where++ showb (BV w n) = fold ["[", showb w, "]", showb n]
stack.yaml view
@@ -1,6 +1,11 @@-allow-newer: true+compiler:+ ghc-9.2.2 extra-deps:- - mono-traversable-keys-0.1.0+ - base-compat-0.12.1+ - base-compat-batteries-0.12.1 -resolver: lts-13.28+resolver:+ lts-19.5++require-stack-version: ">= 2.7"
test/Data/BitVector/Visual.hs view
@@ -1,40 +1,65 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-| +Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++-}++{-# Language DeriveDataTypeable #-}+{-# Language DeriveGeneric #-}+{-# Language DerivingStrategies #-}+{-# Language FlexibleInstances #-}+{-# Language GeneralizedNewtypeDeriving #-}+{-# Language MultiParamTypeClasses #-}+ module Data.BitVector.Visual- ( VisualBitVector()- , VisualBitVectorSmall()- , HasBitVector(..)- )where+ ( HasBitVector (..)+ , VisualBitVector ()+ , VisualBitVectorSmall ()+ ) where import Control.DeepSeq-import Data.Bits import Data.BitVector.LittleEndian+import Data.Bits import Data.Data-import Data.Functor.Compose-import Data.Functor.Identity-import Data.Hashable-import Data.List.NonEmpty (NonEmpty(..))+import Data.Foldable (fold) import Data.Monoid ()-import Data.MonoTraversable-import Data.Semigroup import GHC.Generics import GHC.Natural-import Test.QuickCheck hiding (generate)+import Test.QuickCheck hiding (generate) import Test.SmallCheck.Series -newtype VisualBitVector = VBV BitVector- deriving (Data, Eq, Ord, Generic, NFData, Typeable)+{-|+New-typed 'BitVector' with special instances of: + * 'Bounded' constraining the *length ≤ 8.*+ * 'Show' providing a more detailed rendering suitable for use with testing frameworks which display counterexamples.+-}+newtype VisualBitVector+ = VBV BitVector+ deriving newtype (Eq, NFData, Ord)+ deriving stock (Data, Generic) -newtype VisualBitVectorSmall = VBVS BitVector- deriving (Data, Eq, Ord, Generic, NFData, Typeable) +{-|+New-typed 'BitVector' with special instances of: + * 'Bounded' constraining the *length ≤ 3.*+ * 'Show' providing a more detailed rendering suitable for use with testing frameworks which display counterexamples.+-}+newtype VisualBitVectorSmall+ = VBVS BitVector+ deriving newtype (Eq, NFData, Ord)+ deriving stock (Data, Generic)+++{-|+Type-class for accessing 'BitVector' from structures.+Intended to facilitate generic testing code operating on either 'BitVector', 'VisualBitVector', or 'VisualBitVectorSmall' types.+-} class HasBitVector a where getBitVector :: a -> BitVector@@ -89,78 +114,63 @@ instance Enum VisualBitVector where toEnum n = go $ n `mod` (bit 9 - 1)- where- go i = VBV $ fromNumber (toEnum dim) num- where- (num, off, dim) = getEnumContext i+ where+ go :: (Integral v, FiniteBits v) => v -> VisualBitVector+ go i = VBV $ fromNumber (toEnum dim) num where (num, _, dim) = getEnumContext i - fromEnum (VBV bv) =- case dim of- 0 -> 0- n -> num + 2^dim - 1- where- num = toUnsignedNumber bv- dim = dimension bv+ fromEnum (VBV bv) = case dim of+ 0 -> 0+ n -> num + 2 ^ n - 1+ where+ num = toUnsignedNumber bv+ dim = dimension bv instance Enum VisualBitVectorSmall where toEnum n = go $ n `mod` (bit 4 - 1)- where- go i = VBVS $ fromNumber (toEnum dim) num- where- (num, off, dim) = getEnumContext i+ where+ go :: (Integral v, FiniteBits v) => v -> VisualBitVectorSmall+ go i = VBVS $ fromNumber (toEnum dim) num where (num, _, dim) = getEnumContext i - fromEnum (VBVS bv) =- case dim of- 0 -> 0- n -> num + 2^dim - 1- where- num = toUnsignedNumber bv- dim = dimension bv+ fromEnum (VBVS bv) = case dim of+ 0 -> 0+ n -> num + 2 ^ n - 1+ where+ num = toUnsignedNumber bv+ dim = dimension bv instance Monad m => Serial m VisualBitVector where series = generate $ const allVBVs- where- allVBVs = toEnum <$> [0 .. fromEnum (maxBound :: VisualBitVector)]+ where allVBVs = toEnum <$> [0 .. fromEnum (maxBound :: VisualBitVector)] instance Monad m => Serial m VisualBitVectorSmall where series = generate $ const allVBVs- where- allVBVs = toEnum <$> [0 .. fromEnum (maxBound :: VisualBitVectorSmall)]+ where allVBVs = toEnum <$> [0 .. fromEnum (maxBound :: VisualBitVectorSmall)] instance Show VisualBitVector where - show (VBV bv) = mconcat- [ "["- , show $ dimension bv- , "]"- , "<"- , foldMap (\b -> if b then "1" else "0") $ toBits bv- , ">"- ]+ show (VBV bv) =+ fold ["[", show $ dimension bv, "]", "<", foldMap (\b -> if b then "1" else "0") $ toBits bv, ">"] + instance Show VisualBitVectorSmall where - show (VBVS bv) = mconcat- [ "["- , show $ dimension bv- , "]"- , "<"- , foldMap (\b -> if b then "1" else "0") $ toBits bv- , ">"- ]+ show (VBVS bv) =+ fold ["[", show $ dimension bv, "]", "<", foldMap (\b -> if b then "1" else "0") $ toBits bv, ">"] +getEnumContext :: (FiniteBits b, Num b) => b -> (b, b, Int) getEnumContext i = (num, off, dim)- where- num = i - off- off = bit dim - 1- dim = logBase2 $ i + 1- logBase2 x = finiteBitSize x - 1 - countLeadingZeros x+ where+ num = i - off+ off = bit dim - 1+ dim = logBase2 $ i + 1+ logBase2 :: FiniteBits b => b -> Int+ logBase2 x = finiteBitSize x - 1 - countLeadingZeros x
test/TestSuite.hs view
@@ -1,49 +1,66 @@-{-# LANGUAGE FlexibleInstances #-}+{-| --- We apply this to suppress the deprecated warning cause by calls to 'bitSize'--- If there is a more fine-grained way to supress this warning without suppressing--- deprecated warnings for the whole module, we should do that instead.+Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++-}++{-# Language FlexibleInstances #-}+{-# Language ImportQualifiedPost #-}++ -- We apply this to suppress the deprecated warning cause by calls to 'bitSize'+ -- If there is a more fine-grained way to suppress this warning without suppressing+ -- deprecated warnings for the whole module, that should be done instead. {-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} -module Main ( main ) where+module Main+ ( main+ ) where -import Control.DeepSeq-import Data.Bits-import Data.BitVector.LittleEndian-import Data.BitVector.Visual-import Data.Foldable-import Data.Functor.Compose-import Data.Functor.Identity-import Data.Hashable-import Data.List.NonEmpty (NonEmpty(..))-import Data.Maybe-import Data.Monoid ()-import Data.MonoTraversable-import Data.MonoTraversable.Keys-import Data.Semigroup-import Operator.Binary.Comparison-import Operator.Binary.Logical-import Operator.Unary.Logical-import Test.Tasty-import Test.Tasty.HUnit-import Test.Tasty.QuickCheck hiding ((.&.), forAll, testProperty)-import qualified Test.Tasty.QuickCheck as QC-import Test.Tasty.SmallCheck hiding ((===), (==>), Property, testProperty)-import qualified Test.Tasty.SmallCheck as SC-import TextShow (TextShow(showb), toString)+import Control.DeepSeq+import Data.BitVector.LittleEndian+import Data.BitVector.LittleEndian.Instances ()+import Data.BitVector.Visual+import Data.Bits+import Data.Foldable+import Data.Functor.Compose+import Data.Functor.Identity+import Data.Hashable+import Data.Maybe+import Data.MonoTraversable+import Data.MonoTraversable.Keys+import Data.Monoid ()+import Data.Semigroup+import GHC.Exts (IsList(..))+import Operator.Binary.Comparison+import Operator.Binary.Logical+import Operator.Unary.Logical+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck hiding (forAll, testProperty, (.&.))+import Test.Tasty.QuickCheck qualified as QC+import Test.Tasty.SmallCheck hiding (Property, testProperty, (==>))+import Test.Tasty.SmallCheck qualified as SC+import TextShow (TextShow(showb), toString) infix 0 -=>-(-=>) :: QC.Testable p => Bool -> p -> Property +(-=>) :: QC.Testable p => Bool -> p -> Property (-=>) p q = not p .||. q +{-|+Complete test suite for the 'BitVector' type.+-} main :: IO () main = defaultMain testSuite testSuite :: TestTree-testSuite = testGroup "BitVector tests"+testSuite = testGroup+ "BitVector tests" [ bitsTests , finiteBitsTests , hashableTests@@ -64,18 +81,19 @@ , textshowProperties , bitVectorProperties , bitVectorRankSelect- , monoFunctorEquivelence- , monoFoldableEquivelence- , monoZipEquivelence+ , monoFunctorEquivalence+ , monoFoldableEquivalence+ , monoZipEquivalence ] bitsTests :: TestTree-bitsTests = testGroup "Properties of Bits"+bitsTests = testGroup+ "Properties of Bits" [ QC.testProperty "∀ i ≥ 0, clearBit zeroBits i === zeroBits" zeroBitsAndClearBit , QC.testProperty "∀ i ≥ 0, setBit zeroBits i === bit i" zeroBitsAndSetBit , QC.testProperty "∀ i ≥ 0, testBit zeroBits i === False" zeroBitsAndTestBit- , testCase " popCount zeroBits === 0" zeroBitsAndPopCount+ , testCase " popCount zeroBits === 0" zeroBitsAndPopCount , QC.testProperty "complement === omap not" complementOmapNot , QC.testProperty "(`setBit` i) === (.|. bit i)" setBitDefinition , QC.testProperty "(`clearBit` i) === (.&. complement (bit i))" clearBitDefinition@@ -89,190 +107,170 @@ , QC.testProperty "(`rotateR` i) . (`rotateL` i) === id" leftRightRotateIdentity , QC.testProperty "(`rotateL` i) . (`rotateR` i) === id" rightLeftRotateIdentity ]- where- zeroBitsAndClearBit :: NonNegative Int -> Property- zeroBitsAndClearBit (NonNegative i) =- clearBit (zeroBits :: BitVector) i === zeroBits+ where+ zeroBitsAndClearBit :: NonNegative Int -> Property+ zeroBitsAndClearBit (NonNegative i) = clearBit (zeroBits :: BitVector) i === zeroBits - zeroBitsAndSetBit :: NonNegative Int -> Property- zeroBitsAndSetBit (NonNegative i) =- setBit (zeroBits :: BitVector) i === bit i+ zeroBitsAndSetBit :: NonNegative Int -> Property+ zeroBitsAndSetBit (NonNegative i) = setBit (zeroBits :: BitVector) i === bit i - zeroBitsAndTestBit :: NonNegative Int -> Property- zeroBitsAndTestBit (NonNegative i) =- testBit (zeroBits :: BitVector) i === False+ zeroBitsAndTestBit :: NonNegative Int -> Property+ zeroBitsAndTestBit (NonNegative i) = testBit (zeroBits :: BitVector) i === False - zeroBitsAndPopCount :: Assertion- zeroBitsAndPopCount =- popCount (zeroBits :: BitVector) @?= 0+ zeroBitsAndPopCount :: Assertion+ zeroBitsAndPopCount = popCount (zeroBits :: BitVector) @?= 0 - complementOmapNot :: BitVector -> Property- complementOmapNot bv =- complement bv === omap not bv+ complementOmapNot :: BitVector -> Property+ complementOmapNot bv = complement bv === omap not bv - setBitDefinition :: NonNegative Int -> BitVector -> Property- setBitDefinition (NonNegative i) bv =- bv `setBit` i === bv .|. bit i+ setBitDefinition :: NonNegative Int -> BitVector -> Property+ setBitDefinition (NonNegative i) bv = bv `setBit` i === bv .|. bit i - clearBitDefinition :: NonNegative Int -> BitVector -> Property- clearBitDefinition (NonNegative i) bv =- i < (fromEnum . dimension) bv -=>- (bv `clearBit` i === bv .&. complement (zed .|. bit i))- where- zed = fromNumber (dimension bv) (0 :: Integer)+ clearBitDefinition :: NonNegative Int -> BitVector -> Property+ clearBitDefinition (NonNegative i) bv =+ i < (fromEnum . dimension) bv -=> (bv `clearBit` i === bv .&. complement (zed .|. bit i))+ where zed = fromNumber (dimension bv) (0 :: Integer) - complementBitDefinition :: NonNegative Int -> BitVector -> Property- complementBitDefinition (NonNegative i) bv =- bv `complementBit` i === bv `xor` bit i+ complementBitDefinition :: NonNegative Int -> BitVector -> Property+ complementBitDefinition (NonNegative i) bv = bv `complementBit` i === bv `xor` bit i - testBitAndSetBit :: NonNegative Int -> BitVector -> Bool- testBitAndSetBit (NonNegative i) =- (`testBit` i) . (`setBit` i)+ testBitAndSetBit :: NonNegative Int -> BitVector -> Bool+ testBitAndSetBit (NonNegative i) = (`testBit` i) . (`setBit` i) - testBitAndClearBit :: NonNegative Int -> BitVector -> Bool- testBitAndClearBit (NonNegative i) =- not . (`testBit` i) . (`clearBit` i)+ testBitAndClearBit :: NonNegative Int -> BitVector -> Bool+ testBitAndClearBit (NonNegative i) = not . (`testBit` i) . (`clearBit` i) - leftShiftPositiveShift :: NonNegative Int -> BitVector -> Property- leftShiftPositiveShift (NonNegative i) bv =- bv `shiftL` i === bv `shift` i- - rightShiftNegativeShift :: NonNegative Int -> BitVector -> Property- rightShiftNegativeShift (NonNegative i) bv =- bv `shiftR` i === bv `shift` (-i)- - leftRotatePositiveRotate :: NonNegative Int -> BitVector -> Property- leftRotatePositiveRotate (NonNegative i) bv =- bv `rotateL` i === bv `rotate` i+ leftShiftPositiveShift :: NonNegative Int -> BitVector -> Property+ leftShiftPositiveShift (NonNegative i) bv = bv `shiftL` i === bv `shift` i - rightRotateNegativeRotate :: NonNegative Int -> BitVector -> Property- rightRotateNegativeRotate (NonNegative i) bv =- bv `rotateR` i === bv `rotate` (-i)- - leftRightRotateIdentity :: NonNegative Int -> BitVector -> Property- leftRightRotateIdentity (NonNegative i) bv =- ((`rotateR` i) . (`rotateL` i)) bv === bv+ rightShiftNegativeShift :: NonNegative Int -> BitVector -> Property+ rightShiftNegativeShift (NonNegative i) bv = bv `shiftR` i === bv `shift` (-i) - rightLeftRotateIdentity :: NonNegative Int -> BitVector -> Property- rightLeftRotateIdentity (NonNegative i) bv =- ((`rotateL` i) . (`rotateR` i)) bv === bv+ leftRotatePositiveRotate :: NonNegative Int -> BitVector -> Property+ leftRotatePositiveRotate (NonNegative i) bv = bv `rotateL` i === bv `rotate` i + rightRotateNegativeRotate :: NonNegative Int -> BitVector -> Property+ rightRotateNegativeRotate (NonNegative i) bv = bv `rotateR` i === bv `rotate` (-i) + leftRightRotateIdentity :: NonNegative Int -> BitVector -> Property+ leftRightRotateIdentity (NonNegative i) bv = ((`rotateR` i) . (`rotateL` i)) bv === bv++ rightLeftRotateIdentity :: NonNegative Int -> BitVector -> Property+ rightLeftRotateIdentity (NonNegative i) bv = ((`rotateL` i) . (`rotateR` i)) bv === bv++ finiteBitsTests :: TestTree-finiteBitsTests = testGroup "Properties of FiniteBits"+finiteBitsTests = testGroup+ "Properties of FiniteBits" [ QC.testProperty "bitSize === finiteBitSize" finiteBitSizeIsBitSize , QC.testProperty "bitSizeMaybe === Just . finiteBitSize" finiteBitSizeIsBitSizeMaybe+ , QC.testProperty "dimension === finiteBitSize" finiteBitSizeIsDimension , QC.testProperty "countLeadingZeros <= finiteBitSize" finiteBitSizeIsGreaterThanLeadingZeros , QC.testProperty "countTrailingZeros <= finiteBitSize" finiteBitSizeIsGreaterThanTrailingZeros , QC.testProperty "length . toBits === finiteBitSize" finiteBitSizeIsBitLength , QC.testProperty "length . takeWhile not === countLeadingZeros . fromBits" countLeadingZeroAndFromBits , QC.testProperty "length . takeWhile not . toBits === countLeadingZeros" countLeadingZeroAndToBits- , QC.testProperty "length . takeWhile not . reverse === countTrailingZeros . fromBits" countTrailingZeroAndFromBits- , QC.testProperty "length . takeWhile not . reverse . toBits === countTrailingZeros" countTrailingZeroAndToBits+ , QC.testProperty+ "length . takeWhile not . reverse === countTrailingZeros . fromBits"+ countTrailingZeroAndFromBits+ , QC.testProperty+ "length . takeWhile not . reverse . toBits === countTrailingZeros"+ countTrailingZeroAndToBits ]- where- finiteBitSizeIsBitSize :: BitVector -> Property- finiteBitSizeIsBitSize bv =- bitSize bv === finiteBitSize bv+ where+ finiteBitSizeIsBitSize :: BitVector -> Property+ finiteBitSizeIsBitSize bv = bitSize bv === finiteBitSize bv - finiteBitSizeIsBitSizeMaybe :: BitVector -> Property- finiteBitSizeIsBitSizeMaybe bv =- bitSizeMaybe bv === (Just . finiteBitSize) bv- - finiteBitSizeIsDimension :: BitVector -> Property- finiteBitSizeIsDimension bv =- (fromEnum . dimension) bv === finiteBitSize bv+ finiteBitSizeIsBitSizeMaybe :: BitVector -> Property+ finiteBitSizeIsBitSizeMaybe bv = bitSizeMaybe bv === (Just . finiteBitSize) bv - finiteBitSizeIsGreaterThanLeadingZeros :: BitVector -> Bool- finiteBitSizeIsGreaterThanLeadingZeros bv =- countLeadingZeros bv <= finiteBitSize bv+ finiteBitSizeIsDimension :: BitVector -> Property+ finiteBitSizeIsDimension bv = (fromEnum . dimension) bv === finiteBitSize bv - finiteBitSizeIsGreaterThanTrailingZeros :: BitVector -> Bool- finiteBitSizeIsGreaterThanTrailingZeros bv =- countTrailingZeros bv <= finiteBitSize bv+ finiteBitSizeIsGreaterThanLeadingZeros :: BitVector -> Bool+ finiteBitSizeIsGreaterThanLeadingZeros bv = countLeadingZeros bv <= finiteBitSize bv - finiteBitSizeIsBitLength :: BitVector -> Property- finiteBitSizeIsBitLength bv =- (length . toBits) bv === finiteBitSize bv+ finiteBitSizeIsGreaterThanTrailingZeros :: BitVector -> Bool+ finiteBitSizeIsGreaterThanTrailingZeros bv = countTrailingZeros bv <= finiteBitSize bv - countLeadingZeroAndFromBits :: [Bool] -> Property- countLeadingZeroAndFromBits bs =- (length . takeWhile not) bs === (countLeadingZeros . fromBits) bs+ finiteBitSizeIsBitLength :: BitVector -> Property+ finiteBitSizeIsBitLength bv = (length . toBits) bv === finiteBitSize bv - countLeadingZeroAndToBits :: BitVector -> Property- countLeadingZeroAndToBits bv =- (length . takeWhile not . toBits) bv === countLeadingZeros bv+ countLeadingZeroAndFromBits :: [Bool] -> Property+ countLeadingZeroAndFromBits bs = (length . takeWhile not) bs === (countLeadingZeros . fromBits) bs - countTrailingZeroAndFromBits :: [Bool] -> Property- countTrailingZeroAndFromBits bs =- (length . takeWhile not . reverse) bs === (countTrailingZeros . fromBits) bs+ countLeadingZeroAndToBits :: BitVector -> Property+ countLeadingZeroAndToBits bv = (length . takeWhile not . toBits) bv === countLeadingZeros bv - countTrailingZeroAndToBits :: BitVector -> Property- countTrailingZeroAndToBits bv =- (length . takeWhile not . reverse . toBits) bv === countTrailingZeros bv+ countTrailingZeroAndFromBits :: [Bool] -> Property+ countTrailingZeroAndFromBits bs =+ (length . takeWhile not . reverse) bs === (countTrailingZeros . fromBits) bs + countTrailingZeroAndToBits :: BitVector -> Property+ countTrailingZeroAndToBits bv =+ (length . takeWhile not . reverse . toBits) bv === countTrailingZeros bv + hashableTests :: TestTree-hashableTests = testGroup "Properties of Hashable"+hashableTests = testGroup+ "Properties of Hashable" [ localOption (QuickCheckTests 10000) $ QC.testProperty "a == b -=> (hashWithSalt a) === (hashWithSalt b)" differentSaltsDifferentHashes ]- where- differentSaltsDifferentHashes :: BitVector -> Int -> Int -> Property- differentSaltsDifferentHashes bv salt1 salt2 =- salt1 /= salt2 -=> hashWithSalt salt1 bv /= hashWithSalt salt2 bv- + where+ differentSaltsDifferentHashes :: BitVector -> Int -> Int -> Property+ differentSaltsDifferentHashes bv salt1 salt2 =+ salt1 /= salt2 -=> hashWithSalt salt1 bv /= hashWithSalt salt2 bv monoAdjustableProperties :: TestTree-monoAdjustableProperties = testGroup "Properites of a MonoAdjustable"+monoAdjustableProperties = testGroup+ "Properties of a MonoAdjustable" [ QC.testProperty "oadjust id k === id" oadjustId , QC.testProperty "oadjust (f . g) k === oadjust f k . oadjust g k" oadjustComposition , QC.testProperty "oadjust f k === omapWithKey (\\i -> if i == k then f else id)" omapConditionality , QC.testProperty "oreplace k v === oreplace k v . oadjust f k" oreplaceNullification , QC.testProperty "oreplace (f v) k === oadjust f k . oreplace k v" oreplaceApplication ]- where- oadjustId :: Word -> BitVector -> Property- oadjustId k bv = - oadjust id k bv === bv+ where+ oadjustId :: Word -> BitVector -> Property+ oadjustId k bv = oadjust id k bv === bv - oadjustComposition :: Blind (Bool -> Bool) -> Blind (Bool -> Bool) -> Word -> BitVector -> Property- oadjustComposition (Blind f) (Blind g) k bv =- oadjust (f . g) k bv === (oadjust f k . oadjust g k) bv+ oadjustComposition :: Blind (Bool -> Bool) -> Blind (Bool -> Bool) -> Word -> BitVector -> Property+ oadjustComposition (Blind f) (Blind g) k bv = oadjust (f . g) k bv === (oadjust f k . oadjust g k) bv - omapConditionality :: Blind (Bool -> Bool) -> Word -> BitVector -> Property- omapConditionality (Blind f) k bv =- oadjust f k bv === omapWithKey (\i -> if i == k then f else id) bv+ omapConditionality :: Blind (Bool -> Bool) -> Word -> BitVector -> Property+ omapConditionality (Blind f) k bv =+ oadjust f k bv === omapWithKey (\i -> if i == k then f else id) bv - oreplaceNullification :: Blind (Bool -> Bool) -> Word -> Bool -> BitVector -> Property- oreplaceNullification (Blind f) k v bv =- oreplace k v bv === (oreplace k v . oadjust f k) bv+ oreplaceNullification :: Blind (Bool -> Bool) -> Word -> Bool -> BitVector -> Property+ oreplaceNullification (Blind f) k v bv = oreplace k v bv === (oreplace k v . oadjust f k) bv - oreplaceApplication :: Blind (Bool -> Bool) -> Word -> Bool -> BitVector -> Property- oreplaceApplication (Blind f) k v bv =- oreplace k (f v) bv === (oadjust f k . oreplace k v) bv+ oreplaceApplication :: Blind (Bool -> Bool) -> Word -> Bool -> BitVector -> Property+ oreplaceApplication (Blind f) k v bv = oreplace k (f v) bv === (oadjust f k . oreplace k v) bv monoFunctorProperties :: TestTree-monoFunctorProperties = testGroup "Properites of a MonoFunctor"+monoFunctorProperties = testGroup+ "Properties of a MonoFunctor" [ QC.testProperty "omap id === id" omapId , QC.testProperty "omap (f . g) === omap f . omap g" omapComposition ]- where- omapId :: BitVector -> Property- omapId bv =- omap id bv === bv+ where+ omapId :: BitVector -> Property+ omapId bv = omap id bv === bv - omapComposition :: Blind (Bool -> Bool) -> Blind (Bool -> Bool) -> BitVector -> Property- omapComposition (Blind f) (Blind g) bv =- omap (f . g) bv === (omap f . omap g) bv+ omapComposition :: Blind (Bool -> Bool) -> Blind (Bool -> Bool) -> BitVector -> Property+ omapComposition (Blind f) (Blind g) bv = omap (f . g) bv === (omap f . omap g) bv monoFoldableProperties :: TestTree-monoFoldableProperties = testGroup "Properties of MonoFoldable"+monoFoldableProperties = testGroup+ "Properties of MonoFoldable" [ QC.testProperty "ofoldr f z t === appEndo (ofoldMap (Endo . f) t ) z" testFoldrFoldMap- , QC.testProperty "ofoldl' f z t === appEndo (getDual (ofoldMap (Dual . Endo . flip f) t)) z" testFoldlFoldMap+ , QC.testProperty+ "ofoldl' f z t === appEndo (getDual (ofoldMap (Dual . Endo . flip f) t)) z"+ testFoldlFoldMap , QC.testProperty "ofoldr f z === ofoldr f z . otoList" testFoldr , QC.testProperty "ofoldl' f z === ofoldl' f z . otoList" testFoldl , QC.testProperty "ofoldr1Ex f === foldr1 f . otoList" testFoldr1@@ -285,66 +283,54 @@ , QC.testProperty "lastEx === getLast . ofoldMap1Ex Last" testTail , QC.testProperty "oelem e /== onotElem e" testInclusionConsistency ]- where- testFoldrFoldMap :: Blind (Bool -> Word -> Word) -> Word -> BitVector -> Property- testFoldrFoldMap (Blind f) z bv =- ofoldr f z bv === appEndo (ofoldMap (Endo . f) bv) z+ where+ testFoldrFoldMap :: Blind (Bool -> Word -> Word) -> Word -> BitVector -> Property+ testFoldrFoldMap (Blind f) z bv = ofoldr f z bv === appEndo (ofoldMap (Endo . f) bv) z - testFoldlFoldMap :: Blind (Word -> Bool -> Word) -> Word -> BitVector -> Property- testFoldlFoldMap (Blind f) z bv =- ofoldl' f z bv === appEndo (getDual (ofoldMap (Dual . Endo . flip f) bv)) z+ testFoldlFoldMap :: Blind (Word -> Bool -> Word) -> Word -> BitVector -> Property+ testFoldlFoldMap (Blind f) z bv =+ ofoldl' f z bv === appEndo (getDual (ofoldMap (Dual . Endo . flip f) bv)) z - testFoldr :: Blind (Bool -> Word -> Word) -> Word -> BitVector -> Property- testFoldr (Blind f) z bv =- ofoldr f z bv === (ofoldr f z . otoList) bv+ testFoldr :: Blind (Bool -> Word -> Word) -> Word -> BitVector -> Property+ testFoldr (Blind f) z bv = ofoldr f z bv === (ofoldr f z . otoList) bv - testFoldl :: Blind (Word -> Bool -> Word) -> Word -> BitVector -> Property- testFoldl (Blind f) z bv =- ofoldl' f z bv === (ofoldl' f z . otoList) bv+ testFoldl :: Blind (Word -> Bool -> Word) -> Word -> BitVector -> Property+ testFoldl (Blind f) z bv = ofoldl' f z bv === (ofoldl' f z . otoList) bv --- testFoldr1 :: Blind (Bool -> Bool -> Bool) -> BitVector -> Property- testFoldr1 :: BinaryLogicalOperator -> BitVector -> Property--- testFoldr1 (Blind f) bv =- testFoldr1 x bv =- (not . onull) bv -=> ofoldr1Ex f bv === (foldr1 f . otoList) bv- where- f = getBinaryLogicalOperator x+ -- testFoldr1 :: Blind (Bool -> Bool -> Bool) -> BitVector -> Property+ testFoldr1 :: BinaryLogicalOperator -> BitVector -> Property+ -- testFoldr1 (Blind f) bv =+ testFoldr1 x bv = (not . onull) bv -=> ofoldr1Ex f bv === (foldr1 f . otoList) bv+ where f = getBinaryLogicalOperator x - testFoldl1 :: Blind (Bool -> Bool -> Bool) -> BitVector -> Property- testFoldl1 (Blind f) bv =- (not . onull) bv -=> ofoldl1Ex' f bv === (foldl1 f . otoList) bv+ testFoldl1 :: Blind (Bool -> Bool -> Bool) -> BitVector -> Property+ testFoldl1 (Blind f) bv = (not . onull) bv -=> ofoldl1Ex' f bv === (foldl1 f . otoList) bv - testAll :: Blind (Bool -> Bool) -> BitVector -> Property- testAll (Blind f) bv =- oall f bv === (getAll . ofoldMap (All . f)) bv+ testAll :: Blind (Bool -> Bool) -> BitVector -> Property+ testAll (Blind f) bv = oall f bv === (getAll . ofoldMap (All . f)) bv - testAny :: Blind (Bool -> Bool) -> BitVector -> Property- testAny (Blind f) bv =- oany f bv === (getAny . ofoldMap (Any . f)) bv+ testAny :: Blind (Bool -> Bool) -> BitVector -> Property+ testAny (Blind f) bv = oany f bv === (getAny . ofoldMap (Any . f)) bv - testLength :: BitVector -> Property- testLength bv =- olength bv === (length . otoList) bv+ testLength :: BitVector -> Property+ testLength bv = olength bv === (length . otoList) bv - testNull :: BitVector -> Property- testNull bv =- onull bv === ((0 ==) . olength) bv+ testNull :: BitVector -> Property+ testNull bv = onull bv === ((0 ==) . olength) bv - testHead :: BitVector -> Property- testHead bv =- (not . onull) bv -=> headEx bv === (getFirst . ofoldMap1Ex First) bv+ testHead :: BitVector -> Property+ testHead bv = (not . onull) bv -=> headEx bv === (getFirst . ofoldMap1Ex First) bv - testTail :: BitVector -> Property- testTail bv =- (not . onull) bv -=> lastEx bv === (getLast . ofoldMap1Ex Last) bv+ testTail :: BitVector -> Property+ testTail bv = (not . onull) bv -=> lastEx bv === (getLast . ofoldMap1Ex Last) bv - testInclusionConsistency :: (Bool, BitVector) -> Property- testInclusionConsistency (e, bv) =- oelem e bv === (not . onotElem e) bv+ testInclusionConsistency :: (Bool, BitVector) -> Property+ testInclusionConsistency (e, bv) = oelem e bv === (not . onotElem e) bv monoFoldableWithKeyProperties :: TestTree-monoFoldableWithKeyProperties = testGroup "Properties of MonoFoldableWithKey"+monoFoldableWithKeyProperties = testGroup+ "Properties of MonoFoldableWithKey" [ QC.testProperty "otoKeyedList === zip [0..] . otoList" testNaturalKeyedList , QC.testProperty "ofoldMapWithKey (const f) === ofoldMap f" testConstantFoldMap , QC.testProperty "ofoldrWithKey (const f) === ofoldr f" testConstantFoldr@@ -353,229 +339,229 @@ , QC.testProperty "ofoldrWithKey f === foldr (uncurry f) . otoKeyedList" testUncurriedFoldr , QC.testProperty "ofoldlWithKey f === foldl (uncurry . f) . otoKeyedList" testUncurriedFoldl ]- where- testNaturalKeyedList :: BitVector -> Property- testNaturalKeyedList bv =- otoKeyedList bv === (zip [0..] . otoList) bv+ where+ testNaturalKeyedList :: BitVector -> Property+ testNaturalKeyedList bv = otoKeyedList bv === (zip [0 ..] . otoList) bv - testConstantFoldMap :: Blind (Bool -> [Word]) -> BitVector -> Property- testConstantFoldMap (Blind f) bv =- ofoldMapWithKey (const f) bv === ofoldMap f bv+ testConstantFoldMap :: Blind (Bool -> [Word]) -> BitVector -> Property+ testConstantFoldMap (Blind f) bv = ofoldMapWithKey (const f) bv === ofoldMap f bv - testConstantFoldr :: Blind (Bool -> Word -> Word) -> Word -> BitVector -> Property- testConstantFoldr (Blind f) e bv =- ofoldrWithKey (const f) e bv === ofoldr f e bv+ testConstantFoldr :: Blind (Bool -> Word -> Word) -> Word -> BitVector -> Property+ testConstantFoldr (Blind f) e bv = ofoldrWithKey (const f) e bv === ofoldr f e bv - testConstantFoldl :: Blind (Word -> Bool -> Word) -> Word -> BitVector -> Property- testConstantFoldl (Blind f) e bv =- ofoldlWithKey (const . f) e bv === ofoldl' f e bv+ testConstantFoldl :: Blind (Word -> Bool -> Word) -> Word -> BitVector -> Property+ testConstantFoldl (Blind f) e bv = ofoldlWithKey (const . f) e bv === ofoldl' f e bv - testUncurriedFoldMap :: Blind (Word -> Bool -> [Word]) -> BitVector -> Property- testUncurriedFoldMap (Blind f) bv =- ofoldMapWithKey f bv === (foldMap (uncurry f) . otoKeyedList) bv+ testUncurriedFoldMap :: Blind (Word -> Bool -> [Word]) -> BitVector -> Property+ testUncurriedFoldMap (Blind f) bv = ofoldMapWithKey f bv === (foldMap (uncurry f) . otoKeyedList) bv - testUncurriedFoldr :: Blind (Word -> Bool -> Word -> Word) -> Word -> BitVector -> Property- testUncurriedFoldr (Blind f) e bv =- ofoldrWithKey f e bv === (foldr (uncurry f) e . otoKeyedList) bv+ testUncurriedFoldr :: Blind (Word -> Bool -> Word -> Word) -> Word -> BitVector -> Property+ testUncurriedFoldr (Blind f) e bv = ofoldrWithKey f e bv === (foldr (uncurry f) e . otoKeyedList) bv - testUncurriedFoldl :: Blind (Word -> Word -> Bool -> Word) -> Word -> BitVector -> Property- testUncurriedFoldl (Blind f) e bv =- ofoldlWithKey f e bv === (foldl (uncurry . f) e . otoKeyedList) bv+ testUncurriedFoldl :: Blind (Word -> Word -> Bool -> Word) -> Word -> BitVector -> Property+ testUncurriedFoldl (Blind f) e bv =+ ofoldlWithKey f e bv === (foldl (uncurry . f) e . otoKeyedList) bv monoKeyedProperties :: TestTree-monoKeyedProperties = testGroup "Properites of a MonoKeyed"+monoKeyedProperties = testGroup+ "Properties of a MonoKeyed" [ QC.testProperty "omapWithKey (const id) === id" omapId , QC.testProperty "omapWithKey (\\k -> f k . g k) === omapWithKey f . omapWithKey g" omapComposition ]- where- omapId :: BitVector -> Property- omapId bv =- omapWithKey (const id) bv === bv+ where+ omapId :: BitVector -> Property+ omapId bv = omapWithKey (const id) bv === bv - omapComposition :: Blind (Word -> Bool -> Bool) -> Blind (Word -> Bool -> Bool) -> BitVector -> Property- omapComposition (Blind f) (Blind g) bv =- omapWithKey (\k -> f k . g k) bv === (omapWithKey f . omapWithKey g) bv+ omapComposition+ :: Blind (Word -> Bool -> Bool) -> Blind (Word -> Bool -> Bool) -> BitVector -> Property+ omapComposition (Blind f) (Blind g) bv =+ omapWithKey (\k -> f k . g k) bv === (omapWithKey f . omapWithKey g) bv monoTraversableProperties :: TestTree-monoTraversableProperties = testGroup "Properties of MonoTraversable"+monoTraversableProperties = testGroup+ "Properties of MonoTraversable" [ QC.testProperty "t . otraverse f === otraverse (t . f)" testNaturality , QC.testProperty "otraverse Identity === Identity" testIdentity- , QC.testProperty "otraverse (Compose . fmap g . f) === Compose . fmap (otraverse g) . otraverse f" testComposition+ , QC.testProperty+ "otraverse (Compose . fmap g . f) === Compose . fmap (otraverse g) . otraverse f"+ testComposition , QC.testProperty "otraverse === omapM" testDefinitionEquality ]- where- testNaturality :: Blind (Bool -> [Bool]) -> BitVector -> Property- testNaturality (Blind f) bv =- (headMay . otraverse f) bv === otraverse (headMay . f) bv+ where+ testNaturality :: Blind (Bool -> [Bool]) -> BitVector -> Property+ testNaturality (Blind f) bv = (headMay . otraverse f) bv === otraverse (headMay . f) bv - testIdentity :: BitVector -> Property- testIdentity bv =- otraverse Identity bv === Identity bv+ testIdentity :: BitVector -> Property+ testIdentity bv = otraverse Identity bv === Identity bv - testComposition :: Blind (Bool -> Either Word Bool) -> Blind (Bool -> Maybe Bool) -> BitVector -> Property- testComposition (Blind f) (Blind g) bv =- otraverse (Compose . fmap g . f) bv === (Compose . fmap (otraverse g) . otraverse f) bv+ testComposition+ :: Blind (Bool -> Either Word Bool) -> Blind (Bool -> Maybe Bool) -> BitVector -> Property+ testComposition (Blind f) (Blind g) bv =+ otraverse (Compose . fmap g . f) bv === (Compose . fmap (otraverse g) . otraverse f) bv - testDefinitionEquality :: Blind (Bool -> Maybe Bool) -> BitVector -> Property- testDefinitionEquality (Blind f) bv =- otraverse f bv === omapM f bv+ testDefinitionEquality :: Blind (Bool -> Maybe Bool) -> BitVector -> Property+ testDefinitionEquality (Blind f) bv = otraverse f bv === omapM f bv monoTraversableWithKeyProperties :: TestTree-monoTraversableWithKeyProperties = testGroup "Properties of MonoTraversableWithKey"+monoTraversableWithKeyProperties = testGroup+ "Properties of MonoTraversableWithKey" [ QC.testProperty "t . otraverseWithKey f === otraverseWithKey (\\k -> t . f k)" testNaturality , QC.testProperty "otraverseWithKey (const Identity) === Identity" testIdentity- , QC.testProperty "otraverseWithKey (\\k -> Compose . fmap (g k) . f k) === Compose . fmap (otraverseWithKey g) . otraverseWithKey f" testComposition+ , QC.testProperty+ "otraverseWithKey (\\k -> Compose . fmap (g k) . f k) === Compose . fmap (otraverseWithKey g) . otraverseWithKey f"+ testComposition , QC.testProperty "otraverseWithKey === omapWithKeyM" testDefinitionEquality ]- where- testNaturality :: Blind (Word -> Bool -> [Bool]) -> BitVector -> Property- testNaturality (Blind f) bv =- (headMay . otraverseWithKey f) bv === otraverseWithKey (\k -> headMay . f k) bv+ where+ testNaturality :: Blind (Word -> Bool -> [Bool]) -> BitVector -> Property+ testNaturality (Blind f) bv =+ (headMay . otraverseWithKey f) bv === otraverseWithKey (\k -> headMay . f k) bv - testIdentity :: BitVector -> Property- testIdentity bv =- otraverseWithKey (const Identity) bv === Identity bv+ testIdentity :: BitVector -> Property+ testIdentity bv = otraverseWithKey (const Identity) bv === Identity bv - testComposition :: Blind (Word -> Bool -> Either Word Bool) -> Blind (Word -> Bool -> Maybe Bool) -> BitVector -> Property- testComposition (Blind f) (Blind g) bv =- otraverseWithKey (\k -> Compose . fmap (g k) . f k) bv === (Compose . fmap (otraverseWithKey g) . otraverseWithKey f) bv+ testComposition+ :: Blind (Word -> Bool -> Either Word Bool)+ -> Blind (Word -> Bool -> Maybe Bool)+ -> BitVector+ -> Property+ testComposition (Blind f) (Blind g) bv = otraverseWithKey (\k -> Compose . fmap (g k) . f k) bv+ === (Compose . fmap (otraverseWithKey g) . otraverseWithKey f) bv - testDefinitionEquality :: Blind (Word -> Bool -> Maybe Bool) -> BitVector -> Property- testDefinitionEquality (Blind f) bv =- otraverseWithKey f bv === omapWithKeyM f bv+ testDefinitionEquality :: Blind (Word -> Bool -> Maybe Bool) -> BitVector -> Property+ testDefinitionEquality (Blind f) bv = otraverseWithKey f bv === omapWithKeyM f bv monoZipProperties :: TestTree-monoZipProperties = testGroup "Properites of a MonoZip"- [ QC.testProperty "ozipWith const u u === ozipWith (flip const) u u === u" ozipWithConst+monoZipProperties = testGroup+ "Properties of a MonoZip"+ [ QC.testProperty "ozipWith const u u === ozipWith (const id) u u === u" ozipWithConst , QC.testProperty "ozipWith (flip f) x y === ozipWith f y x" ozipWithTransposition- , QC.testProperty "ozipWith (\\a b -> f (g a) (h b)) x y === ozipWith f (omap g x) (omap h y)" ozipWithComposition+ , QC.testProperty+ "ozipWith (\\a b -> f (g a) (h b)) x y === ozipWith f (omap g x) (omap h y)"+ ozipWithComposition ]- where- ozipWithConst :: BitVector -> Property- ozipWithConst u =- ozipWith const u u === u .&&. ozipWith (flip const) u u === u+ where+ ozipWithConst :: BitVector -> Property+ ozipWithConst u = ozipWith const u u === u .&&. ozipWith (const id) u u === u - ozipWithTransposition :: Blind (Bool -> Bool -> Bool) -> BitVector -> BitVector -> Property- ozipWithTransposition (Blind f) x y =- ozipWith (flip f) x y === ozipWith f y x+ ozipWithTransposition :: Blind (Bool -> Bool -> Bool) -> BitVector -> BitVector -> Property+ ozipWithTransposition (Blind f) x y = ozipWith (flip f) x y === ozipWith f y x - ozipWithComposition- :: Blind (Bool -> Bool -> Bool)- -> Blind (Bool -> Bool)- -> Blind (Bool -> Bool) -> BitVector -> BitVector -> Property- ozipWithComposition (Blind f) (Blind g) (Blind h) x y =- ozipWith (\a b -> f (g a) (h b)) x y === ozipWith f (omap g x) (omap h y)+ ozipWithComposition+ :: Blind (Bool -> Bool -> Bool)+ -> Blind (Bool -> Bool)+ -> Blind (Bool -> Bool)+ -> BitVector+ -> BitVector+ -> Property+ ozipWithComposition (Blind f) (Blind g) (Blind h) x y =+ ozipWith (\a b -> f (g a) (h b)) x y === ozipWith f (omap g x) (omap h y) monoZipWithKeyProperties :: TestTree-monoZipWithKeyProperties = testGroup "Properites of a MonoZipWithKey"- [ QC.testProperty "ozipWithKey (const f) === ozipWith f" ozipWithKeyConst- ]- where- ozipWithKeyConst :: Blind (Bool -> Bool -> Bool) -> BitVector -> BitVector -> Property- ozipWithKeyConst (Blind f) x y =- ozipWithKey (const f) x y === ozipWith f x y+monoZipWithKeyProperties = testGroup+ "Properties of a MonoZipWithKey"+ [QC.testProperty "ozipWithKey (const f) === ozipWith f" ozipWithKeyConst]+ where+ ozipWithKeyConst :: Blind (Bool -> Bool -> Bool) -> BitVector -> BitVector -> Property+ ozipWithKeyConst (Blind f) x y = ozipWithKey (const f) x y === ozipWith f x y +{- HLINT ignore monoidProperties "Monoid law, left identity" -}+{- HLINT ignore monoidProperties "Monoid law, right identity" -}+{- HLINT ignore monoidProperties "Use fold" -} monoidProperties :: TestTree-monoidProperties = testGroup "Properties of a Monoid"- [ QC.testProperty "left identity" leftIdentity+monoidProperties = testGroup+ "Properties of a Monoid"+ [ QC.testProperty "left identity" leftIdentity , QC.testProperty "right identity" rightIdentity- , QC.testProperty "mempty is associative" operationAssocativity+ , QC.testProperty "mempty is associative" operationAssociativity , QC.testProperty "mconcat === foldr (<>) mempty" foldableApplication ]- where- leftIdentity :: BitVector -> Property- leftIdentity a =- mempty `mappend` a === a+ where+ leftIdentity :: BitVector -> Property+ leftIdentity a = mempty `mappend` a === a - rightIdentity :: BitVector -> Property- rightIdentity a =- a `mappend` mempty === a+ rightIdentity :: BitVector -> Property+ rightIdentity a = a `mappend` mempty === a - operationAssocativity :: BitVector -> BitVector -> BitVector -> Property- operationAssocativity a b c =- a `mappend` (b `mappend` c) === (a `mappend` b) `mappend` c+ operationAssociativity :: BitVector -> BitVector -> BitVector -> Property+ operationAssociativity a b c = a `mappend` (b `mappend` c) === (a `mappend` b) `mappend` c - foldableApplication :: [BitVector] -> Property- foldableApplication bvs = - mconcat bvs === foldr mappend mempty bvs+ foldableApplication :: [BitVector] -> Property+ foldableApplication bvs = mconcat bvs === foldr mappend mempty bvs normalFormDataProperties :: TestTree-normalFormDataProperties = testGroup "Properties of NFData"- [ QC.testProperty "rnf result is finite" finiteReduction- ]- where- finiteReduction :: BitVector -> Property- finiteReduction bv =- rnf bv === ()+normalFormDataProperties = testGroup+ "Properties of NFData"+ [QC.testProperty "rnf result is finite" finiteReduction]+ where+ finiteReduction :: BitVector -> Property+ finiteReduction bv = rnf bv === () orderingProperties :: TestTree-orderingProperties = testGroup "Properties of an Ordering"- [ QC.testProperty "ordering preserves symetry" symetry+orderingProperties = testGroup+ "Properties of an Ordering"+ [ QC.testProperty "ordering preserves symmetry" symmetry , QC.testProperty "ordering is transitive (total)" transitivity ]- where- symetry :: BitVector -> BitVector -> Bool- symetry lhs rhs =- case (lhs `compare` rhs, rhs `compare` lhs) of- (EQ, EQ) -> True- (GT, LT) -> True- (LT, GT) -> True- _ -> False+ where+ symmetry :: BitVector -> BitVector -> Bool+ symmetry lhs rhs = case (lhs `compare` rhs, rhs `compare` lhs) of+ (EQ, EQ) -> True+ (GT, LT) -> True+ (LT, GT) -> True+ _ -> False - transitivity :: BitVector -> BitVector -> BitVector -> Property- transitivity a b c = caseOne .||. caseTwo- where- caseOne = (a <= b && b <= c) -=> a <= c- caseTwo = (a >= b && b >= c) -=> a >= c+ transitivity :: BitVector -> BitVector -> BitVector -> Property+ transitivity a b c = caseOne .||. caseTwo+ where+ caseOne = (a <= b && b <= c) -=> a <= c+ caseTwo = (a >= b && b >= c) -=> a >= c semigroupProperties :: TestTree-semigroupProperties = testGroup "Properties of a Semigroup"- [ localOption (QuickCheckTests 10000)- $ QC.testProperty "(<>) is associative" operationAssocativity+semigroupProperties = testGroup+ "Properties of a Semigroup"+ [ localOption (QuickCheckTests 10000) $ QC.testProperty "(<>) is associative" operationAssociativity , QC.testProperty "sconcat === foldr1 (<>)" foldableApplication , QC.testProperty "stimes n === mconcat . replicate n" repeatedApplication ]- where- operationAssocativity :: BitVector -> BitVector -> BitVector -> Property- operationAssocativity a b c =- a <> (b <> c) === (a <> b) <> c+ where+ operationAssociativity :: BitVector -> BitVector -> BitVector -> Property+ operationAssociativity a b c = a <> (b <> c) === (a <> b) <> c - foldableApplication :: NonEmptyList BitVector -> Property- foldableApplication nel =- sconcat bvs === foldr1 mappend bvs- where- -- We do this because there is currently no Arbitrary inctance for NonEmpty- bvs = let x:xs = getNonEmpty nel- in x:|xs+ foldableApplication :: NonEmptyList BitVector -> Property+ foldableApplication manyBVs = sconcat bvs === foldr1 mappend bvs+ where+ -- We do this because there is currently no Arbitrary instance for NonEmpty+ bvs = fromList $ getNonEmpty manyBVs - repeatedApplication :: NonNegative Int -> BitVector -> Property- repeatedApplication (NonNegative i) bv =- stimes i bv === (mconcat . replicate i) bv+ repeatedApplication :: NonNegative Int -> BitVector -> Property+ repeatedApplication (NonNegative i) bv = stimes i bv === (mconcat . replicate i) bv showProperties :: TestTree-showProperties = testGroup "Properties of Show"+showProperties = testGroup+ "Properties of Show" [ QC.testProperty "show result is finite" finiteString , QC.testProperty "show result is non-null" nonNullString ]- where- finiteString :: BitVector -> Property- finiteString bv =- show bv === show bv - - nonNullString :: BitVector -> Bool- nonNullString =- not . null . show+ where+ finiteString :: BitVector -> Property+ finiteString bv = show bv === show bv + nonNullString :: BitVector -> Bool+ nonNullString = not . null . show+++ textshowProperties :: TestTree textshowProperties = testGroup "Properties of TextShow" [ QC.testProperty "textshow and show result agree" textshowCoherence@@ -586,224 +572,208 @@ (toString . showb $ bv) === show bv - bitVectorProperties :: TestTree-bitVectorProperties = testGroup "BitVector properties"+bitVectorProperties = testGroup+ "BitVector properties" [ QC.testProperty "otoList === toBits" otoListTest , QC.testProperty "dimension === length . toBits" dimensionAndToBits , QC.testProperty "dimension === finiteBitSize" dimensionAndFiniteBitSize , QC.testProperty "fromBits . toBits === id" toBitsFromBits- , testCase "isZeroVector zeroBits" zeroBitsIsZeroVector+ , testCase "isZeroVector zeroBits" zeroBitsIsZeroVector , QC.testProperty "isZeroVector === (0 ==) . popCount" popCountAndZeroVector , QC.testProperty "isZeroVector === all not . toBits" zeroVectorAndAllBitsOff , QC.testProperty "(0 ==) . toUnsignedNumber -=> isZeroVector" toUnsignedNumImpliesZeroVector , QC.testProperty "toSignedNumber . fromNumber === id" bitVectorUnsignedNumIdentity , QC.testProperty "isSigned == const False" noSignBitVector -- For an unknown reason, this test case causes GHC to panic!--- , QC.testProperty "i > j -=> subRange (i,j) === const zeroBits" badSubRangeEmptyResult+ , QC.testProperty "i > j -=> subRange (i,j) === const zeroBits" badSubRangeEmptyResult , QC.testProperty "i <= j -=> dimension . subRange (i,j) === const (j - i + 1)" subRangeFixedDimension ]- where- otoListTest :: BitVector -> Property- otoListTest bv =- otoList bv === toBits bv+ where+ otoListTest :: BitVector -> Property+ otoListTest bv = otoList bv === toBits bv - dimensionAndToBits :: BitVector -> Property- dimensionAndToBits bv =- (fromEnum . dimension) bv === (length . toBits) bv+ dimensionAndToBits :: BitVector -> Property+ dimensionAndToBits bv = (fromEnum . dimension) bv === (length . toBits) bv - dimensionAndFiniteBitSize :: BitVector -> Property- dimensionAndFiniteBitSize bv =- (fromEnum . dimension) bv === finiteBitSize bv+ dimensionAndFiniteBitSize :: BitVector -> Property+ dimensionAndFiniteBitSize bv = (fromEnum . dimension) bv === finiteBitSize bv - toBitsFromBits :: BitVector -> Property- toBitsFromBits bv =- (fromBits . toBits) bv === bv+ toBitsFromBits :: BitVector -> Property+ toBitsFromBits bv = (fromBits . toBits) bv === bv - zeroBitsIsZeroVector :: Assertion- zeroBitsIsZeroVector =- assertBool "zeroBits is not a 'zero vector'" $ isZeroVector zeroBits+ zeroBitsIsZeroVector :: Assertion+ zeroBitsIsZeroVector = assertBool "zeroBits is not a 'zero vector'" $ isZeroVector zeroBits - popCountAndZeroVector :: BitVector -> Property- popCountAndZeroVector bv =- isZeroVector bv === ((0 ==) . popCount) bv+ popCountAndZeroVector :: BitVector -> Property+ popCountAndZeroVector bv = isZeroVector bv === ((0 ==) . popCount) bv - zeroVectorAndAllBitsOff :: BitVector -> Property- zeroVectorAndAllBitsOff bv =- isZeroVector bv === (all not . toBits) bv+ zeroVectorAndAllBitsOff :: BitVector -> Property+ zeroVectorAndAllBitsOff bv = isZeroVector bv === (all not . toBits) bv - toUnsignedNumImpliesZeroVector :: BitVector -> Property- toUnsignedNumImpliesZeroVector bv =- ((0 ==) . (toUnsignedNumber :: BitVector -> Integer)) bv -=> isZeroVector bv+ toUnsignedNumImpliesZeroVector :: BitVector -> Property+ toUnsignedNumImpliesZeroVector bv =+ ((0 ==) . (toUnsignedNumber :: BitVector -> Integer)) bv -=> isZeroVector bv - bitVectorUnsignedNumIdentity :: Integer -> Property- bitVectorUnsignedNumIdentity num =- (toSignedNumber . fromNumber width) num === num- where- width = succ . succ . ceiling . logBase (2.0 :: Double) . fromIntegral $ abs num+ bitVectorUnsignedNumIdentity :: Integer -> Property+ bitVectorUnsignedNumIdentity num = (toSignedNumber . fromNumber width) num === num+ where width = succ . succ . ceiling . logBase (2.0 :: Double) . fromIntegral $ abs num - noSignBitVector :: BitVector -> Property- noSignBitVector bv =- isSigned bv === False+ noSignBitVector :: BitVector -> Property+ noSignBitVector bv = isSigned bv === False - badSubRangeEmptyResult :: (Word, Word) -> BitVector -> Property- badSubRangeEmptyResult range@(lower, upper) bv =- lower > upper -=> subRange range bv === zeroBits+ badSubRangeEmptyResult :: (Word, Word) -> BitVector -> Property+ badSubRangeEmptyResult range@(lower, upper) bv = lower > upper -=> subRange range bv === zeroBits - subRangeFixedDimension :: (NonNegative Int, NonNegative Int) -> BitVector -> Property- subRangeFixedDimension (NonNegative lowerI, NonNegative upperI) bv =- lower <= upper -=> dimension (subRange (lower, upper) bv) === upper - lower + 1- where- lower = toEnum lowerI- upper = toEnum upperI+ subRangeFixedDimension :: (NonNegative Int, NonNegative Int) -> BitVector -> Property+ subRangeFixedDimension (NonNegative lowerI, NonNegative upperI) bv =+ lower <= upper -=> dimension (subRange (lower, upper) bv) === upper - lower + 1+ where+ lower = toEnum lowerI+ upper = toEnum upperI bitVectorRankSelect :: TestTree-bitVectorRankSelect = testGroup "BitVector rank/select"+bitVectorRankSelect = testGroup+ "BitVector rank/select" [ QC.testProperty "select (bit i) 0 === i" selectBitValue , QC.testProperty "select (bit x .|. bit y) 0 === min (select (bit x) 0) (select (bit y) 0)" selectBitOr- , QC.testProperty "rank (bit x .|. bit y) (max x y + 1) === rank (bit x) (x+1) + rank (bit y) (y+1)" rankBitOr+ , QC.testProperty+ "rank (bit x .|. bit y) (max x y + 1) === rank (bit x) (x+1) + rank (bit y) (y+1)"+ rankBitOr , QC.testProperty "rank (bit i) (i+1) === i" rankBitValue , QC.testProperty "rank <$> id <*> dimension === popCount" rankPopCount , QC.testProperty "rank bv i === length . filter id . take i . toBits bv" rankToBits , QC.testProperty "rank bv (select bv i) === i" rankSelectMinDef ]- where- selectBitValue :: NonNegative Int -> Property- selectBitValue (NonNegative x) =- select (bit x) 0 === Just (toEnum x)+ where+ selectBitValue :: NonNegative Int -> Property+ selectBitValue (NonNegative x) = select (bit x) 0 === Just (toEnum x) - selectBitOr :: NonNegative Int -> NonNegative Int -> Property- selectBitOr (NonNegative x) (NonNegative y) =- select (bit x .|. bit y) 0 === min (select (bit x) 0) (select (bit y) 0)+ selectBitOr :: NonNegative Int -> NonNegative Int -> Property+ selectBitOr (NonNegative x) (NonNegative y) =+ select (bit x .|. bit y) 0 === min (select (bit x) 0) (select (bit y) 0) - rankBitValue :: NonNegative Word -> Property- rankBitValue (NonNegative x) =- rank (bit (fromEnum x)) (x+1) === 1+ rankBitValue :: NonNegative Word -> Property+ rankBitValue (NonNegative x) = rank (bit (fromEnum x)) (x + 1) === 1 - rankBitOr :: NonNegative Int -> NonNegative Int -> Property- rankBitOr (NonNegative x) (NonNegative y) =- x /= y -=>- rank (bit x .|. bit y) z' === rank (bit x) (x'+1) + rank (bit y) (y'+1)- where- x' = toEnum x- y' = toEnum y- z' = max x' y' + 1+ rankBitOr :: NonNegative Int -> NonNegative Int -> Property+ rankBitOr (NonNegative x) (NonNegative y) =+ x /= y -=> rank (bit x .|. bit y) z' === rank (bit x) (x' + 1) + rank (bit y) (y' + 1)+ where+ x' = toEnum x+ y' = toEnum y+ z' = max x' y' + 1 - rankPopCount :: BitVector -> Property- rankPopCount bv =- (rank <$> id <*> dimension) bv === toEnum (popCount bv)+ rankPopCount :: BitVector -> Property+ rankPopCount bv = (rank <$> id <*> dimension) bv === toEnum (popCount bv) - rankToBits :: BitVector -> NonNegative Word -> Property- rankToBits bv (NonNegative x) =- rank bv x === (toEnum . length . filter id . take (fromEnum x) . toBits) bv+ rankToBits :: BitVector -> NonNegative Word -> Property+ rankToBits bv (NonNegative x) =+ rank bv x === (toEnum . length . filter id . take (fromEnum x) . toBits) bv - rankSelectMinDef :: BitVector -> NonNegative Word -> Property- rankSelectMinDef bv (NonNegative x) =- let idx = select bv x- k = fromJust idx- in idx === Nothing .||. rank bv k === x- + rankSelectMinDef :: BitVector -> NonNegative Word -> Property+ rankSelectMinDef bv (NonNegative x) =+ let idx = select bv x+ k = fromJust idx+ in idx === Nothing .||. rank bv k === x -monoFunctorEquivelence :: TestTree-monoFunctorEquivelence = testGroup "Equivelence of a MonoFunctor"- [ SC.testProperty "omap f === fromBits . map f . toBits" $ forAll omapOptimizationIsValid- ]- where- omapOptimizationIsValid :: (Bool -> Bool, VisualBitVector) -> Bool- omapOptimizationIsValid (f, y) = omap f bv == (fromBits . map f . toBits) bv- where- bv = getBitVector y +monoFunctorEquivalence :: TestTree+monoFunctorEquivalence = testGroup+ "Equivalence of a MonoFunctor"+ [SC.testProperty "omap f === fromBits . map f . toBits" $ forAll omapOptimizationIsValid]+ where+ omapOptimizationIsValid :: (Bool -> Bool, VisualBitVector) -> Bool+ omapOptimizationIsValid (f, y) = omap f bv == (fromBits . map f . toBits) bv+ where bv = getBitVector y -monoFoldableEquivelence :: TestTree-monoFoldableEquivelence = testGroup "Equivelence of a MonoFoldable"- [ SC.testProperty "oall f === all f . otoList" $ forAll oallOptimizationIsValid- , SC.testProperty "oany f === any f . otoList" $ forAll oanyOptimizationIsValid- , SC.testProperty "ofoldr1Ex f === foldr1 f . otoList" $ forAll ofoldr1ExOptimizationIsValid- , SC.testProperty "ofold'1Ex' f === foldl1 f . otoList" $ forAll ofoldl1ExOptimizationIsValid- , SC.testProperty "headEx === head . otoList" $ forAll headExOptimizationIsValid- , SC.testProperty "lastEx === last . otoList" $ forAll lastExOptimizationIsValid--- , SC.testProperty "maximumByEx f === maximumBy f . otoList" $ forAll maximumByExOptimizationIsValid--- , SC.testProperty "minimumByEx f === minimumBy f . otoList" $ forAll minimumByExOptimizationIsValid- , SC.testProperty "oelem e === oelem e . otoList" $ forAll oelemOptimizationIsValid- , SC.testProperty "onotElem e === onotElem e . otoList" $ forAll onotElemOptimizationIsValid++monoFoldableEquivalence :: TestTree+monoFoldableEquivalence = testGroup+ "Equivalence of a MonoFoldable"+ [ SC.testProperty "oall f === all f . otoList" $ forAll oallOptimizationIsValid+ , SC.testProperty "oany f === any f . otoList" $ forAll oanyOptimizationIsValid+ , SC.testProperty "ofoldr1Ex f === foldr1 f . otoList" $ forAll ofoldr1ExOptimizationIsValid+ , SC.testProperty "ofoldl1Ex' f === foldl1 f . otoList" $ forAll ofoldl1ExOptimizationIsValid+ , SC.testProperty "headEx === head . otoList" $ forAll headExOptimizationIsValid+ , SC.testProperty "lastEx === last . otoList" $ forAll lastExOptimizationIsValid+ , SC.testProperty "maximumByEx f === maximumBy f . otoList" $ forAll maximumByExOptimizationIsValid+ , SC.testProperty "minimumByEx f === minimumBy f . otoList" $ forAll minimumByExOptimizationIsValid+ , SC.testProperty "oelem e === oelem e . otoList" $ forAll oelemOptimizationIsValid+ , SC.testProperty "onotElem e === onotElem e . otoList" $ forAll onotElemOptimizationIsValid ]- where- oallOptimizationIsValid :: (UnaryLogicalOperator, VisualBitVector) -> Bool- oallOptimizationIsValid (y, x) = oall op bv == (all op . otoList) bv- where- bv = getBitVector x- op = getUnaryLogicalOperator y+ where+ oallOptimizationIsValid :: (UnaryLogicalOperator, VisualBitVector) -> Bool+ oallOptimizationIsValid (y, x) = oall op bv == (all op . otoList) bv+ where+ bv = getBitVector x+ op = getUnaryLogicalOperator y - oanyOptimizationIsValid :: (UnaryLogicalOperator, VisualBitVector) -> Bool- oanyOptimizationIsValid (y, x) = oany op bv == (any op . otoList) bv- where- bv = getBitVector x- op = getUnaryLogicalOperator y+ oanyOptimizationIsValid :: (UnaryLogicalOperator, VisualBitVector) -> Bool+ oanyOptimizationIsValid (y, x) = oany op bv == (any op . otoList) bv+ where+ bv = getBitVector x+ op = getUnaryLogicalOperator y - ofoldr1ExOptimizationIsValid :: (BinaryLogicalOperator, VisualBitVector) -> Bool- ofoldr1ExOptimizationIsValid (y, x) =- isZeroVector bv || ofoldr1Ex op bv == (foldr1 op . otoList) bv- where- bv = getBitVector x- op = getBinaryLogicalOperator y+ ofoldr1ExOptimizationIsValid :: (BinaryLogicalOperator, VisualBitVector) -> Bool+ ofoldr1ExOptimizationIsValid (y, x) = isZeroVector bv || ofoldr1Ex op bv == (foldr1 op . otoList) bv+ where+ bv = getBitVector x+ op = getBinaryLogicalOperator y - ofoldl1ExOptimizationIsValid :: (BinaryLogicalOperator, VisualBitVector) -> Bool- ofoldl1ExOptimizationIsValid (y, x) =- isZeroVector bv || ofoldl1Ex' op bv == (foldl1 op . otoList) bv- where- bv = getBitVector x- op = getBinaryLogicalOperator y+ ofoldl1ExOptimizationIsValid :: (BinaryLogicalOperator, VisualBitVector) -> Bool+ ofoldl1ExOptimizationIsValid (y, x) = isZeroVector bv || ofoldl1Ex' op bv == (foldl1 op . otoList) bv+ where+ bv = getBitVector x+ op = getBinaryLogicalOperator y - headExOptimizationIsValid :: VisualBitVector -> Bool- headExOptimizationIsValid x =- isZeroVector bv || headEx bv == (head . otoList) bv- where- bv = getBitVector x+ headExOptimizationIsValid :: VisualBitVector -> Bool+ headExOptimizationIsValid x = isZeroVector bv || headEx bv == (head . otoList) bv+ where bv = getBitVector x - lastExOptimizationIsValid :: VisualBitVector -> Bool- lastExOptimizationIsValid x =- isZeroVector bv || lastEx bv == (last . otoList) bv- where- bv = getBitVector x+ lastExOptimizationIsValid :: VisualBitVector -> Bool+ lastExOptimizationIsValid x = isZeroVector bv || lastEx bv == (last . otoList) bv+ where bv = getBitVector x - maximumByExOptimizationIsValid :: (VisualBitVector, ComparisonOperator) -> Bool- maximumByExOptimizationIsValid (x, y) =- isZeroVector bv || maximumByEx op bv == (maximumBy op . otoList) bv- where- bv = getBitVector x- op = getComparator y+ maximumByExOptimizationIsValid :: (VisualBitVector, ComparisonOperator) -> Bool+ maximumByExOptimizationIsValid (x, y) =+ isZeroVector bv || maximumByEx op bv == (maximumBy op . otoList) bv+ where+ bv = getBitVector x+ op = getComparator y - minimumByExOptimizationIsValid :: (VisualBitVector, ComparisonOperator) -> Bool- minimumByExOptimizationIsValid (x, y) =- isZeroVector bv || minimumByEx op bv == (minimumBy op . otoList) bv- where- bv = getBitVector x- op = getComparator y+ minimumByExOptimizationIsValid :: (VisualBitVector, ComparisonOperator) -> Bool+ minimumByExOptimizationIsValid (x, y) =+ isZeroVector bv || minimumByEx op bv == (minimumBy op . otoList) bv+ where+ bv = getBitVector x+ op = getComparator y - oelemOptimizationIsValid :: (VisualBitVector, Bool) -> Bool- oelemOptimizationIsValid (x, e) = oelem e bv == (oelem e . otoList) bv- where- bv = getBitVector x+ oelemOptimizationIsValid :: (VisualBitVector, Bool) -> Bool+ oelemOptimizationIsValid (x, e) = oelem e bv == (oelem e . otoList) bv where bv = getBitVector x - onotElemOptimizationIsValid :: (VisualBitVector, Bool) -> Bool- onotElemOptimizationIsValid (x, e) = onotElem e bv == (onotElem e . otoList) bv- where- bv = getBitVector x+ onotElemOptimizationIsValid :: (VisualBitVector, Bool) -> Bool+ onotElemOptimizationIsValid (x, e) = onotElem e bv == (onotElem e . otoList) bv+ where bv = getBitVector x -monoZipEquivelence :: TestTree-monoZipEquivelence = testGroup "Equivelence of a MonoZip"- [ SC.testProperty "ozipWith f x === fromBits . zipWith f . (toBits x) . toBits" $ forAll omapOptimizationIsValid+monoZipEquivalence :: TestTree+monoZipEquivalence = testGroup+ "Equivalence of a MonoZip"+ [ SC.testProperty "ozipWith f x === fromBits . zipWith f . (toBits x) . toBits"+ $ forAll omapOptimizationIsValid ]- where- omapOptimizationIsValid :: (BinaryLogicalOperator, VisualBitVectorSmall, VisualBitVectorSmall) -> Bool- omapOptimizationIsValid (f, x, y) = ozipWith op lhs rhs == (fromBits . zipWith op (toBits lhs) . toBits) rhs- where- op = getBinaryLogicalOperator f- lhs = getBitVector x- rhs = getBitVector y+ where+ omapOptimizationIsValid+ :: (BinaryLogicalOperator, VisualBitVectorSmall, VisualBitVectorSmall) -> Bool+ omapOptimizationIsValid (f, x, y) = ozipWith op lhs rhs+ == (fromBits . zipWith op (toBits lhs) . toBits) rhs+ where+ op = getBinaryLogicalOperator f+ lhs = getBitVector x+ rhs = getBitVector y+ {- infixr 0 ===>
util/Operator/Binary/Comparison.hs view
@@ -1,27 +1,41 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-| +Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++-}++{-# Language BangPatterns #-}+{-# Language DeriveAnyClass #-}+{-# Language DeriveGeneric #-}+{-# Language DerivingStrategies #-}+{-# Language FlexibleInstances #-}+{-# Language MultiParamTypeClasses #-}+{-# Language Safe #-}+ module Operator.Binary.Comparison- ( ComparisonOperator(getComparator)- ) where+ ( ComparisonOperator (getComparator)+ ) where import Control.DeepSeq-import Data.Data-import Data.List (elemIndex)-import Data.Maybe (fromJust)-import Data.Monoid ()-import Data.Semigroup+import Data.List (elemIndex)+import Data.Maybe (fromJust)+import Data.Monoid () import GHC.Generics-import Test.QuickCheck hiding (generate)+import Test.QuickCheck hiding (generate) import Test.SmallCheck.Series -newtype ComparisonOperator = CO { getComparator :: Bool -> Bool -> Ordering }- deriving (Generic, NFData, Typeable)+{-|+Representation of all possible binary operators of type @(Bool -> Bool -> Bool)@.+Useful for both property and enumeration based testing.+-}+newtype ComparisonOperator+ = CO { getComparator :: Bool -> Bool -> Ordering }+ deriving anyclass (NFData)+ deriving stock (Generic) comparatorList :: [ComparisonOperator]@@ -30,10 +44,13 @@ x <- [minBound .. maxBound] y <- [minBound .. maxBound] z <- [minBound .. maxBound]- pure . CO $ \a b -> if not a && not b then w- else if not a && b then x- else if a && not b then y- else {- a && b -} z+ pure+ $ let+ op False False = w+ op False True = x+ op True False = y+ op True True = z+ in CO op instance Arbitrary ComparisonOperator where@@ -55,8 +72,7 @@ instance Enum ComparisonOperator where - toEnum n = let !i = n `quot` length comparatorList- in comparatorList !! i+ toEnum n = let !i = n `quot` length comparatorList in comparatorList !! i fromEnum c = fromJust $ elemIndex c comparatorList @@ -65,9 +81,9 @@ (CO f) == (CO g) = and [ f False False == g False False- , f False True == g False True- , f True False == g True False- , f True True == g True True+ , f False True == g False True+ , f True False == g True False+ , f True True == g True True ] @@ -80,8 +96,8 @@ show (CO f) = unlines [ ""- , "f / F F -> " <> show (f False False)- , " | F T -> " <> show (f False True )- , " | T F -> " <> show (f True False)- , " \\ T T -> " <> show (f True True )+ , "f / F F -> " <> show (f False False)+ , " | F T -> " <> show (f False True)+ , " | T F -> " <> show (f True False)+ , " \\ T T -> " <> show (f True True) ]
util/Operator/Binary/Logical.hs view
@@ -1,26 +1,40 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-| +Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++-}++{-# Language DeriveAnyClass #-}+{-# Language DeriveDataTypeable #-}+{-# Language DeriveGeneric #-}+{-# Language DerivingStrategies #-}+{-# Language FlexibleInstances #-}+{-# Language MultiParamTypeClasses #-}+{-# Language Safe #-}+ module Operator.Binary.Logical- ( BinaryLogicalOperator()- , getBinaryLogicalSymbol- , getBinaryLogicalOperator- , fromBinaryLogicalFunction- ) where+ ( BinaryLogicalOperator ()+ , fromBinaryLogicalFunction+ , getBinaryLogicalOperator+ , getBinaryLogicalSymbol+ ) where import Control.DeepSeq import Data.Data import Data.Monoid ()-import Data.Semigroup import GHC.Generics-import Test.QuickCheck hiding (generate)+import Test.QuickCheck hiding (generate) import Test.SmallCheck.Series -data BinaryLogicalOperator+{-|+Representation of all possible /binary/ operators of type @(Bool -> Bool -> Bool)@.+Useful for both property and enumeration based testing.+-}+data BinaryLogicalOperator = AlwaysFalse | LogicalNOR | ConverseNonImplication@@ -37,7 +51,8 @@ | ConverseImplication | LogicalOR | AlwaysTrue- deriving (Data, Eq, Ord, Generic, NFData, Typeable)+ deriving anyclass (NFData)+ deriving stock (Data, Eq, Generic, Ord) instance Arbitrary BinaryLogicalOperator where@@ -59,87 +74,85 @@ instance Enum BinaryLogicalOperator where - toEnum n =- case n `rem` 16 of- 0 -> AlwaysFalse- 1 -> LogicalNOR- 2 -> ConverseNonImplication- 3 -> NotFirstArgument- 4 -> NonImplication- 5 -> NotSecondArgument- 6 -> LogicalXOR- 7 -> LogicalNAND- 8 -> LogicalAND- 9 -> LogicalXNOR- 10 -> SecondArgument- 11 -> Implication- 12 -> FirstArgument- 13 -> ConverseImplication- 14 -> LogicalOR- _ -> AlwaysTrue+ toEnum n = case n `rem` 16 of+ 0 -> AlwaysFalse+ 1 -> LogicalNOR+ 2 -> ConverseNonImplication+ 3 -> NotFirstArgument+ 4 -> NonImplication+ 5 -> NotSecondArgument+ 6 -> LogicalXOR+ 7 -> LogicalNAND+ 8 -> LogicalAND+ 9 -> LogicalXNOR+ 10 -> SecondArgument+ 11 -> Implication+ 12 -> FirstArgument+ 13 -> ConverseImplication+ 14 -> LogicalOR+ _ -> AlwaysTrue - fromEnum x =- case x of- AlwaysFalse -> 0- LogicalNOR -> 1- ConverseNonImplication -> 2- NotFirstArgument -> 3- NonImplication -> 4- NotSecondArgument -> 5- LogicalXOR -> 6- LogicalNAND -> 7- LogicalAND -> 8- LogicalXNOR -> 9- SecondArgument -> 10- Implication -> 11- FirstArgument -> 12- ConverseImplication -> 13- LogicalOR -> 14- AlwaysTrue -> 15+ fromEnum x = case x of+ AlwaysFalse -> 0+ LogicalNOR -> 1+ ConverseNonImplication -> 2+ NotFirstArgument -> 3+ NonImplication -> 4+ NotSecondArgument -> 5+ LogicalXOR -> 6+ LogicalNAND -> 7+ LogicalAND -> 8+ LogicalXNOR -> 9+ SecondArgument -> 10+ Implication -> 11+ FirstArgument -> 12+ ConverseImplication -> 13+ LogicalOR -> 14+ AlwaysTrue -> 15 - succ x =- case x of- AlwaysFalse -> LogicalNOR- LogicalNOR -> ConverseNonImplication- ConverseNonImplication -> NotFirstArgument- NotFirstArgument -> NonImplication- NonImplication -> NotSecondArgument- NotSecondArgument -> LogicalXOR- LogicalXOR -> LogicalNAND- LogicalNAND -> LogicalAND- LogicalAND -> LogicalXNOR- LogicalXNOR -> SecondArgument- SecondArgument -> Implication- Implication -> FirstArgument- FirstArgument -> ConverseImplication- ConverseImplication -> LogicalOR- LogicalOR -> AlwaysTrue- AlwaysTrue -> AlwaysFalse+ succ x = case x of+ AlwaysFalse -> LogicalNOR+ LogicalNOR -> ConverseNonImplication+ ConverseNonImplication -> NotFirstArgument+ NotFirstArgument -> NonImplication+ NonImplication -> NotSecondArgument+ NotSecondArgument -> LogicalXOR+ LogicalXOR -> LogicalNAND+ LogicalNAND -> LogicalAND+ LogicalAND -> LogicalXNOR+ LogicalXNOR -> SecondArgument+ SecondArgument -> Implication+ Implication -> FirstArgument+ FirstArgument -> ConverseImplication+ ConverseImplication -> LogicalOR+ LogicalOR -> AlwaysTrue+ AlwaysTrue -> AlwaysFalse - pred x =- case x of- AlwaysFalse -> AlwaysTrue- LogicalNOR -> AlwaysFalse- ConverseNonImplication -> LogicalNOR- NotFirstArgument -> ConverseNonImplication- NonImplication -> NotFirstArgument- NotSecondArgument -> NonImplication- LogicalXOR -> NotSecondArgument- LogicalNAND -> LogicalXOR- LogicalAND -> LogicalNAND- LogicalXNOR -> LogicalAND- SecondArgument -> LogicalXNOR- Implication -> SecondArgument- FirstArgument -> Implication- ConverseImplication -> FirstArgument- LogicalOR -> ConverseImplication- AlwaysTrue -> LogicalOR+ pred x = case x of+ AlwaysFalse -> AlwaysTrue+ LogicalNOR -> AlwaysFalse+ ConverseNonImplication -> LogicalNOR+ NotFirstArgument -> ConverseNonImplication+ NonImplication -> NotFirstArgument+ NotSecondArgument -> NonImplication+ LogicalXOR -> NotSecondArgument+ LogicalNAND -> LogicalXOR+ LogicalAND -> LogicalNAND+ LogicalXNOR -> LogicalAND+ SecondArgument -> LogicalXNOR+ Implication -> SecondArgument+ FirstArgument -> Implication+ ConverseImplication -> FirstArgument+ LogicalOR -> ConverseImplication+ AlwaysTrue -> LogicalOR + -- enumFrom x = toEnum <$> [fromEnum x .. 15] --- enumFromTo x y = +-- enumFromTo x y = + instance Monad m => Serial m BinaryLogicalOperator where series = generate $ const [minBound .. maxBound]@@ -148,84 +161,91 @@ instance Show BinaryLogicalOperator where show x = "f p q = " <> s- where- s = case x of- AlwaysFalse -> "False (Contradiction)"- LogicalNOR -> "¬p ∧ ¬q (Logical NOR)"- ConverseNonImplication -> "¬p ∧ q (Converse Non-Implication)"- NotFirstArgument -> "¬p (Not First)"- NonImplication -> "p ∧ ¬q (Non-Implication)"- NotSecondArgument -> "¬q (Not Second)"- LogicalXOR -> "(p ∧ ¬q) ∨ (¬p ∧ q) (Logical XOR)"- LogicalNAND -> "¬p ∨ ¬q (Logical NAND)"- LogicalAND -> "p ∧ q (Logical AND)"- LogicalXNOR -> "(p ∧ q) ∨ (¬p ∧ ¬q) (Logical XNOR)"- SecondArgument -> "q (Second)"- Implication -> "¬p ∨ q (Implication)"- FirstArgument -> "p (First)"- ConverseImplication -> "p ∨ ¬q (Converse Implication)"- LogicalOR -> "p ∧ q (Logical OR)"- AlwaysTrue -> "True (Tautology)"+ where+ s = case x of+ AlwaysFalse -> "False (Contradiction)"+ LogicalNOR -> "¬p ∧ ¬q (Logical NOR)"+ ConverseNonImplication -> "¬p ∧ q (Converse Non-Implication)"+ NotFirstArgument -> "¬p (Not First)"+ NonImplication -> "p ∧ ¬q (Non-Implication)"+ NotSecondArgument -> "¬q (Not Second)"+ LogicalXOR -> "(p ∧ ¬q) ∨ (¬p ∧ q) (Logical XOR)"+ LogicalNAND -> "¬p ∨ ¬q (Logical NAND)"+ LogicalAND -> "p ∧ q (Logical AND)"+ LogicalXNOR -> "(p ∧ q) ∨ (¬p ∧ ¬q) (Logical XNOR)"+ SecondArgument -> "q (Second)"+ Implication -> "¬p ∨ q (Implication)"+ FirstArgument -> "p (First)"+ ConverseImplication -> "p ∨ ¬q (Converse Implication)"+ LogicalOR -> "p ∧ q (Logical OR)"+ AlwaysTrue -> "True (Tautology)" +{-|+Convert from a closed, binary function over 'Bool' to a 'BinaryLogicalOperator'.+-}+fromBinaryLogicalFunction :: (Bool -> Bool -> Bool) -> BinaryLogicalOperator+fromBinaryLogicalFunction f = case (f True True, f True False, f False True, f False False) of+ (False, False, False, False) -> AlwaysFalse+ (False, False, False, True ) -> LogicalNOR+ (False, False, True , False) -> ConverseNonImplication+ (False, False, True , True ) -> NotFirstArgument+ (False, True , False, False) -> NonImplication+ (False, True , False, True ) -> NotSecondArgument+ (False, True , True , False) -> LogicalXOR+ (False, True , True , True ) -> LogicalNAND+ (True , False, False, False) -> LogicalAND+ (True , False, False, True ) -> LogicalXNOR+ (True , False, True , False) -> SecondArgument+ (True , False, True , True ) -> Implication+ (True , True , False, False) -> FirstArgument+ (True , True , False, True ) -> ConverseImplication+ (True , True , True , False) -> LogicalOR+ (True , True , True , True ) -> AlwaysTrue+++{-|+Convert from a 'BinaryLogicalOperator' to a closed, binary function over 'Bool'.+-} getBinaryLogicalOperator :: BinaryLogicalOperator -> Bool -> Bool -> Bool-getBinaryLogicalOperator x =- case x of- AlwaysFalse -> const (const False)- LogicalNOR -> \p q -> not $ p || q- ConverseNonImplication -> \p q -> not p && q- NotFirstArgument -> \p _ -> not p- NonImplication -> \p q -> p && not q- NotSecondArgument -> \_ q -> not q- LogicalXOR -> (/=)- LogicalNAND -> \p q -> not $ p && q- LogicalAND -> (&&)- LogicalXNOR -> (==)- SecondArgument -> \_ q -> q- Implication -> \p q -> not p || q- FirstArgument -> const- ConverseImplication -> \p q -> p || not q- LogicalOR -> (||)- AlwaysTrue -> const (const True)+getBinaryLogicalOperator x = case x of+ AlwaysFalse -> const (const False)+ LogicalNOR -> \p q -> not $ p || q+ ConverseNonImplication -> \p q -> not p && q+ NotFirstArgument -> \p _ -> not p+ NonImplication -> \p q -> p && not q+ NotSecondArgument -> \_ q -> not q+ LogicalXOR -> (/=)+ LogicalNAND -> \p q -> not $ p && q+ LogicalAND -> (&&)+ LogicalXNOR -> (==)+ SecondArgument -> \_ q -> q+ Implication -> \p q -> not p || q+ FirstArgument -> const+ ConverseImplication -> \p q -> p || not q+ LogicalOR -> (||)+ AlwaysTrue -> const (const True) +{-|+Query the Haskell expression of a 'BinaryLogicalOperator' representation symbolically as a 'String'.+-} getBinaryLogicalSymbol :: BinaryLogicalOperator -> String-getBinaryLogicalSymbol x =- case x of- AlwaysFalse -> "(const False)"- LogicalNOR -> "(not . (||))"- ConverseNonImplication -> "(</=)"- NotFirstArgument -> "(not . fst)"- NonImplication -> "(=/>)"- NotSecondArgument -> "(not . snd)"- LogicalXOR -> "(/=)"- LogicalNAND -> "(not . (&&))"- LogicalAND -> "(&&)"- LogicalXNOR -> "(==)"- SecondArgument -> "(snd)"- Implication -> "(==>)"- FirstArgument -> "(fst)"- ConverseImplication -> "(<==)"- LogicalOR -> "(||)"- AlwaysTrue -> "(const True)"-+getBinaryLogicalSymbol x = case x of+ AlwaysFalse -> "(const False)"+ LogicalNOR -> "(not . (||))"+ ConverseNonImplication -> "(</=)"+ NotFirstArgument -> "(not . fst)"+ NonImplication -> "(=/>)"+ NotSecondArgument -> "(not . snd)"+ LogicalXOR -> "(/=)"+ LogicalNAND -> "(not . (&&))"+ LogicalAND -> "(&&)"+ LogicalXNOR -> "(==)"+ SecondArgument -> "(snd)"+ Implication -> "(==>)"+ FirstArgument -> "(fst)"+ ConverseImplication -> "(<==)"+ LogicalOR -> "(||)"+ AlwaysTrue -> "(const True)" -fromBinaryLogicalFunction :: (Bool -> Bool -> Bool) -> BinaryLogicalOperator-fromBinaryLogicalFunction f = - case (f True True, f True False, f False True, f False False) of- (False, False, False, False) -> AlwaysFalse- (False, False, False, True ) -> LogicalNOR- (False, False, True , False) -> ConverseNonImplication- (False, False, True , True ) -> NotFirstArgument- (False, True , False, False) -> NonImplication- (False, True , False, True ) -> NotSecondArgument- (False, True , True , False) -> LogicalXOR- (False, True , True , True ) -> LogicalNAND- (True , False, False, False) -> LogicalAND- (True , False, False, True ) -> LogicalXNOR- (True , False, True , False) -> SecondArgument- (True , False, True , True ) -> Implication- (True , True , False, False) -> FirstArgument- (True , True , False, True ) -> ConverseImplication- (True , True , True , False) -> LogicalOR - (True , True , True , True ) -> AlwaysTrue
util/Operator/Unary/Logical.hs view
@@ -1,31 +1,46 @@-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE MultiParamTypeClasses #-}+{-| +Copyright : © 2020 Alex Washburn+License : BSD-3-Clause+Maintainer : github@recursion.ninja+Stability : Stable++-}++{-# Language DeriveAnyClass #-}+{-# Language DeriveDataTypeable #-}+{-# Language DeriveGeneric #-}+{-# Language DerivingStrategies #-}+{-# Language FlexibleInstances #-}+{-# Language MultiParamTypeClasses #-}+{-# Language Safe #-}+ module Operator.Unary.Logical- ( UnaryLogicalOperator()- , getUnaryLogicalSymbol- , getUnaryLogicalOperator- , fromUnaryLogicalFunction- ) where+ ( UnaryLogicalOperator ()+ , fromUnaryLogicalFunction+ , getUnaryLogicalOperator+ , getUnaryLogicalSymbol+ ) where import Control.DeepSeq import Data.Data import Data.Monoid ()-import Data.Semigroup import GHC.Generics-import Test.QuickCheck hiding (generate)+import Test.QuickCheck hiding (generate) import Test.SmallCheck.Series -data UnaryLogicalOperator+{-|+Representation of all possible /unary/ operators of type @(Bool -> Bool)@.+Useful for both property and enumeration based testing.+-}+data UnaryLogicalOperator = AlwaysFalse | Identity | Negation | AlwaysTrue- deriving (Data, Eq, Ord, Generic, NFData, Typeable)+ deriving anyclass (NFData)+ deriving stock (Data, Eq, Generic, Ord) instance Arbitrary UnaryLogicalOperator where@@ -47,34 +62,29 @@ instance Enum UnaryLogicalOperator where - toEnum n =- case n `rem` 4 of- 0 -> AlwaysFalse- 1 -> Identity- 2 -> Negation- _ -> AlwaysTrue-- fromEnum x =- case x of- AlwaysFalse -> 0- Identity -> 1- Negation -> 2- AlwaysTrue -> 3+ toEnum n = case n `rem` 4 of+ 0 -> AlwaysFalse+ 1 -> Identity+ 2 -> Negation+ _ -> AlwaysTrue - succ x =- case x of- AlwaysFalse -> Identity- Identity -> Negation- Negation -> AlwaysTrue- AlwaysTrue -> AlwaysFalse+ fromEnum x = case x of+ AlwaysFalse -> 0+ Identity -> 1+ Negation -> 2+ AlwaysTrue -> 3 + succ x = case x of+ AlwaysFalse -> Identity+ Identity -> Negation+ Negation -> AlwaysTrue+ AlwaysTrue -> AlwaysFalse - pred x =- case x of- AlwaysFalse -> AlwaysTrue- Identity -> AlwaysFalse- Negation -> Identity- AlwaysTrue -> Negation+ pred x = case x of+ AlwaysFalse -> AlwaysTrue+ Identity -> AlwaysFalse+ Negation -> Identity+ AlwaysTrue -> Negation instance Monad m => Serial m UnaryLogicalOperator where@@ -85,37 +95,42 @@ instance Show UnaryLogicalOperator where show x = "f p q = " <> s- where- s = case x of- AlwaysFalse -> "False (Contradiction)"- Identity -> "id (Identity)"- Negation -> "not (Negation)"- AlwaysTrue -> "True (Tautology)"+ where+ s = case x of+ AlwaysFalse -> "False (Contradiction)"+ Identity -> "id (Identity)"+ Negation -> "not (Negation)"+ AlwaysTrue -> "True (Tautology)" -getUnaryLogicalOperator :: UnaryLogicalOperator -> Bool -> Bool-getUnaryLogicalOperator x =- case x of- AlwaysFalse -> const False- Identity -> id- Negation -> not- AlwaysTrue -> const True+{-|+Convert from a closed, unnary function over 'Bool' to a 'UnaryLogicalOperator'.+-}+fromUnaryLogicalFunction :: (Bool -> Bool) -> UnaryLogicalOperator+fromUnaryLogicalFunction f = case (f False, f True) of+ (False, False) -> AlwaysFalse+ (False, True ) -> Identity+ (True , False) -> Negation+ (True , True ) -> AlwaysTrue -getUnaryLogicalSymbol :: UnaryLogicalOperator -> String-getUnaryLogicalSymbol x =- case x of- AlwaysFalse -> "(const False)"- Identity -> "(id)"- Negation -> "(not)"- AlwaysTrue -> "(const True)"+{-|+Convert from a 'UnaryLogicalOperator' to a closed, unary function over 'Bool'.+-}+getUnaryLogicalOperator :: UnaryLogicalOperator -> Bool -> Bool+getUnaryLogicalOperator x = case x of+ AlwaysFalse -> const False+ Identity -> id+ Negation -> not+ AlwaysTrue -> const True -fromUnaryLogicalFunction :: (Bool -> Bool) -> UnaryLogicalOperator-fromUnaryLogicalFunction f = - case (f False, f True) of- (False, False) -> AlwaysFalse- (False, True ) -> Identity- (True , False) -> Negation- (True , True ) -> AlwaysTrue-+{-|+Query the Haskell expression of a 'UnaryLogicalOperator' representation symbolically as a 'String'.+-}+getUnaryLogicalSymbol :: UnaryLogicalOperator -> String+getUnaryLogicalSymbol x = case x of+ AlwaysFalse -> "(const False)"+ Identity -> "(id)"+ Negation -> "(not)"+ AlwaysTrue -> "(const True)"