bitvec 0.1.0.2 → 0.1.1.0
raw patch · 12 files changed
+543/−242 lines, 12 filesdep +bitvecdep +quickcheck-classesdep ~QuickCheckdep ~basenew-uploaderPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: bitvec, quickcheck-classes
Dependency ranges changed: QuickCheck, base
API changes (from Hackage documentation)
+ Data.Vector.Unboxed.Bit: (!) :: Unbox a => Vector a -> Int -> a
+ Data.Vector.Unboxed.Bit: (!?) :: Unbox a => Vector a -> Int -> Maybe a
+ Data.Vector.Unboxed.Bit: (++) :: Unbox a => Vector a -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: (//) :: Unbox a => Vector a -> [(Int, a)] -> Vector a
+ Data.Vector.Unboxed.Bit: accum :: Unbox a => (a -> b -> a) -> Vector a -> [(Int, b)] -> Vector a
+ Data.Vector.Unboxed.Bit: accumulate :: (Unbox a, Unbox b) => (a -> b -> a) -> Vector a -> Vector (Int, b) -> Vector a
+ Data.Vector.Unboxed.Bit: accumulate_ :: (Unbox a, Unbox b) => (a -> b -> a) -> Vector a -> Vector Int -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: backpermute :: Unbox a => Vector a -> Vector Int -> Vector a
+ Data.Vector.Unboxed.Bit: break :: Unbox a => (a -> Bool) -> Vector a -> (Vector a, Vector a)
+ Data.Vector.Unboxed.Bit: class (Vector Vector a, MVector MVector a) => Unbox a
+ Data.Vector.Unboxed.Bit: concat :: Unbox a => [Vector a] -> Vector a
+ Data.Vector.Unboxed.Bit: concatMap :: (Unbox a, Unbox b) => (a -> Vector b) -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: cons :: Unbox a => a -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: constructN :: Unbox a => Int -> (Vector a -> a) -> Vector a
+ Data.Vector.Unboxed.Bit: constructrN :: Unbox a => Int -> (Vector a -> a) -> Vector a
+ Data.Vector.Unboxed.Bit: convert :: (Vector v a, Vector w a) => v a -> w a
+ Data.Vector.Unboxed.Bit: copy :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
+ Data.Vector.Unboxed.Bit: create :: Unbox a => (forall s. () => ST s (MVector s a)) -> Vector a
+ Data.Vector.Unboxed.Bit: createT :: (Traversable f, Unbox a) => (forall s. () => ST s (f (MVector s a))) -> f (Vector a)
+ Data.Vector.Unboxed.Bit: data family Vector a :: Type
+ Data.Vector.Unboxed.Bit: drop :: Unbox a => Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: dropWhile :: Unbox a => (a -> Bool) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: elem :: (Unbox a, Eq a) => a -> Vector a -> Bool
+ Data.Vector.Unboxed.Bit: elemIndex :: (Unbox a, Eq a) => a -> Vector a -> Maybe Int
+ Data.Vector.Unboxed.Bit: elemIndices :: (Unbox a, Eq a) => a -> Vector a -> Vector Int
+ Data.Vector.Unboxed.Bit: empty :: Unbox a => Vector a
+ Data.Vector.Unboxed.Bit: enumFromN :: (Unbox a, Num a) => a -> Int -> Vector a
+ Data.Vector.Unboxed.Bit: enumFromStepN :: (Unbox a, Num a) => a -> a -> Int -> Vector a
+ Data.Vector.Unboxed.Bit: enumFromThenTo :: (Unbox a, Enum a) => a -> a -> a -> Vector a
+ Data.Vector.Unboxed.Bit: enumFromTo :: (Unbox a, Enum a) => a -> a -> Vector a
+ Data.Vector.Unboxed.Bit: filter :: Unbox a => (a -> Bool) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: filterM :: (Monad m, Unbox a) => (a -> m Bool) -> Vector a -> m (Vector a)
+ Data.Vector.Unboxed.Bit: find :: Unbox a => (a -> Bool) -> Vector a -> Maybe a
+ Data.Vector.Unboxed.Bit: findIndices :: Unbox a => (a -> Bool) -> Vector a -> Vector Int
+ Data.Vector.Unboxed.Bit: fold1M :: (Monad m, Unbox a) => (a -> a -> m a) -> Vector a -> m a
+ Data.Vector.Unboxed.Bit: fold1M' :: (Monad m, Unbox a) => (a -> a -> m a) -> Vector a -> m a
+ Data.Vector.Unboxed.Bit: fold1M'_ :: (Monad m, Unbox a) => (a -> a -> m a) -> Vector a -> m ()
+ Data.Vector.Unboxed.Bit: fold1M_ :: (Monad m, Unbox a) => (a -> a -> m a) -> Vector a -> m ()
+ Data.Vector.Unboxed.Bit: foldM :: (Monad m, Unbox b) => (a -> b -> m a) -> a -> Vector b -> m a
+ Data.Vector.Unboxed.Bit: foldM' :: (Monad m, Unbox b) => (a -> b -> m a) -> a -> Vector b -> m a
+ Data.Vector.Unboxed.Bit: foldM'_ :: (Monad m, Unbox b) => (a -> b -> m a) -> a -> Vector b -> m ()
+ Data.Vector.Unboxed.Bit: foldM_ :: (Monad m, Unbox b) => (a -> b -> m a) -> a -> Vector b -> m ()
+ Data.Vector.Unboxed.Bit: foldl :: Unbox b => (a -> b -> a) -> a -> Vector b -> a
+ Data.Vector.Unboxed.Bit: foldl' :: Unbox b => (a -> b -> a) -> a -> Vector b -> a
+ Data.Vector.Unboxed.Bit: foldl1 :: Unbox a => (a -> a -> a) -> Vector a -> a
+ Data.Vector.Unboxed.Bit: foldl1' :: Unbox a => (a -> a -> a) -> Vector a -> a
+ Data.Vector.Unboxed.Bit: foldr :: Unbox a => (a -> b -> b) -> b -> Vector a -> b
+ Data.Vector.Unboxed.Bit: foldr' :: Unbox a => (a -> b -> b) -> b -> Vector a -> b
+ Data.Vector.Unboxed.Bit: foldr1 :: Unbox a => (a -> a -> a) -> Vector a -> a
+ Data.Vector.Unboxed.Bit: foldr1' :: Unbox a => (a -> a -> a) -> Vector a -> a
+ Data.Vector.Unboxed.Bit: forM :: (Monad m, Unbox a, Unbox b) => Vector a -> (a -> m b) -> m (Vector b)
+ Data.Vector.Unboxed.Bit: forM_ :: (Monad m, Unbox a) => Vector a -> (a -> m b) -> m ()
+ Data.Vector.Unboxed.Bit: force :: Unbox a => Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: freeze :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+ Data.Vector.Unboxed.Bit: fromList :: Unbox a => [a] -> Vector a
+ Data.Vector.Unboxed.Bit: fromListN :: Unbox a => Int -> [a] -> Vector a
+ Data.Vector.Unboxed.Bit: generate :: Unbox a => Int -> (Int -> a) -> Vector a
+ Data.Vector.Unboxed.Bit: generateM :: (Monad m, Unbox a) => Int -> (Int -> m a) -> m (Vector a)
+ Data.Vector.Unboxed.Bit: head :: Unbox a => Vector a -> a
+ Data.Vector.Unboxed.Bit: headM :: (Unbox a, Monad m) => Vector a -> m a
+ Data.Vector.Unboxed.Bit: ifilter :: Unbox a => (Int -> a -> Bool) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: ifoldM :: (Monad m, Unbox b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a
+ Data.Vector.Unboxed.Bit: ifoldM' :: (Monad m, Unbox b) => (a -> Int -> b -> m a) -> a -> Vector b -> m a
+ Data.Vector.Unboxed.Bit: ifoldM'_ :: (Monad m, Unbox b) => (a -> Int -> b -> m a) -> a -> Vector b -> m ()
+ Data.Vector.Unboxed.Bit: ifoldM_ :: (Monad m, Unbox b) => (a -> Int -> b -> m a) -> a -> Vector b -> m ()
+ Data.Vector.Unboxed.Bit: ifoldl :: Unbox b => (a -> Int -> b -> a) -> a -> Vector b -> a
+ Data.Vector.Unboxed.Bit: ifoldl' :: Unbox b => (a -> Int -> b -> a) -> a -> Vector b -> a
+ Data.Vector.Unboxed.Bit: ifoldr :: Unbox a => (Int -> a -> b -> b) -> b -> Vector a -> b
+ Data.Vector.Unboxed.Bit: ifoldr' :: Unbox a => (Int -> a -> b -> b) -> b -> Vector a -> b
+ Data.Vector.Unboxed.Bit: imap :: (Unbox a, Unbox b) => (Int -> a -> b) -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: imapM :: (Monad m, Unbox a, Unbox b) => (Int -> a -> m b) -> Vector a -> m (Vector b)
+ Data.Vector.Unboxed.Bit: imapM_ :: (Monad m, Unbox a) => (Int -> a -> m b) -> Vector a -> m ()
+ Data.Vector.Unboxed.Bit: imapMaybe :: (Unbox a, Unbox b) => (Int -> a -> Maybe b) -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: indexM :: (Unbox a, Monad m) => Vector a -> Int -> m a
+ Data.Vector.Unboxed.Bit: indexed :: Unbox a => Vector a -> Vector (Int, a)
+ Data.Vector.Unboxed.Bit: infix 4 `elem`
+ Data.Vector.Unboxed.Bit: infixr 5 ++
+ Data.Vector.Unboxed.Bit: init :: Unbox a => Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: iterateN :: Unbox a => Int -> (a -> a) -> a -> Vector a
+ Data.Vector.Unboxed.Bit: iterateNM :: (Monad m, Unbox a) => Int -> (a -> m a) -> a -> m (Vector a)
+ Data.Vector.Unboxed.Bit: izipWith :: (Unbox a, Unbox b, Unbox c) => (Int -> a -> b -> c) -> Vector a -> Vector b -> Vector c
+ Data.Vector.Unboxed.Bit: izipWith3 :: (Unbox a, Unbox b, Unbox c, Unbox d) => (Int -> a -> b -> c -> d) -> Vector a -> Vector b -> Vector c -> Vector d
+ Data.Vector.Unboxed.Bit: izipWith4 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => (Int -> a -> b -> c -> d -> e) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e
+ Data.Vector.Unboxed.Bit: izipWith5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => (Int -> a -> b -> c -> d -> e -> f) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f
+ Data.Vector.Unboxed.Bit: izipWith6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f, Unbox g) => (Int -> a -> b -> c -> d -> e -> f -> g) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f -> Vector g
+ Data.Vector.Unboxed.Bit: izipWithM :: (Monad m, Unbox a, Unbox b, Unbox c) => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)
+ Data.Vector.Unboxed.Bit: izipWithM_ :: (Monad m, Unbox a, Unbox b) => (Int -> a -> b -> m c) -> Vector a -> Vector b -> m ()
+ Data.Vector.Unboxed.Bit: last :: Unbox a => Vector a -> a
+ Data.Vector.Unboxed.Bit: lastM :: (Unbox a, Monad m) => Vector a -> m a
+ Data.Vector.Unboxed.Bit: length :: Unbox a => Vector a -> Int
+ Data.Vector.Unboxed.Bit: map :: (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: mapM :: (Monad m, Unbox a, Unbox b) => (a -> m b) -> Vector a -> m (Vector b)
+ Data.Vector.Unboxed.Bit: mapM_ :: (Monad m, Unbox a) => (a -> m b) -> Vector a -> m ()
+ Data.Vector.Unboxed.Bit: mapMaybe :: (Unbox a, Unbox b) => (a -> Maybe b) -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: maxIndex :: (Unbox a, Ord a) => Vector a -> Int
+ Data.Vector.Unboxed.Bit: maxIndexBy :: Unbox a => (a -> a -> Ordering) -> Vector a -> Int
+ Data.Vector.Unboxed.Bit: maximum :: (Unbox a, Ord a) => Vector a -> a
+ Data.Vector.Unboxed.Bit: maximumBy :: Unbox a => (a -> a -> Ordering) -> Vector a -> a
+ Data.Vector.Unboxed.Bit: minIndex :: (Unbox a, Ord a) => Vector a -> Int
+ Data.Vector.Unboxed.Bit: minIndexBy :: Unbox a => (a -> a -> Ordering) -> Vector a -> Int
+ Data.Vector.Unboxed.Bit: minimum :: (Unbox a, Ord a) => Vector a -> a
+ Data.Vector.Unboxed.Bit: minimumBy :: Unbox a => (a -> a -> Ordering) -> Vector a -> a
+ Data.Vector.Unboxed.Bit: modify :: Unbox a => (forall s. () => MVector s a -> ST s ()) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: notElem :: (Unbox a, Eq a) => a -> Vector a -> Bool
+ Data.Vector.Unboxed.Bit: null :: Unbox a => Vector a -> Bool
+ Data.Vector.Unboxed.Bit: partition :: Unbox a => (a -> Bool) -> Vector a -> (Vector a, Vector a)
+ Data.Vector.Unboxed.Bit: postscanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: postscanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: postscanr :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: postscanr' :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: prescanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: prescanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: prescanr :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: prescanr' :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: product :: (Unbox a, Num a) => Vector a -> a
+ Data.Vector.Unboxed.Bit: replicate :: Unbox a => Int -> a -> Vector a
+ Data.Vector.Unboxed.Bit: replicateM :: (Monad m, Unbox a) => Int -> m a -> m (Vector a)
+ Data.Vector.Unboxed.Bit: scanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: scanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: scanl1 :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: scanl1' :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: scanr :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: scanr' :: (Unbox a, Unbox b) => (a -> b -> b) -> b -> Vector a -> Vector b
+ Data.Vector.Unboxed.Bit: scanr1 :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: scanr1' :: Unbox a => (a -> a -> a) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: singleton :: Unbox a => a -> Vector a
+ Data.Vector.Unboxed.Bit: slice :: Unbox a => Int -> Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: snoc :: Unbox a => Vector a -> a -> Vector a
+ Data.Vector.Unboxed.Bit: span :: Unbox a => (a -> Bool) -> Vector a -> (Vector a, Vector a)
+ Data.Vector.Unboxed.Bit: splitAt :: Unbox a => Int -> Vector a -> (Vector a, Vector a)
+ Data.Vector.Unboxed.Bit: sum :: (Unbox a, Num a) => Vector a -> a
+ Data.Vector.Unboxed.Bit: tail :: Unbox a => Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: take :: Unbox a => Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: takeWhile :: Unbox a => (a -> Bool) -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: thaw :: (Unbox a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Bit: toList :: Unbox a => Vector a -> [a]
+ Data.Vector.Unboxed.Bit: unfoldr :: Unbox a => (b -> Maybe (a, b)) -> b -> Vector a
+ Data.Vector.Unboxed.Bit: unfoldrM :: (Monad m, Unbox a) => (b -> m (Maybe (a, b))) -> b -> m (Vector a)
+ Data.Vector.Unboxed.Bit: unfoldrN :: Unbox a => Int -> (b -> Maybe (a, b)) -> b -> Vector a
+ Data.Vector.Unboxed.Bit: unfoldrNM :: (Monad m, Unbox a) => Int -> (b -> m (Maybe (a, b))) -> b -> m (Vector a)
+ Data.Vector.Unboxed.Bit: uniq :: (Unbox a, Eq a) => Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeAccum :: Unbox a => (a -> b -> a) -> Vector a -> [(Int, b)] -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeAccumulate :: (Unbox a, Unbox b) => (a -> b -> a) -> Vector a -> Vector (Int, b) -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeAccumulate_ :: (Unbox a, Unbox b) => (a -> b -> a) -> Vector a -> Vector Int -> Vector b -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeBackpermute :: Unbox a => Vector a -> Vector Int -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeCopy :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> Vector a -> m ()
+ Data.Vector.Unboxed.Bit: unsafeDrop :: Unbox a => Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeFreeze :: (Unbox a, PrimMonad m) => MVector (PrimState m) a -> m (Vector a)
+ Data.Vector.Unboxed.Bit: unsafeHead :: Unbox a => Vector a -> a
+ Data.Vector.Unboxed.Bit: unsafeHeadM :: (Unbox a, Monad m) => Vector a -> m a
+ Data.Vector.Unboxed.Bit: unsafeIndex :: Unbox a => Vector a -> Int -> a
+ Data.Vector.Unboxed.Bit: unsafeIndexM :: (Unbox a, Monad m) => Vector a -> Int -> m a
+ Data.Vector.Unboxed.Bit: unsafeInit :: Unbox a => Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeLast :: Unbox a => Vector a -> a
+ Data.Vector.Unboxed.Bit: unsafeLastM :: (Unbox a, Monad m) => Vector a -> m a
+ Data.Vector.Unboxed.Bit: unsafeSlice :: Unbox a => Int -> Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeTail :: Unbox a => Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeTake :: Unbox a => Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeThaw :: (Unbox a, PrimMonad m) => Vector a -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Bit: unsafeUpd :: Unbox a => Vector a -> [(Int, a)] -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeUpdate :: Unbox a => Vector a -> Vector (Int, a) -> Vector a
+ Data.Vector.Unboxed.Bit: unsafeUpdate_ :: Unbox a => Vector a -> Vector Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: unstablePartition :: Unbox a => (a -> Bool) -> Vector a -> (Vector a, Vector a)
+ Data.Vector.Unboxed.Bit: unzip :: (Unbox a, Unbox b) => Vector (a, b) -> (Vector a, Vector b)
+ Data.Vector.Unboxed.Bit: unzip3 :: (Unbox a, Unbox b, Unbox c) => Vector (a, b, c) -> (Vector a, Vector b, Vector c)
+ Data.Vector.Unboxed.Bit: unzip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => Vector (a, b, c, d) -> (Vector a, Vector b, Vector c, Vector d)
+ Data.Vector.Unboxed.Bit: unzip5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => Vector (a, b, c, d, e) -> (Vector a, Vector b, Vector c, Vector d, Vector e)
+ Data.Vector.Unboxed.Bit: unzip6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => Vector (a, b, c, d, e, f) -> (Vector a, Vector b, Vector c, Vector d, Vector e, Vector f)
+ Data.Vector.Unboxed.Bit: update :: Unbox a => Vector a -> Vector (Int, a) -> Vector a
+ Data.Vector.Unboxed.Bit: update_ :: Unbox a => Vector a -> Vector Int -> Vector a -> Vector a
+ Data.Vector.Unboxed.Bit: zip :: (Unbox a, Unbox b) => Vector a -> Vector b -> Vector (a, b)
+ Data.Vector.Unboxed.Bit: zip3 :: (Unbox a, Unbox b, Unbox c) => Vector a -> Vector b -> Vector c -> Vector (a, b, c)
+ Data.Vector.Unboxed.Bit: zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => Vector a -> Vector b -> Vector c -> Vector d -> Vector (a, b, c, d)
+ Data.Vector.Unboxed.Bit: zip5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector (a, b, c, d, e)
+ Data.Vector.Unboxed.Bit: zip6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f -> Vector (a, b, c, d, e, f)
+ Data.Vector.Unboxed.Bit: zipWith :: (Unbox a, Unbox b, Unbox c) => (a -> b -> c) -> Vector a -> Vector b -> Vector c
+ Data.Vector.Unboxed.Bit: zipWith3 :: (Unbox a, Unbox b, Unbox c, Unbox d) => (a -> b -> c -> d) -> Vector a -> Vector b -> Vector c -> Vector d
+ Data.Vector.Unboxed.Bit: zipWith4 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => (a -> b -> c -> d -> e) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e
+ Data.Vector.Unboxed.Bit: zipWith5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => (a -> b -> c -> d -> e -> f) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f
+ Data.Vector.Unboxed.Bit: zipWith6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f, Unbox g) => (a -> b -> c -> d -> e -> f -> g) -> Vector a -> Vector b -> Vector c -> Vector d -> Vector e -> Vector f -> Vector g
+ Data.Vector.Unboxed.Bit: zipWithM :: (Monad m, Unbox a, Unbox b, Unbox c) => (a -> b -> m c) -> Vector a -> Vector b -> m (Vector c)
+ Data.Vector.Unboxed.Bit: zipWithM_ :: (Monad m, Unbox a, Unbox b) => (a -> b -> m c) -> Vector a -> Vector b -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: class (Vector Vector a, MVector MVector a) => Unbox a
+ Data.Vector.Unboxed.Mutable.Bit: clear :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: clone :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: copy :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: data family Vector a :: Type
+ Data.Vector.Unboxed.Mutable.Bit: drop :: Unbox a => Int -> MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: grow :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: init :: Unbox a => MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: length :: Unbox a => MVector s a -> Int
+ Data.Vector.Unboxed.Mutable.Bit: modify :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> (a -> a) -> Int -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: move :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: new :: (PrimMonad m, Unbox a) => Int -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: nextPermutation :: (PrimMonad m, Ord e, Unbox e) => MVector (PrimState m) e -> m Bool
+ Data.Vector.Unboxed.Mutable.Bit: null :: Unbox a => MVector s a -> Bool
+ Data.Vector.Unboxed.Mutable.Bit: overlaps :: Unbox a => MVector s a -> MVector s a -> Bool
+ Data.Vector.Unboxed.Mutable.Bit: read :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m a
+ Data.Vector.Unboxed.Mutable.Bit: replicate :: (PrimMonad m, Unbox a) => Int -> a -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: replicateM :: (PrimMonad m, Unbox a) => Int -> m a -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: set :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: slice :: Unbox a => Int -> Int -> MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: splitAt :: Unbox a => Int -> MVector s a -> (MVector s a, MVector s a)
+ Data.Vector.Unboxed.Mutable.Bit: swap :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> Int -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: tail :: Unbox a => MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: take :: Unbox a => Int -> MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: type IOVector = MVector RealWorld
+ Data.Vector.Unboxed.Mutable.Bit: type STVector s = MVector s
+ Data.Vector.Unboxed.Mutable.Bit: unsafeCopy :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: unsafeDrop :: Unbox a => Int -> MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: unsafeGrow :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: unsafeInit :: Unbox a => MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: unsafeModify :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> (a -> a) -> Int -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: unsafeMove :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> MVector (PrimState m) a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: unsafeNew :: (PrimMonad m, Unbox a) => Int -> m (MVector (PrimState m) a)
+ Data.Vector.Unboxed.Mutable.Bit: unsafeRead :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> m a
+ Data.Vector.Unboxed.Mutable.Bit: unsafeSlice :: Unbox a => Int -> Int -> MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: unsafeSwap :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> Int -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: unsafeTail :: Unbox a => MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: unsafeTake :: Unbox a => Int -> MVector s a -> MVector s a
+ Data.Vector.Unboxed.Mutable.Bit: unsafeWrite :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: unzip :: (Unbox a, Unbox b) => MVector s (a, b) -> (MVector s a, MVector s b)
+ Data.Vector.Unboxed.Mutable.Bit: unzip3 :: (Unbox a, Unbox b, Unbox c) => MVector s (a, b, c) -> (MVector s a, MVector s b, MVector s c)
+ Data.Vector.Unboxed.Mutable.Bit: unzip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => MVector s (a, b, c, d) -> (MVector s a, MVector s b, MVector s c, MVector s d)
+ Data.Vector.Unboxed.Mutable.Bit: unzip5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => MVector s (a, b, c, d, e) -> (MVector s a, MVector s b, MVector s c, MVector s d, MVector s e)
+ Data.Vector.Unboxed.Mutable.Bit: unzip6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => MVector s (a, b, c, d, e, f) -> (MVector s a, MVector s b, MVector s c, MVector s d, MVector s e, MVector s f)
+ Data.Vector.Unboxed.Mutable.Bit: write :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> Int -> a -> m ()
+ Data.Vector.Unboxed.Mutable.Bit: zip :: (Unbox a, Unbox b) => MVector s a -> MVector s b -> MVector s (a, b)
+ Data.Vector.Unboxed.Mutable.Bit: zip3 :: (Unbox a, Unbox b, Unbox c) => MVector s a -> MVector s b -> MVector s c -> MVector s (a, b, c)
+ Data.Vector.Unboxed.Mutable.Bit: zip4 :: (Unbox a, Unbox b, Unbox c, Unbox d) => MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s (a, b, c, d)
+ Data.Vector.Unboxed.Mutable.Bit: zip5 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e) => MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s e -> MVector s (a, b, c, d, e)
+ Data.Vector.Unboxed.Mutable.Bit: zip6 :: (Unbox a, Unbox b, Unbox c, Unbox d, Unbox e, Unbox f) => MVector s a -> MVector s b -> MVector s c -> MVector s d -> MVector s e -> MVector s f -> MVector s (a, b, c, d, e, f)
- Data.Vector.Unboxed.Bit: all :: Num t => (t -> Bool) -> Vector Bit -> Bool
+ Data.Vector.Unboxed.Bit: all :: (Bit -> Bool) -> Vector Bit -> Bool
- Data.Vector.Unboxed.Bit: any :: Num t => (t -> Bool) -> Vector Bit -> Bool
+ Data.Vector.Unboxed.Bit: any :: (Bit -> Bool) -> Vector Bit -> Bool
- Data.Vector.Unboxed.Bit: findIndex :: Num t => (t -> Bool) -> Vector Bit -> Maybe Int
+ Data.Vector.Unboxed.Bit: findIndex :: (Bit -> Bool) -> Vector Bit -> Maybe Int
Files
- bitvec.cabal +64/−66
- src/Data/Bit.hs +22/−18
- src/Data/Bit/Internal.hs +38/−18
- src/Data/Vector/Unboxed/Bit.hs +46/−36
- src/Data/Vector/Unboxed/Bit/Internal.hs +141/−36
- src/Data/Vector/Unboxed/Mutable/Bit.hs +28/−28
- test/Main.hs +2/−1
- test/Support.hs +13/−10
- test/Tests/Bit.hs +11/−4
- test/Tests/MVector.hs +167/−14
- test/Tests/SetOps.hs +6/−6
- test/Tests/Vector.hs +5/−5
bitvec.cabal view
@@ -1,71 +1,69 @@-name: bitvec-version: 0.1.0.2-stability: experimental--cabal-version: >= 1.9.2-build-type: Simple--author: James Cook <mokus@deepbondi.net>-maintainer: James Cook <mokus@deepbondi.net>-license: PublicDomain-license-file: LICENSE-homepage: https://github.com/mokus0/bitvec--category: Data, Bit Vectors-synopsis: Unboxed vectors of bits / dense IntSets-description: Another bit-array library for Haskell. This one defines a `Bit` - type (which is an instance of all the "expected" classes, including- numeric ones) and makes that type an instance of `Data.Vector.Unboxed.- Unbox`, so we get a lot of nice APIs for free. `Bool` is already an- unboxable type, but the current unboxed `Vector` implementation packs- each bit as a byte. This one packs 8 bits per byte, as expected- (`UArray` from the `array` package also uses one bit per `Bool`).- .- In addition to the `Vector` interface, there are several high-level- operations and some low-level ones suitable for building new bulk- operations by viewing the bit-vector as a word vector.--tested-with: GHC == 7.0.4,- GHC == 7.2.2,- GHC == 7.4.2,- GHC == 7.6.3,- GHC == 7.8.4,- GHC == 7.10.1,- GHC == 7.11+name: bitvec+version: 0.1.1.0+cabal-version: >=1.10+build-type: Simple+license: PublicDomain+license-file: LICENSE+maintainer: Andrew Lelechenko <andrew.lelechenko@gmail.com>+homepage: https://github.com/Bodigrim/bitvec+synopsis: Unboxed vectors of bits / dense IntSets+description:+ Another bit-array library for Haskell. This one defines a `Bit`+ type (which is an instance of all the "expected" classes, including+ numeric ones) and makes that type an instance of `Data.Vector.Unboxed.+ Unbox`, so we get a lot of nice APIs for free. `Bool` is already an+ unboxable type, but the current unboxed `Vector` implementation packs+ each bit as a byte. This one packs 8 bits per byte, as expected+ (`UArray` from the `array` package also uses one bit per `Bool`).+ .+ In addition to the `Vector` interface, there are several high-level+ operations and some low-level ones suitable for building new bulk+ operations by viewing the bit-vector as a word vector.+category: Data, Bit Vectors+author: James Cook <mokus@deepbondi.net>,+ Andrew Lelechenko <andrew.lelechenko@gmail.com>+tested-with: GHC ==8.0.2 GHC ==8.2.2 GHC ==8.4.3 GHC ==8.6.3 source-repository head type: git- location: git://github.com/mokus0/bitvec.git+ location: git://github.com/Bodigrim/bitvec.git -Test-Suite bitvec-tests- type: exitcode-stdio-1.0- hs-source-dirs: src test- ghc-options: -threaded -fwarn-unused-imports -fwarn-unused-binds- main-is: Main.hs- other-modules: Support- Tests.Bit- Tests.MVector- Tests.SetOps- Tests.Vector- build-depends: base >= 3,- HUnit,- primitive,- vector >= 0.8,- test-framework,- test-framework-hunit,- test-framework-quickcheck2,- QuickCheck+library+ exposed-modules:+ Data.Bit+ Data.Vector.Unboxed.Bit+ Data.Vector.Unboxed.Mutable.Bit+ build-depends:+ base >=3 && <5,+ primitive -any,+ vector >=0.8+ default-language: Haskell2010+ hs-source-dirs: src+ other-modules:+ Data.Bit.Internal+ Data.Vector.Unboxed.Bit.Internal+ ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-type-defaults -Library- hs-source-dirs: src- ghc-options: -fwarn-unused-imports -fwarn-unused-binds -fwarn-type-defaults- exposed-modules: Data.Bit- Data.Vector.Unboxed.Bit- Data.Vector.Unboxed.Mutable.Bit- other-modules: Data.Bit.Internal- Data.Vector.Unboxed.Bit.Internal- build-depends: base >= 3 && < 5,- primitive,- vector >= 0.8- if impl(ghc == 7.2.1)- ghc-options: -trust vector +test-suite bitvec-tests+ type: exitcode-stdio-1.0+ main-is: Main.hs+ build-depends:+ base >=3,+ bitvec -any,+ HUnit -any,+ primitive -any,+ vector >=0.8,+ test-framework -any,+ test-framework-hunit -any,+ test-framework-quickcheck2 -any,+ QuickCheck >=2.10,+ quickcheck-classes >=0.6.1+ default-language: Haskell2010+ hs-source-dirs: test+ other-modules:+ Support+ Tests.Bit+ Tests.MVector+ Tests.SetOps+ Tests.Vector+ ghc-options: -threaded -fwarn-unused-imports -fwarn-unused-binds
src/Data/Bit.hs view
@@ -4,6 +4,9 @@ #else #define safe #endif++{-# OPTIONS_GHC -fno-warn-orphans #-}+ module Data.Bit ( Bit , fromBool@@ -28,8 +31,8 @@ liftInt2 :: (Int -> Int -> Int) -> (Bit -> Bit -> Bit) liftInt2 op x y = fromIntegral (fromIntegral x `op` fromIntegral y) --- | The 'Num' instance is currently based on integers mod 2, so (+) and (-) are --- XOR, (*) is AND, and all the unary operations are identities. Saturating +-- | The 'Num' instance is currently based on integers mod 2, so (+) and (-) are+-- XOR, (*) is AND, and all the unary operations are identities. Saturating -- operations would also be a sensible alternative. instance Num Bit where fromInteger = fromBool . odd@@ -44,9 +47,9 @@ toRational (Bit True ) = 1 instance Integral Bit where- quotRem _ 0 = error "divide by zero"- quotRem x 1 = (x, 0)- + quotRem _ (Bit False) = error "divide by zero"+ quotRem x (Bit True ) = (x, 0)+ divMod = quotRem toInteger (Bit False) = 0 toInteger (Bit True ) = 1@@ -55,33 +58,34 @@ (.&.) = liftBool2 (&&) (.|.) = liftBool2 (||) xor = liftBool2 (/=)- + complement (Bit x) = Bit (not x)- + shift b 0 = b- shift b _ = 0- + shift _ _ = 0+ rotate = const- + bit 0 = 1 bit _ = 0- + setBit _ 0 = 1 setBit b _ = b- + clearBit _ 0 = 0 clearBit b _ = b- + complementBit b 0 = complement b complementBit b _ = b- + testBit b 0 = toBool b testBit _ _ = False- - bitSize _ = 1- ++ bitSizeMaybe _ = Just 1+ bitSize _ = 1+ isSigned _ = False- + #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ >= 704 popCount = fromEnum
src/Data/Bit/Internal.hs view
@@ -11,7 +11,6 @@ import safe Data.Bits import safe Data.List import safe Data.Typeable-import safe Data.Word #if !MIN_VERSION_base(4,3,0) import safe Control.Monad@@ -22,11 +21,11 @@ #endif -newtype Bit = Bit Bool+newtype Bit = Bit { toBool :: Bool } deriving (Bounded, Eq, Ord, Typeable) -fromBool b = Bit b-toBool (Bit b) = b+fromBool :: Bool -> Bit+fromBool b = Bit b instance Enum Bit where toEnum = fromBool . toEnum@@ -41,37 +40,53 @@ -- |The number of 'Bit's in a 'Word'. A handy constant to have around when defining 'Word'-based bulk operations on bit vectors. wordSize :: Int-wordSize = bitSize (0 :: Word)+wordSize = finiteBitSize (0 :: Word) lgWordSize, wordSizeMask, wordSizeMaskC :: Int-lgWordSize = lg2 wordSize+lgWordSize = case wordSize of+ 32 -> 5+ 64 -> 6+ _ -> lg2 wordSize+ wordSizeMask = wordSize - 1 wordSizeMaskC = complement wordSizeMask +divWordSize :: Bits a => a -> a divWordSize x = shiftR x lgWordSize++modWordSize :: Int -> Int modWordSize x = x .&. (wordSize - 1) +mulWordSize :: Bits a => a -> a mulWordSize x = shiftL x lgWordSize -- number of words needed to store n bits-nWords nBits = divWordSize (nBits + wordSize - 1)+nWords :: Int -> Int+nWords ns = divWordSize (ns + wordSize - 1) -- number of bits storable in n words-nBits nWords = mulWordSize nWords+nBits :: Bits a => a -> a+nBits ns = mulWordSize ns +aligned :: Int -> Bool aligned x = (x .&. wordSizeMask == 0)++notAligned :: Int -> Bool notAligned x = x /= alignDown x -- round a number of bits up to the nearest multiple of word size+alignUp :: Int -> Int alignUp x | x == x' = x' | otherwise = x' + wordSize where x' = alignDown x+ -- round a number of bits down to the nearest multiple of word size+alignDown :: Int -> Int alignDown x = x .&. wordSizeMaskC readBit :: Int -> Word -> Bit-readBit i w = fromBool (testBit w i)+readBit i w = fromBool (w .&. (1 `unsafeShiftL` i) /= 0) extendToWord :: Bit -> Word extendToWord (Bit False) = 0@@ -81,14 +96,18 @@ mask :: Int -> Word mask b = m where- m | b >= bitSize m = complement 0- | b < 0 = 0- | otherwise = bit b - 1+ m | b >= finiteBitSize m = complement 0+ | b < 0 = 0+ | otherwise = bit b - 1 +masked :: Int -> Word -> Word masked b x = x .&. mask b++isMasked :: Int -> Word -> Bool isMasked b x = (masked b x == x) -- meld 2 words by taking the low 'b' bits from 'lo' and the rest from 'hi'+meld :: Int -> Word -> Word -> Word meld b lo hi = (lo .&. m) .|. (hi .&. complement m) where m = mask b @@ -107,17 +126,17 @@ -- this could be given a more general type, but it would be wrong; it works for any fixed word size, but only for unsigned types reverseWord :: Word -> Word-reverseWord x = foldr swap x masks+reverseWord xx = foldr swap xx masks where nextMask (d, x) = (d', x `xor` shift x d') where !d' = d `shiftR` 1- - !(_:masks) = ++ !(_:masks) = takeWhile ((0 /=) . snd)- (iterate nextMask (bitSize x, maxBound))- + (iterate nextMask (finiteBitSize xx, maxBound))+ swap (n, m) x = ((x .&. m) `shiftL` n) .|. ((x .&. complement m) `shiftR` n)- + -- TODO: is an unrolled version like "loop lgWordSize" faster than the generic implementation above? If so, can that be fixed? -- loop 0 x = x -- loop 1 x = loop 0 (((x .&. 0x5555555555555555) `shiftL` 1) .|. ((x .&. 0xAAAAAAAAAAAAAAAA) `shiftR` 1))@@ -128,6 +147,7 @@ -- loop 6 x = loop 5 (((x .&. 0x00000000FFFFFFFF) `shiftL` 32) .|. ((x .&. 0xFFFFFFFF00000000) `shiftR` 32)) -- loop _ _ = error "reverseWord only implemented for up to 64 bit words!" +reversePartialWord :: Int -> Word -> Word reversePartialWord n w | n >= wordSize = reverseWord w | otherwise = reverseWord w `shiftR` (wordSize - n)
src/Data/Vector/Unboxed/Bit.hs view
@@ -9,47 +9,47 @@ module Data.Vector.Unboxed.Bit ( module Data.Bit , module U- + , wordSize , wordLength , fromWords , toWords , indexWord- + , pad , padWith- + , zipWords- + , union , unions- + , intersection , intersections , difference , symDiff- + , invert- + , select , selectBits- + , exclude , excludeBits- + , countBits , listBits- + , and , or- + , any , anyBits , all , allBits- + , reverse- + , first , findIndex ) where@@ -79,7 +79,7 @@ fromWords n ws | n <= m = BitVec 0 n (V.take (nWords n) ws) | otherwise = pad n (BitVec 0 m ws)- where + where m = nBits (V.length ws) -- |Given a vector of bits, extract an unboxed vector of words. If the bits don't completely fill the words, the last word will be zero-padded.@@ -97,9 +97,9 @@ zipWords (flip op) ys xs | otherwise = runST $ do -- TODO: eliminate this extra traversal- xs <- V.thaw xs- B.zipInPlace op xs ys- Unsafe.unsafeFreeze xs+ xs1 <- V.thaw xs+ B.zipInPlace op xs1 ys+ Unsafe.unsafeFreeze xs1 -- |(internal) N-ary 'zipWords' with specified output length. Makes all kinds of assumptions; mainly only valid for union and intersection. {-# INLINE zipMany #-}@@ -110,11 +110,18 @@ P.mapM_ (B.zipInPlace op ys) xss Unsafe.unsafeFreeze ys -union = zipWords (.|.)+union :: Vector Bit -> Vector Bit -> Vector Bit+union = zipWords (.|.)++intersection :: Vector Bit -> Vector Bit -> Vector Bit intersection = zipWords (.&.)-difference = zipWords diff-symDiff = zipWords xor +difference :: Vector Bit -> Vector Bit -> Vector Bit+difference = zipWords diff++symDiff :: Vector Bit -> Vector Bit -> Vector Bit+symDiff = zipWords xor+ unions :: Int -> [U.Vector Bit] -> U.Vector Bit unions = zipMany 0 (.|.) @@ -130,26 +137,26 @@ Unsafe.unsafeFreeze ys -- | Given a vector of bits and a vector of things, extract those things for which the corresponding bit is set.--- +-- -- For example, @select (V.map (fromBool . p) x) x == V.filter p x@. select :: (V.Vector v1 Bit, V.Vector v2 t) => v1 Bit -> v2 t -> [t] select is xs = L.unfoldr next 0 where n = min (V.length is) (V.length xs)- + next j | j >= n = Nothing | toBool (is V.! j) = Just (xs V.! j, j + 1) | otherwise = next (j + 1) -- | Given a vector of bits and a vector of things, extract those things for which the corresponding bit is unset.--- +-- -- For example, @exclude (V.map (fromBool . p) x) x == V.filter (not . p) x@. exclude :: (V.Vector v1 Bit, V.Vector v2 t) => v1 Bit -> v2 t -> [t] exclude is xs = L.unfoldr next 0 where n = min (V.length is) (V.length xs)- + next j | j >= n = Nothing | toBool (is V.! j) = next (j + 1)@@ -157,15 +164,15 @@ selectBits :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit selectBits is xs = runST $ do- xs <- U.thaw xs- n <- B.selectBitsInPlace is xs- Unsafe.unsafeFreeze (MV.take n xs)+ xs1 <- U.thaw xs+ n <- B.selectBitsInPlace is xs1+ Unsafe.unsafeFreeze (MV.take n xs1) excludeBits :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit excludeBits is xs = runST $ do- xs <- U.thaw xs- n <- B.excludeBitsInPlace is xs- Unsafe.unsafeFreeze (MV.take n xs)+ xs1 <- U.thaw xs+ n <- B.excludeBitsInPlace is xs1+ Unsafe.unsafeFreeze (MV.take n xs1) -- |return the number of ones in a bit vector countBits :: U.Vector Bit -> Int@@ -182,7 +189,7 @@ !n = V.length v loop bs !i | i >= n = bs []- | otherwise = + | otherwise = loop (bs . bitsInWord i (indexWord v i)) (i + wordSize) -- | 'True' if all bits in the vector are set@@ -205,12 +212,14 @@ | otherwise = (indexWord v i /= 0) || loop (i + wordSize) +all :: (Bit -> Bool) -> Vector Bit -> Bool all p = case (p 0, p 1) of (False, False) -> U.null (False, True) -> allBits 1 (True, False) -> allBits 0 (True, True) -> flip seq True +any :: (Bit -> Bool) -> Vector Bit -> Bool any p = case (p 0, p 1) of (False, False) -> flip seq False (False, True) -> anyBits 1@@ -218,11 +227,11 @@ (True, True) -> not . U.null allBits, anyBits :: Bit -> U.Vector Bit -> Bool-allBits 0 = not . or-allBits 1 = and+allBits (Bit False) = not . or+allBits (Bit True) = and -anyBits 0 = not . and-anyBits 1 = or+anyBits (Bit False) = not . and+anyBits (Bit True) = or reverse :: U.Vector Bit -> U.Vector Bit reverse xs = runST $ do@@ -239,11 +248,12 @@ !n = V.length xs !ff | toBool b = ffs | otherwise = ffs . complement- + loop !i | i >= n = Nothing | otherwise = fmap (i +) (ff (indexWord xs i)) `mplus` loop (i + wordSize) +findIndex :: (Bit -> Bool) -> Vector Bit -> Maybe Int findIndex p xs = case (p 0, p 1) of (False, False) -> Nothing (False, True) -> first 1 xs
src/Data/Vector/Unboxed/Bit/Internal.hs view
@@ -2,14 +2,18 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ViewPatterns #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}+ module Data.Vector.Unboxed.Bit.Internal ( Bit , U.Vector(BitVec) , U.MVector(BitMVec)- + , padWith , pad- + , indexWord , readWord , writeWord@@ -24,7 +28,6 @@ import qualified Data.Vector.Generic as V import qualified Data.Vector.Generic.Mutable as MV import qualified Data.Vector.Unboxed as U-import Data.Word -- Ints are offset and length in bits data instance U.MVector s Bit = BitMVec !Int !Int !(U.MVector s Word)@@ -34,7 +37,7 @@ -- | read a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.). If the offset is such that the word extends past the end of the vector, the result is zero-padded. indexWord :: U.Vector Bit -> Int -> Word-indexWord (BitVec 0 n v) i +indexWord (BitVec 0 n v) i | aligned i = masked b lo | j + 1 == nWords n = masked b (extractWord k lo 0 ) | otherwise = masked b (extractWord k lo hi)@@ -63,7 +66,7 @@ -- | write a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.). If the offset is such that the word extends past the end of the vector, the word is truncated and as many low-order bits as possible are written. writeWord :: PrimMonad m => U.MVector (PrimState m) Bit -> Int -> Word -> m () writeWord (BitMVec 0 n v) i x- | aligned i = + | aligned i = if b < wordSize then do y <- MV.read v j@@ -108,68 +111,170 @@ instance U.Unbox Bit +loMask :: Int -> Word+loMask n = 1 `shiftL` n - 1++hiMask :: Int -> Word+hiMask n = complement (1 `shiftL` n - 1)+ instance MV.MVector U.MVector Bit where #if MIN_VERSION_vector(0,11,0)- basicInitialize (BitMVec _ _ v) = MV.basicInitialize v+ {-# INLINE basicInitialize #-}+ basicInitialize (BitMVec _ 0 _) = pure ()+ basicInitialize (BitMVec 0 n v) = case modWordSize n of+ 0 -> MV.basicInitialize v+ nMod -> do+ let vLen = MV.basicLength v+ MV.basicInitialize (MV.slice 0 (vLen - 1) v)+ MV.modify v (\val -> val .&. hiMask nMod) (vLen - 1)+ basicInitialize (BitMVec s n v) = case modWordSize (s + n) of+ 0 -> do+ let vLen = MV.basicLength v+ MV.basicInitialize (MV.slice 1 (vLen - 1) v)+ MV.modify v (\val -> val .&. loMask s) 0+ nMod -> do+ let vLen = MV.basicLength v+ lohiMask = loMask s .|. hiMask nMod+ if vLen == 1+ then MV.modify v (\val -> val .&. lohiMask) 0+ else do+ MV.basicInitialize (MV.slice 1 (vLen - 2) v)+ MV.modify v (\val -> val .&. loMask s) 0+ MV.modify v (\val -> val .&. hiMask nMod) (vLen - 1) #endif- ++ {-# INLINE basicUnsafeNew #-} basicUnsafeNew n = liftM (BitMVec 0 n) (MV.basicUnsafeNew (nWords n))++ {-# INLINE basicUnsafeReplicate #-} basicUnsafeReplicate n x = liftM (BitMVec 0 n) (MV.basicUnsafeReplicate (nWords n) (extendToWord x))- ++ {-# INLINE basicOverlaps #-} basicOverlaps (BitMVec _ _ v1) (BitMVec _ _ v2) = MV.basicOverlaps v1 v2- ++ {-# INLINE basicLength #-} basicLength (BitMVec _ n _) = n- basicUnsafeRead (BitMVec 0 _ v) i = liftM (readBit (modWordSize i)) (MV.basicUnsafeRead v (divWordSize i))- basicUnsafeRead (BitMVec s n v) i = MV.basicUnsafeRead (BitMVec 0 (n + s) v) (i + s)- basicUnsafeWrite (BitMVec 0 _ v) i x = do- let j = divWordSize i; k = modWordSize i++ {-# INLINE basicUnsafeRead #-}+ basicUnsafeRead (BitMVec s _ v) !i' = let i = s + i' in liftM (readBit (modWordSize i)) (MV.basicUnsafeRead v (divWordSize i))++ {-# INLINE basicUnsafeWrite #-}+ basicUnsafeWrite (BitMVec s _ v) !i' !x = do+ let i = s + i'+ let j = divWordSize i; k = modWordSize i; kk = 1 `unsafeShiftL` k w <- MV.basicUnsafeRead v j- MV.basicUnsafeWrite v j $ if toBool x- then setBit w k- else clearBit w k- - basicUnsafeWrite (BitMVec s n v) i x =- MV.basicUnsafeWrite (BitMVec 0 (n + s) v) (i + s) x- basicSet (BitMVec _ _ v) x = MV.basicSet v (extendToWord x)- + when (fromBool (w .&. kk /= 0) /= x) $+ MV.basicUnsafeWrite v j (w `xor` kk)++ {-# INLINE basicClear #-}+ basicClear _ = pure ()++ {-# INLINE basicSet #-}+ basicSet (BitMVec _ 0 _) _ = pure ()+ basicSet (BitMVec 0 n v) (extendToWord -> x) = case modWordSize n of+ 0 -> MV.basicSet v x+ nMod -> do+ let vLen = MV.basicLength v+ MV.basicSet (MV.slice 0 (vLen - 1) v) x+ MV.modify v (\val -> val .&. hiMask nMod .|. x .&. loMask nMod) (vLen - 1)+ basicSet (BitMVec s n v) (extendToWord -> x) = case modWordSize (s + n) of+ 0 -> do+ let vLen = MV.basicLength v+ MV.basicSet (MV.slice 1 (vLen - 1) v) x+ MV.modify v (\val -> val .&. loMask s .|. x .&. hiMask s) 0+ nMod -> do+ let vLen = MV.basicLength v+ lohiMask = loMask s .|. hiMask nMod+ if vLen == 1+ then MV.modify v (\val -> val .&. lohiMask .|. x .&. complement lohiMask) 0+ else do+ MV.basicSet (MV.slice 1 (vLen - 2) v) x+ MV.modify v (\val -> val .&. loMask s .|. x .&. hiMask s) 0+ MV.modify v (\val -> val .&. hiMask nMod .|. x .&. loMask nMod) (vLen - 1)+ {-# INLINE basicUnsafeCopy #-}+ basicUnsafeCopy _ (BitMVec _ 0 _) = pure ()+ basicUnsafeCopy (BitMVec 0 _ dst) (BitMVec 0 n src) = case modWordSize n of+ 0 -> MV.basicUnsafeCopy dst src+ nMod -> do+ let vLen = MV.basicLength src+ MV.basicUnsafeCopy (MV.slice 0 (vLen - 1) dst) (MV.slice 0 (vLen - 1) src)+ valSrc <- MV.basicUnsafeRead src (vLen - 1)+ MV.modify dst (\val -> val .&. hiMask nMod .|. valSrc .&. loMask nMod) (vLen - 1)+ basicUnsafeCopy (BitMVec dstShift _ dst) (BitMVec s n src)+ | dstShift == s = case modWordSize (s + n) of+ 0 -> do+ let vLen = MV.basicLength src+ MV.basicUnsafeCopy (MV.slice 1 (vLen - 1) dst) (MV.slice 1 (vLen - 1) src)+ valSrc <- MV.basicUnsafeRead src 0+ MV.modify dst (\val -> val .&. loMask s .|. valSrc .&. hiMask s) 0+ nMod -> do+ let vLen = MV.basicLength src+ lohiMask = loMask s .|. hiMask nMod+ if vLen == 1+ then do+ valSrc <- MV.basicUnsafeRead src 0+ MV.modify dst (\val -> val .&. lohiMask .|. valSrc .&. complement lohiMask) 0+ else do+ MV.basicUnsafeCopy (MV.slice 1 (vLen - 2) dst) (MV.slice 1 (vLen - 2) src)+ valSrcFirst <- MV.basicUnsafeRead src 0+ MV.modify dst (\val -> val .&. loMask s .|. valSrcFirst .&. hiMask s) 0+ valSrcLast <- MV.basicUnsafeRead src (vLen - 1)+ MV.modify dst (\val -> val .&. hiMask nMod .|. valSrcLast .&. loMask nMod) (vLen - 1)+ basicUnsafeCopy dst@(BitMVec _ len _) src = do_copy 0 where n = alignUp len- + do_copy i | i < n = do x <- readWord src i writeWord dst i x do_copy (i+wordSize) | otherwise = return ()- ++ {-# INLINE basicUnsafeMove #-}+ basicUnsafeMove !dst !src@(BitMVec srcShift srcLen _)+ | MV.basicOverlaps dst src = do+ -- Align shifts of src and srcCopy to speed up basicUnsafeCopy srcCopy src+ -- TODO write tests on copy and move inside array+ srcCopy <- BitMVec srcShift srcLen <$> MV.basicUnsafeNew (nWords (srcShift + srcLen))+ MV.basicUnsafeCopy srcCopy src+ MV.basicUnsafeCopy dst srcCopy+ | otherwise = MV.basicUnsafeCopy dst src+ {-# INLINE basicUnsafeSlice #-} basicUnsafeSlice offset n (BitMVec s _ v) = BitMVec relStartBit n (MV.basicUnsafeSlice startWord (endWord - startWord) v)- where + where absStartBit = s + offset relStartBit = modWordSize absStartBit absEndBit = absStartBit + n endWord = nWords absEndBit startWord = divWordSize absStartBit + {-# INLINE basicUnsafeGrow #-}+ basicUnsafeGrow (BitMVec s n v) by =+ BitMVec s (n + by) <$> if delta == 0 then pure v else MV.basicUnsafeGrow v delta+ where+ delta = nWords (s + n + by) - nWords (s + n)++ instance V.Vector U.Vector Bit where basicUnsafeFreeze (BitMVec s n v) = liftM (BitVec s n) (V.basicUnsafeFreeze v) basicUnsafeThaw (BitVec s n v) = liftM (BitMVec s n) (V.basicUnsafeThaw v) basicLength (BitVec _ n _) = n- - basicUnsafeIndexM (BitVec 0 _ v) i = liftM (readBit (modWordSize i)) (V.basicUnsafeIndexM v (divWordSize i))- basicUnsafeIndexM (BitVec s n v) i = V.basicUnsafeIndexM (BitVec 0 (n + s) v) (i + s)- ++ basicUnsafeIndexM (BitVec s _ v) !i' = let i = s + i' in liftM (readBit (modWordSize i)) (V.basicUnsafeIndexM v (divWordSize i))+ basicUnsafeCopy dst src = do- src <- V.basicUnsafeThaw src- MV.basicUnsafeCopy dst src- + src1 <- V.basicUnsafeThaw src+ MV.basicUnsafeCopy dst src1+ {-# INLINE basicUnsafeSlice #-} basicUnsafeSlice offset n (BitVec s _ v) = BitVec relStartBit n (V.basicUnsafeSlice startWord (endWord - startWord) v)- where + where absStartBit = s + offset relStartBit = modWordSize absStartBit absEndBit = absStartBit + n@@ -177,20 +282,20 @@ startWord = divWordSize absStartBit padWith :: Bit -> Int -> U.Vector Bit -> U.Vector Bit-padWith b n' bitvec@(BitVec s n v)+padWith b n' bitvec@(BitVec _ n _) | n' <= n = bitvec | otherwise = runST $ do mv@(BitMVec mvStart _ ws) <- MV.replicate n' b when (mvStart /= 0) (fail "assertion failed: offset /= 0 after MV.new")- + V.copy (MV.basicUnsafeSlice 0 n mv) bitvec- + when (notAligned n) $ do let i = divWordSize n j = modWordSize n x <- MV.read ws i MV.write ws i (meld j x (extendToWord b))- + V.unsafeFreeze mv pad :: Int -> U.Vector Bit -> U.Vector Bit
src/Data/Vector/Unboxed/Mutable/Bit.hs view
@@ -9,21 +9,21 @@ module Data.Vector.Unboxed.Mutable.Bit ( module Data.Bit , module U- + , wordSize , wordLength , cloneFromWords , cloneToWords , readWord , writeWord- + , mapMInPlaceWithIndex , mapInPlaceWithIndex , mapMInPlace , mapInPlace- + , zipInPlace- + , unionInPlace , intersectionInPlace , differenceInPlace@@ -31,18 +31,18 @@ , invertInPlace , selectBitsInPlace , excludeBitsInPlace- + , countBits , listBits- + , and , or- + , any , anyBits , all , allBits- + , reverseInPlace ) where @@ -73,26 +73,26 @@ let wordsNeeded = nWords n wordsGiven = MV.length ws fillNeeded = wordsNeeded - wordsGiven- + v <- MV.new wordsNeeded- + if fillNeeded > 0 then do MV.copy (MV.slice 0 wordsGiven v) ws MV.set (MV.slice wordsGiven fillNeeded v) 0 else do MV.copy v (MV.slice 0 wordsNeeded ws)- + return (BitMVec 0 n v) -- |clone a vector of bits to a new unboxed vector of words. If the bits don't completely fill the words, the last word will be zero-padded. cloneToWords :: PrimMonad m => U.MVector (PrimState m) Bit -> m (U.MVector (PrimState m) Word) cloneToWords v@(BitMVec s n ws) | aligned s = do- ws <- MV.clone (MV.slice (divWordSize s) (nWords n) ws)+ ws1 <- MV.clone (MV.slice (divWordSize s) (nWords n) ws) when (not (aligned n)) $ do- readWord v (alignDown n) >>= MV.write ws (divWordSize n)- return ws+ readWord v (alignDown n) >>= MV.write ws1 (divWordSize n)+ return ws1 | otherwise = cloneWords v -- |Map a function over a bit vector one 'Word' at a time ('wordSize' bits at a time). The function will be passed the bit index (which will always be 'wordSize'-aligned) and the current value of the corresponding word. The returned word will be written back to the vector. If there is a partial word at the end of the vector, it will be zero-padded when passed to the function and truncated when the result is written back to the array.@@ -101,13 +101,13 @@ PrimMonad m => (Int -> Word -> m Word) -> U.MVector (PrimState m) Bit -> m ()-mapMInPlaceWithIndex f xs@(BitMVec 0 n v) = loop 0 0+mapMInPlaceWithIndex f xs@(BitMVec 0 _ v) = loop 0 0 where !n_ = alignDown (MV.length xs) loop !i !j | i >= n_ = when (n_ /= MV.length xs) $ do readWord xs i >>= f i >>= writeWord xs i- + | otherwise = do MV.read v j >>= f i >>= MV.write v j loop (i + wordSize) (j + 1)@@ -147,15 +147,15 @@ -- WARNING: relies on guarantee by mapMInPlaceWithIndex that index will always be aligned! !n = min (MV.length xs) (V.length ys) {-# INLINE g #-}- g !i !x = + g !i !x = let !w = masked (n2 - i) (v V.! divWordSize i) in f x w zipInPlace f xs ys = mapInPlaceWithIndex g (MV.basicUnsafeSlice 0 n xs)- where + where !n = min (MV.length xs) (V.length ys) {-# INLINE g #-}- g !i !x = + g !i !x = let !w = indexWord ys i in f x w @@ -261,11 +261,11 @@ (True, True) -> return . not . MV.null allBits, anyBits :: PrimMonad m => Bit -> U.MVector (PrimState m) Bit -> m Bool-allBits 0 = liftM not . or-allBits 1 = and+allBits (Bit False) = liftM not . or+allBits (Bit True) = and -anyBits 0 = liftM not . and-anyBits 1 = or+anyBits (Bit False) = liftM not . and+anyBits (Bit True) = or reverseInPlace :: PrimMonad m => U.MVector (PrimState m) Bit -> m () reverseInPlace xs = loop 0 (MV.length xs)@@ -274,26 +274,26 @@ | i' <= j' = do x <- readWord xs i y <- readWord xs j'- + writeWord xs i (reverseWord y) writeWord xs j' (reverseWord x)- + loop i' j' | i' < j = do let w = (j - i) `shiftR` 1 k = j - w x <- readWord xs i y <- readWord xs k- + writeWord xs i (meld w (reversePartialWord w y) x) writeWord xs k (meld w (reversePartialWord w x) y)- + loop i' j' | i < j = do let w = j - i x <- readWord xs i writeWord xs i (meld w (reversePartialWord w x) x) | otherwise = return ()- where + where !i' = i + wordSize !j' = j - wordSize
test/Main.hs view
@@ -8,7 +8,8 @@ import Tests.MVector (mvectorTests) import Tests.Vector (vectorTests) -main = defaultMain +main :: IO ()+main = defaultMain [ bitTests , mvectorTests , setOpTests
test/Support.hs view
@@ -1,20 +1,20 @@ {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}+ module Support where -import Control.Applicative import Control.Monad.ST import Data.Bit import Data.Bits-import Data.Word import qualified Data.Vector.Generic as V import qualified Data.Vector.Generic.Mutable as M import qualified Data.Vector.Generic.New as N import qualified Data.Vector.Unboxed as U import Data.Vector.Unboxed.Bit (wordSize) import Test.QuickCheck-import Test.QuickCheck.Function instance Arbitrary Bit where arbitrary = fromBool <$> arbitrary@@ -26,9 +26,6 @@ instance Function Bit where function f = functionMap toBool fromBool f -instance Function Word where- function f = functionMap (fromIntegral :: Word -> Int) fromIntegral f- instance (Arbitrary a, U.Unbox a) => Arbitrary (U.Vector a) where arbitrary = V.new <$> arbitrary @@ -41,7 +38,7 @@ -- this instance is designed to make sure that the arbitrary vectors we work with are not all nicely aligned; we need to deal with cases where the vector is a weird slice of some other vector. instance (V.Vector v a, Arbitrary a) => Arbitrary (N.New v a) where arbitrary = frequency- [ (10, newFromList <$> arbitrary) + [ (10, newFromList <$> arbitrary) , (1, N.drop <$> arbitrary <*> arbitrary) , (1, N.take <$> arbitrary <*> arbitrary) , (1, slice <$> arbitrary <*> arbitrary <*> arbitrary)@@ -50,6 +47,7 @@ let (s', n') = trimSlice s n (M.length v) in M.slice s' n' v +trimSlice :: Integral a => a -> a -> a -> (a, a) trimSlice s n l = (s', n') where s' | l == 0 = 0@@ -57,6 +55,7 @@ n' | s' == 0 = 0 | otherwise = n `mod` (l - s') +sliceList :: Int -> Int -> [a] -> [a] sliceList s n = take n . drop s packBitsToWord :: [Bit] -> (Word, [Bit])@@ -79,25 +78,29 @@ writeWordL xs n w = pre ++ writeWordL post 0 w where (pre, post) = splitAt n xs +prop_writeWordL_preserves_length :: [Bit] -> NonNegative Int -> Word -> Bool prop_writeWordL_preserves_length xs (NonNegative n) w = length (writeWordL xs n w) == length xs +prop_writeWordL_preserves_prefix :: [Bit] -> NonNegative Int -> Word -> Bool prop_writeWordL_preserves_prefix xs (NonNegative n) w = take n (writeWordL xs n w) == take n xs +prop_writeWordL_preserves_suffix :: [Bit] -> NonNegative Int -> Word -> Bool prop_writeWordL_preserves_suffix xs (NonNegative n) w = drop (n + wordSize) (writeWordL xs n w) == drop (n + wordSize) xs -prop_writeWordL_readWordL xs n w =+prop_writeWordL_readWordL :: [Bit] -> Int -> Bool+prop_writeWordL_readWordL xs n = writeWordL xs n (readWordL xs n) == xs -- the opposite is more work to state, but these tests together with the simplicity of the definitions makes me reasonably confident in these as a reference implementation. withNonEmptyMVec :: Eq t => (U.Vector Bit -> t)- -> (forall s. U.MVector s Bit -> ST s t) + -> (forall s. U.MVector s Bit -> ST s t) -> Property withNonEmptyMVec f g = forAll arbitrary $ \xs ->- let xs' = V.new xs + let xs' = V.new xs in not (U.null xs') ==> f xs' == runST (N.run xs >>= g)
test/Tests/Bit.hs view
@@ -2,20 +2,25 @@ import Data.Bit import Data.Bits-import Test.HUnit-import Test.Framework (testGroup)+import Test.HUnit ((@?=))+import Test.Framework (Test, testGroup) import Test.Framework.Providers.HUnit (testCase) import Test.Framework.Providers.QuickCheck2 (testProperty) -b0 = 0 :: Bit-b1 = 1 :: Bit+b0 :: Bit+b0 = 0 +b1 :: Bit+b1 = 1++testOp :: (Eq a, Show a) => String -> (Bit -> a) -> (Bit -> a) -> [Test] testOp opName op rOp = [ testCase (unwords [opName, show x]) (op x @?= rOp x) | x <- [0, 1 :: Bit] ] +testBinop :: (Eq a, Show a) => String -> (Bit -> Bit -> a) -> (Bit -> Bit -> a) -> [Test] testBinop opName op rOp = [ testCase (unwords [show x, opName, show y]) (op x y @?= rOp x y)@@ -23,6 +28,7 @@ , y <- [0, 1 :: Bit] ] +bitTests :: Test bitTests = testGroup "Data.Bit" [ testGroup "basic assertions" [ testCase "toBool 0" (toBool 0 @?= False)@@ -43,4 +49,5 @@ ] ] +prop_fromInteger :: Integer -> Bool prop_fromInteger x = fromInteger x == fromBool (odd x)
test/Tests/MVector.hs view
@@ -5,19 +5,26 @@ import Control.Monad import Control.Monad.ST import Data.Bit+import Data.Proxy import Data.STRef import qualified Data.Vector.Generic as V+import qualified Data.Vector.Generic.Mutable as M (basicInitialize, basicSet) import qualified Data.Vector.Generic.New as N import qualified Data.Vector.Unboxed.Bit as B import qualified Data.Vector.Unboxed.Mutable.Bit as U import qualified Data.Vector.Unboxed.Mutable as M-import Data.Word-import Test.Framework (testGroup)+import Test.Framework (Test, testGroup)+import Test.Framework.Providers.HUnit (testCase) import Test.Framework.Providers.QuickCheck2 (testProperty)+import Test.HUnit (assertEqual)+import Test.QuickCheck+import Test.QuickCheck.Classes +mvectorTests :: Test mvectorTests = testGroup "Data.Vector.Unboxed.Mutable.Bit" [ testGroup "Data.Vector.Unboxed.Mutable functions" [ testProperty "slice" prop_slice_def+ , testProperty "grow" prop_grow_def ] , testProperty "wordLength" prop_wordLength_def , testGroup "Read/write Words"@@ -33,21 +40,167 @@ , testProperty "countBits" prop_countBits_def , testProperty "listBits" prop_listBits_def , testProperty "reverseInPlace" prop_reverseInPlace_def+ , testGroup "MVector laws" $ map (uncurry testProperty) $ lawsProperties $ muvectorLaws (Proxy :: Proxy Bit)+ , testCase "basicInitialize 1" case_write_init_read1+ , testCase "basicInitialize 2" case_write_init_read2+ , testCase "basicInitialize 3" case_write_init_read3+ , testCase "basicInitialize 4" case_write_init_read4+ , testCase "basicSet 1" case_write_set_read1+ , testCase "basicSet 2" case_write_set_read2+ , testCase "basicSet 3" case_write_set_read3+ , testCase "basicSet 4" case_write_set_read4+ , testCase "basicSet 5" case_set_read1+ , testCase "basicSet 6" case_set_read2+ , testCase "basicSet 7" case_set_read3+ , testCase "basicUnsafeCopy1" case_write_copy_read1+ , testCase "basicUnsafeCopy2" case_write_copy_read2+ , testCase "basicUnsafeCopy3" case_write_copy_read3+ , testCase "basicUnsafeCopy4" case_write_copy_read4+ , testCase "basicUnsafeCopy5" case_write_copy_read5 ] +case_write_init_read1 :: IO ()+case_write_init_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 2+ M.write arr 0 (fromBool True)+ M.basicInitialize (M.slice 1 1 arr)+ M.read arr 0++case_write_init_read2 :: IO ()+case_write_init_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 2+ M.write arr 1 (fromBool True)+ M.basicInitialize (M.slice 0 1 arr)+ M.read arr 1++case_write_init_read3 :: IO ()+case_write_init_read3 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do+ arr <- M.new 2+ M.write arr 0 (fromBool True)+ M.write arr 1 (fromBool True)+ M.basicInitialize (M.slice 1 0 arr)+ (,) <$> M.read arr 0 <*> M.read arr 1++case_write_init_read4 :: IO ()+case_write_init_read4 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do+ arr <- M.new 3+ M.write arr 0 (fromBool True)+ M.write arr 2 (fromBool True)+ M.basicInitialize (M.slice 1 1 arr)+ (,) <$> M.read arr 0 <*> M.read arr 2++case_write_set_read1 :: IO ()+case_write_set_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 2+ M.write arr 0 (fromBool True)+ M.basicSet (M.slice 1 1 arr) (fromBool False)+ M.read arr 0++case_write_set_read2 :: IO ()+case_write_set_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 2+ M.write arr 1 (fromBool True)+ M.basicSet (M.slice 0 1 arr) (fromBool False)+ M.read arr 1++case_write_set_read3 :: IO ()+case_write_set_read3 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do+ arr <- M.new 2+ M.write arr 0 (fromBool True)+ M.write arr 1 (fromBool True)+ M.basicSet (M.slice 1 0 arr) (fromBool False)+ (,) <$> M.read arr 0 <*> M.read arr 1++case_write_set_read4 :: IO ()+case_write_set_read4 = assertEqual "should be equal" (fromBool True, fromBool True) $ runST $ do+ arr <- M.new 3+ M.write arr 0 (fromBool True)+ M.write arr 2 (fromBool True)+ M.basicSet (M.slice 1 1 arr) (fromBool False)+ (,) <$> M.read arr 0 <*> M.read arr 2++case_set_read1 :: IO ()+case_set_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 1+ M.basicSet arr (fromBool True)+ M.read arr 0++case_set_read2 :: IO ()+case_set_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 2+ M.basicSet (M.slice 1 1 arr) (fromBool True)+ M.read arr 1++case_set_read3 :: IO ()+case_set_read3 = assertEqual "should be equal" (fromBool True) $ runST $ do+ arr <- M.new 192+ M.basicSet (M.slice 71 121 arr) (fromBool True)+ M.read arr 145++case_write_copy_read1 :: IO ()+case_write_copy_read1 = assertEqual "should be equal" (fromBool True) $ runST $ do+ src <- M.slice 37 28 <$> M.new 65+ M.write src 27 (fromBool True)+ dst <- M.slice 37 28 <$> M.new 65+ M.copy dst src+ M.read dst 27++case_write_copy_read2 :: IO ()+case_write_copy_read2 = assertEqual "should be equal" (fromBool True) $ runST $ do+ src <- M.slice 32 33 <$> M.new 65+ M.write src 0 (fromBool True)+ dst <- M.slice 32 33 <$> M.new 65+ M.copy dst src+ M.read dst 0++case_write_copy_read3 :: IO ()+case_write_copy_read3 = assertEqual "should be equal" (fromBool True) $ runST $ do+ src <- M.slice 1 1 <$> M.new 2+ M.write src 0 (fromBool True)+ dst <- M.slice 1 1 <$> M.new 2+ M.copy dst src+ M.read dst 0++case_write_copy_read4 :: IO ()+case_write_copy_read4 = assertEqual "should be equal" (fromBool True) $ runST $ do+ src <- M.slice 12 52 <$> M.new 64+ M.write src 22 (fromBool True)+ dst <- M.slice 12 52 <$> M.new 64+ M.copy dst src+ M.read dst 22++case_write_copy_read5 :: IO ()+case_write_copy_read5 = assertEqual "should be equal" (fromBool True) $ runST $ do+ src <- M.slice 48 80 <$> M.new 128+ M.write src 46 (fromBool True)+ dst <- M.slice 48 80 <$> M.new 128+ M.copy dst src+ M.read dst 46+ prop_slice_def :: Int -> Int -> N.New U.Vector Bit -> Bool prop_slice_def s n xs = runST $ do let xs' = V.new xs (s', n') = trimSlice s n (V.length xs')- xs <- N.run xs- xs <- V.unsafeFreeze (M.slice s' n' xs)- - return (B.toList xs == sliceList s' n' (B.toList xs'))+ xs1 <- N.run xs+ xs2 <- V.unsafeFreeze (M.slice s' n' xs1) + return (B.toList xs2 == sliceList s' n' (B.toList xs'))++prop_grow_def :: B.Vector Bit -> NonNegative Int -> Bool+prop_grow_def xs (NonNegative m) = runST $ do+ let n = B.length xs+ v0 <- B.thaw xs+ v1 <- M.grow v0 m+ fv0 <- B.freeze v0+ fv1 <- B.freeze v1+ return (fv0 == B.take n fv1)++prop_readWord_def :: Int -> Property prop_readWord_def n = withNonEmptyMVec (\xs -> readWordL (B.toList xs) (n `mod` V.length xs)) (\xs -> U.readWord xs (n `mod` M.length xs)) +prop_writeWord_def :: Int -> Word -> Property prop_writeWord_def n w = withNonEmptyMVec (\xs -> B.fromList $ writeWordL (B.toList xs) (n `mod` V.length xs) w)@@ -60,7 +213,7 @@ == runST (fmap U.length (N.run xs >>= U.cloneToWords)) prop_cloneFromWords_def :: Int -> Int -> N.New U.Vector Word -> Bool-prop_cloneFromWords_def maxN n' ws +prop_cloneFromWords_def maxN n' ws = runST (N.run ws >>= U.cloneFromWords n >>= V.unsafeFreeze) == B.fromWords n (V.new ws) where n = n' `mod` maxN@@ -71,27 +224,27 @@ == B.toWords (V.new xs) prop_mapMInPlaceWithIndex_leftToRight :: N.New U.Vector Bit -> Bool-prop_mapMInPlaceWithIndex_leftToRight xs +prop_mapMInPlaceWithIndex_leftToRight xs = runST $ do x <- newSTRef (-1)- xs <- N.run xs+ xs1 <- N.run xs let f i _ = do j <- readSTRef x writeSTRef x i return (if i > j then maxBound else 0)- U.mapMInPlaceWithIndex f xs- xs <- V.unsafeFreeze xs- return (all toBool (B.toList xs))+ U.mapMInPlaceWithIndex f xs1+ xs2 <- V.unsafeFreeze xs1+ return (all toBool (B.toList xs2)) prop_mapMInPlaceWithIndex_aligned :: N.New U.Vector Bit -> Bool prop_mapMInPlaceWithIndex_aligned xs = runST $ do ok <- newSTRef True- xs <- N.run xs+ xs1 <- N.run xs let aligned i = i `mod` U.wordSize == 0 f i x = do when (not (aligned i)) (writeSTRef ok False) return x- U.mapMInPlaceWithIndex f xs+ U.mapMInPlaceWithIndex f xs1 readSTRef ok prop_countBits_def :: N.New U.Vector Bit -> Bool
test/Tests/SetOps.hs view
@@ -5,27 +5,27 @@ import Data.Bit import Data.Bits import qualified Data.Vector.Unboxed.Bit as U-import Data.Word-import Test.Framework (testGroup)+import Test.Framework (Test, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) +setOpTests :: Test setOpTests = testGroup "Set operations" [ testProperty "union" prop_union_def , testProperty "intersection" prop_intersection_def , testProperty "difference" prop_difference_def , testProperty "symDiff" prop_symDiff_def- + , testProperty "unions" (prop_unions_def 1000) , testProperty "intersections" (prop_unions_def 1000)- + , testProperty "invert" prop_invert_def- + , testProperty "select" prop_select_def , testProperty "exclude" prop_exclude_def , testProperty "selectBits" prop_selectBits_def , testProperty "excludeBits" prop_excludeBits_def- + , testProperty "countBits" prop_countBits_def ]
test/Tests/Vector.hs view
@@ -6,16 +6,16 @@ import Data.Bits import Data.List import qualified Data.Vector.Unboxed.Bit as U-import Data.Word-import Test.Framework (testGroup)+import Test.Framework (Test, testGroup) import Test.Framework.Providers.HUnit (testCase) import Test.Framework.Providers.QuickCheck2 (testProperty)-import Test.HUnit+import Test.HUnit ((@?=)) import Test.QuickCheck import Test.QuickCheck.Function +vectorTests :: Test vectorTests = testGroup "Data.Vector.Unboxed.Bit"- [ testCase "wordSize correct" (U.wordSize @?= bitSize (0 :: Word))+ [ testCase "wordSize correct" (U.wordSize @?= finiteBitSize (0 :: Word)) , testGroup "Data.Vector.Unboxed functions" [ testProperty "toList . fromList == id" prop_toList_fromList , testProperty "fromList . toList == id" prop_fromList_toList@@ -79,7 +79,7 @@ (w, bs') -> w : loop bs' prop_indexWord_def :: Int -> U.Vector Bit -> Property-prop_indexWord_def n xs +prop_indexWord_def n xs = not (U.null xs) ==> readWordL (U.toList xs) n' == U.indexWord xs n'