storablevector 0.2.9.1 → 0.2.10
raw patch · 4 files changed
+66/−26 lines, 4 files
Files
- src/Data/StorableVector.hs +36/−24
- src/Data/StorableVector/Lazy.hs +4/−0
- storablevector.cabal +3/−2
- tests/Test.hs +23/−0
src/Data/StorableVector.hs view
@@ -130,6 +130,7 @@ split, splitWith, tokens,+ sliceVertical, -- ** Joining strings join,@@ -388,14 +389,14 @@ {-# INLINE snoc #-} -- | /O(1)/ Extract the first element of a 'Vector', which must be non-empty.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. head :: (Storable a) => Vector a -> a head = withNonEmptyVector "head" $ \ p s _l -> foreignPeek p s {-# INLINE head #-} -- | /O(1)/ Extract the elements after the head of a 'Vector', which must be non-empty.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. tail :: (Storable a) => Vector a -> Vector a tail = withNonEmptyVector "tail" $ \ p s l -> SV p (s+1) (l-1)@@ -409,14 +410,14 @@ {-# INLINE laxTail #-} -- | /O(1)/ Extract the last element of a 'Vector', which must be finite and non-empty.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. last :: (Storable a) => Vector a -> a last = withNonEmptyVector "last" $ \ p s l -> foreignPeek p (s+l-1) {-# INLINE last #-} -- | /O(1)/ Return all the elements of a 'Vector' except the last one.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. init :: Vector a -> Vector a init = withNonEmptyVector "init" $ \ p s l -> SV p s (l-1)@@ -484,7 +485,6 @@ -- | 'foldl', applied to a binary operator, a starting value (typically -- the left-identity of the operator), and a Vector, reduces the -- 'Vector' using the binary operator, from left to right.--- This function is subject to array fusion. foldl :: (Storable a) => (b -> a -> b) -> b -> Vector a -> b foldl f v xs = foldr (\x k acc -> k (f acc x)) id xs v@@ -586,8 +586,7 @@ -- | 'foldl1' is a variant of 'foldl' that has no starting value -- argument, and thus must be applied to non-empty 'Vector's.--- This function is subject to array fusion.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. foldl1 :: (Storable a) => (a -> a -> a) -> Vector a -> a foldl1 f = switchL@@ -596,7 +595,7 @@ {-# INLINE foldl1 #-} -- | 'foldl1\'' is like 'foldl1', but strict in the accumulator.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. foldl1' :: (Storable a) => (a -> a -> a) -> Vector a -> a foldl1' f = switchL@@ -606,7 +605,7 @@ -- | 'foldr1' is a variant of 'foldr' that has no starting value argument, -- and thus must be applied to non-empty 'Vector's--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. foldr1 :: (Storable a) => (a -> a -> a) -> Vector a -> a foldr1 f = switchR@@ -659,13 +658,13 @@ -- | /O(n)/ 'maximum' returns the maximum value from a 'Vector' -- This function will fuse.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. maximum :: (Storable a, Ord a) => Vector a -> a maximum = foldl1' max -- | /O(n)/ 'minimum' returns the minimum value from a 'Vector' -- This function will fuse.--- An exception will be thrown in the case of an empty 'Vector'.+-- It is a checked error to pass an empty 'Vector'. minimum :: (Storable a, Ord a) => Vector a -> a minimum = foldl1' min @@ -1023,6 +1022,20 @@ | otherwise = (SV x s n, SV x (s+n) (l-n)) {-# INLINE splitAt #-} +{- | 'sliceVertical' @n xs@ divides vector in chunks of size @n@.+Requires time proportionally to length of result list,+i.e. @ceiling (length xs / n)@. -}+sliceVertical :: (Storable a) => Int -> Vector a -> [Vector a]+sliceVertical n =+ List.unfoldr (\x -> toMaybe (not (null x)) (splitAt n x))+{-# INLINE sliceVertical #-}++_sliceVertical :: (Storable a) => Int -> Vector a -> [Vector a]+_sliceVertical n xs =+ List.map (take n . flip drop xs) $+ List.takeWhile (< length xs) $ List.iterate (n+) 0++ -- | 'takeWhile', applied to a predicate @p@ and a 'Vector' @xs@, -- returns the longest prefix (possibly empty) of @xs@ of elements that -- satisfy @p@.@@ -1253,8 +1266,7 @@ {-# INLINE notElem #-} -- | /O(n)/ 'filter', applied to a predicate and a 'Vector',--- returns a 'Vector' containing those elements that satisfy the--- predicate. This function is subject to array fusion.+-- returns a 'Vector' containing those elements that satisfy the predicate. filter :: (Storable a) => (a -> Bool) -> Vector a -> Vector a filter p (SV fp s l) = let end = s+l@@ -1418,17 +1430,17 @@ then return (ptrs, P.sum ls) else moduleError "interleave" "all input vectors must have the same length") (\(ptrs, totalLength) -> create totalLength $ \p ->- let n = P.length vs- pEnd = advancePtr p totalLength- go = Strict.arguments3 $ \k0 j p0 -> do- poke p0 =<< flip peekElemOff j =<< peekElemOff ptrs k0- let p1 = advancePtr p0 1- k1 = succ k0- when (p1 < pEnd) $- if k1 < n- then go k1 j p1- else go 0 (succ j) p1- in go 0 0 p)+ let len = P.length vs+ go = Strict.arguments1 $ \m ->+ when (m < totalLength) $ do+ {-+ divMod would be more correct,+ but is slower on the architectures I know+ -}+ let (j,k) = P.quotRem m len+ pokeElemOff p m =<< flip peekElemOff j =<< peekElemOff ptrs k+ go $ succ m+ in go 0) {-# INLINE interleave #-}
src/Data/StorableVector/Lazy.hs view
@@ -296,6 +296,10 @@ concat :: (Storable a) => [Vector a] -> Vector a concat = SV . List.concat . List.map chunks +sliceVertical :: (Storable a) => Int -> Vector a -> [Vector a]+sliceVertical n =+ List.unfoldr (\x -> toMaybe (not (null x)) (splitAt n x))+ -- * Transformations
storablevector.cabal view
@@ -1,5 +1,5 @@ Name: storablevector-Version: 0.2.9.1+Version: 0.2.10 Category: Data Synopsis: Fast, packed, strict storable arrays with a list interface like ByteString Description:@@ -48,7 +48,7 @@ Source-Repository this type: darcs location: http://code.haskell.org/storablevector/- tag: 0.2.9.1+ tag: 0.2.10 Library@@ -114,6 +114,7 @@ Build-Depends: storablevector, bytestring >=0.9 && <0.11,+ utility-ht >=0.0.5 && <0.1, QuickCheck >=1 && <3 If flag(splitBase) Build-Depends:
tests/Test.hs view
@@ -1,5 +1,7 @@ import qualified Data.StorableVector as V import qualified Data.ByteString as P+import qualified Data.List.HT as ListHT+import Test.QuickCheck.Modifiers (Positive(Positive), ) import Test.QuickCheck (Property, quickCheck, ) import Test.Utility (V, W, X, P, applyId, applyModel,@@ -40,6 +42,10 @@ prop_spanVP :: (W -> Bool) -> V -> Bool prop_splitVP :: W -> V -> Bool prop_splitAtVP :: X -> V -> Bool+prop_sieveVP :: Positive X -> V -> Bool+prop_sliceVerticalVP :: Positive X -> V -> Bool+prop_deinterleaveVP :: Positive X -> V -> Bool+prop_interleaveVP :: Positive X -> V -> Bool prop_takeVP :: X -> V -> Bool prop_takeWhileVP :: (W -> Bool) -> V -> Bool prop_elemVP :: W -> V -> Bool@@ -114,6 +120,19 @@ prop_scanlVP = V.scanl `eqnotnull3` P.scanl prop_scanrVP = V.scanr `eqnotnull3` P.scanr +prop_sliceVerticalVP (Positive n) =+ V.sliceVertical n `eq1` (ListHT.sliceVertical n :: [W] -> [[W]])++prop_sieveVP (Positive n) =+ V.sieve n `eq1` (ListHT.sieve n :: [W] -> [W])++prop_deinterleaveVP (Positive n) =+ V.deinterleave n `eq1` (ListHT.sliceHorizontal n :: [W] -> [[W]])++prop_interleaveVP (Positive n) xs =+ let xss = ListHT.switchR [] const $ V.sliceVertical n xs+ in V.interleave xss == V.concat (V.transpose xss)+ prop_eqVP = eq2 ((==) :: V -> V -> Bool)@@ -201,6 +220,10 @@ ("elemIndex", quickCheck prop_elemIndexVP) : ("elemIndices", quickCheck prop_elemIndicesVP) : ("concatMap", quickCheck prop_concatMapVP) :+ ("sieve", quickCheck prop_sieveVP) :+ ("sliceVertical", quickCheck prop_sliceVerticalVP) :+ ("deinterleave", quickCheck prop_deinterleaveVP) :+ ("interleave", quickCheck prop_interleaveVP) : []