vector 0.2 → 0.3
raw patch · 17 files changed
+1576/−295 lines, 17 filesdep ~basedep ~ghc
Dependency ranges changed: base, ghc
Files
- Data/Vector.hs +397/−8
- Data/Vector/Fusion/Stream.hs +41/−20
- Data/Vector/Fusion/Stream/Monadic.hs +138/−19
- Data/Vector/Fusion/Util.hs +35/−0
- Data/Vector/IVector.hs +228/−82
- Data/Vector/MVector.hs +13/−6
- Data/Vector/MVector/New.hs +56/−3
- Data/Vector/Mutable.hs +0/−77
- Data/Vector/Mutable/IO.hs +58/−0
- Data/Vector/Mutable/ST.hs +77/−0
- Data/Vector/Unboxed.hs +366/−7
- Data/Vector/Unboxed/Mutable.hs +0/−63
- Data/Vector/Unboxed/Mutable/IO.hs +59/−0
- Data/Vector/Unboxed/Mutable/ST.hs +63/−0
- Data/Vector/Unboxed/Unbox.hs +12/−0
- LICENSE +1/−2
- vector.cabal +32/−8
Data/Vector.hs view
@@ -13,11 +13,57 @@ -- module Data.Vector (- Vector(..), module Data.Vector.IVector+ Vector,++ -- * Length information+ length, null,++ -- * Construction+ empty, singleton, cons, snoc, replicate, (++), copy,++ -- * Accessing individual elements+ (!), head, last, indexM, headM, lastM,++ -- * Subvectors+ slice, init, tail, take, drop,++ -- * Permutations+ accum, (//), update, backpermute, reverse,++ -- * Mapping+ map, concatMap,++ -- * Zipping and unzipping+ zipWith, zipWith3, zip, zip3, unzip, unzip3,++ -- * Filtering+ filter, takeWhile, dropWhile,++ -- * Searching+ elem, notElem, find, findIndex,++ -- * Folding+ foldl, foldl1, foldl', foldl1', foldr, foldr1,++ -- * Specialised folds+ and, or, sum, product, maximum, minimum,++ -- * Unfolding+ unfoldr,++ -- * Scans+ prescanl, prescanl',++ -- * Enumeration+ enumFromTo, enumFromThenTo,++ -- * Conversion to/from lists+ toList, fromList ) where -import Data.Vector.IVector-import qualified Data.Vector.Mutable as Mut+import Data.Vector.IVector ( IVector(..) )+import qualified Data.Vector.IVector as IV+import qualified Data.Vector.Mutable.ST as Mut import Control.Monad.ST ( runST ) @@ -25,10 +71,27 @@ import GHC.Prim ( Array#, unsafeFreezeArray#, indexArray#, (+#) ) import GHC.Base ( Int(..) ) +import Prelude hiding ( length, null,+ replicate, (++),+ head, last,+ init, tail, take, drop, reverse,+ map, concatMap,+ zipWith, zipWith3, zip, zip3, unzip, unzip3,+ filter, takeWhile, dropWhile,+ elem, notElem,+ foldl, foldl1, foldr, foldr1,+ and, or, sum, product, minimum, maximum,+ enumFromTo, enumFromThenTo )++import qualified Prelude+ data Vector a = Vector {-# UNPACK #-} !Int {-# UNPACK #-} !Int (Array# a) +instance Show a => Show (Vector a) where+ show = (Prelude.++ " :: Data.Vector.Vector") . ("fromList " Prelude.++) . show . toList+ instance IVector Vector a where {-# INLINE vnew #-} vnew init = runST (do@@ -42,15 +105,341 @@ {-# INLINE unsafeSlice #-} unsafeSlice (Vector i _ arr#) j n = Vector (i+j) n arr# - {-# INLINE unsafeIndex #-}- unsafeIndex (Vector (I# i#) _ arr#) (I# j#) f- = case indexArray# arr# (i# +# j#) of (# x #) -> f x+ {-# INLINE unsafeIndexM #-}+ unsafeIndexM (Vector (I# i#) _ arr#) (I# j#)+ = case indexArray# arr# (i# +# j#) of (# x #) -> return x instance Eq a => Eq (Vector a) where {-# INLINE (==) #-}- (==) = eq+ (==) = IV.eq instance Ord a => Ord (Vector a) where {-# INLINE compare #-}- compare = cmp+ compare = IV.cmp++-- Length+-- ------++length :: Vector a -> Int+{-# INLINE length #-}+length = IV.length++null :: Vector a -> Bool+{-# INLINE null #-}+null = IV.null++-- Construction+-- ------------++-- | Empty vector+empty :: Vector a+{-# INLINE empty #-}+empty = IV.empty++-- | Vector with exaclty one element+singleton :: a -> Vector a+{-# INLINE singleton #-}+singleton = IV.singleton++-- | Vector of the given length with the given value in each position+replicate :: Int -> a -> Vector a+{-# INLINE replicate #-}+replicate = IV.replicate++-- | Prepend an element+cons :: a -> Vector a -> Vector a+{-# INLINE cons #-}+cons = IV.cons++-- | Append an element+snoc :: Vector a -> a -> Vector a+{-# INLINE snoc #-}+snoc = IV.snoc++infixr 5 +++-- | Concatenate two vectors+(++) :: Vector a -> Vector a -> Vector a+{-# INLINE (++) #-}+(++) = (IV.++)++-- | Create a copy of a vector. Useful when dealing with slices.+copy :: Vector a -> Vector a+{-# INLINE copy #-}+copy = IV.copy++-- Accessing individual elements+-- -----------------------------++-- | Indexing+(!) :: Vector a -> Int -> a+{-# INLINE (!) #-}+(!) = (IV.!)++-- | First element+head :: Vector a -> a+{-# INLINE head #-}+head = IV.head++-- | Last element+last :: Vector a -> a+{-# INLINE last #-}+last = IV.last++-- | Monadic indexing which can be strict in the vector while remaining lazy in+-- the element+indexM :: Monad m => Vector a -> Int -> m a+{-# INLINE indexM #-}+indexM = IV.indexM++headM :: Monad m => Vector a -> m a+{-# INLINE headM #-}+headM = IV.headM++lastM :: Monad m => Vector a -> m a+{-# INLINE lastM #-}+lastM = IV.lastM++-- Subarrays+-- ---------++-- | Yield a part of the vector without copying it. Safer version of+-- 'unsafeSlice'.+slice :: Vector a -> Int -- ^ starting index+ -> Int -- ^ length+ -> Vector a+{-# INLINE slice #-}+slice = IV.slice++-- | Yield all but the last element without copying.+init :: Vector a -> Vector a+{-# INLINE init #-}+init = IV.init++-- | All but the first element (without copying).+tail :: Vector a -> Vector a+{-# INLINE tail #-}+tail = IV.tail++-- | Yield the first @n@ elements without copying.+take :: Int -> Vector a -> Vector a+{-# INLINE take #-}+take = IV.take++-- | Yield all but the first @n@ elements without copying.+drop :: Int -> Vector a -> Vector a+{-# INLINE drop #-}+drop = IV.drop++-- Permutations+-- ------------++accum :: (a -> b -> a) -> Vector a -> [(Int,b)] -> Vector a+{-# INLINE accum #-}+accum = IV.accum++(//) :: Vector a -> [(Int, a)] -> Vector a+{-# INLINE (//) #-}+(//) = (IV.//)++update :: Vector a -> Vector (Int, a) -> Vector a+{-# INLINE update #-}+update = IV.update++backpermute :: Vector a -> Vector Int -> Vector a+{-# INLINE backpermute #-}+backpermute = IV.backpermute++reverse :: Vector a -> Vector a+{-# INLINE reverse #-}+reverse = IV.reverse++-- Mapping+-- -------++-- | Map a function over a vector+map :: (a -> b) -> Vector a -> Vector b+{-# INLINE map #-}+map = IV.map++concatMap :: (a -> Vector b) -> Vector a -> Vector b+{-# INLINE concatMap #-}+concatMap = IV.concatMap++-- Zipping/unzipping+-- -----------------++-- | Zip two vectors with the given function.+zipWith :: (a -> b -> c) -> Vector a -> Vector b -> Vector c+{-# INLINE zipWith #-}+zipWith = IV.zipWith++-- | Zip three vectors with the given function.+zipWith3 :: (a -> b -> c -> d) -> Vector a -> Vector b -> Vector c -> Vector d+{-# INLINE zipWith3 #-}+zipWith3 = IV.zipWith3++zip :: Vector a -> Vector b -> Vector (a, b)+{-# INLINE zip #-}+zip = IV.zip++zip3 :: Vector a -> Vector b -> Vector c -> Vector (a, b, c)+{-# INLINE zip3 #-}+zip3 = IV.zip3++unzip :: Vector (a, b) -> (Vector a, Vector b)+{-# INLINE unzip #-}+unzip = IV.unzip++unzip3 :: Vector (a, b, c) -> (Vector a, Vector b, Vector c)+{-# INLINE unzip3 #-}+unzip3 = IV.unzip3++-- Filtering+-- ---------++-- | Drop elements which do not satisfy the predicate+filter :: (a -> Bool) -> Vector a -> Vector a+{-# INLINE filter #-}+filter = IV.filter++-- | Yield the longest prefix of elements satisfying the predicate.+takeWhile :: (a -> Bool) -> Vector a -> Vector a+{-# INLINE takeWhile #-}+takeWhile = IV.takeWhile++-- | Drop the longest prefix of elements that satisfy the predicate.+dropWhile :: (a -> Bool) -> Vector a -> Vector a+{-# INLINE dropWhile #-}+dropWhile = IV.dropWhile++-- Searching+-- ---------++infix 4 `elem`+-- | Check whether the vector contains an element+elem :: Eq a => a -> Vector a -> Bool+{-# INLINE elem #-}+elem = IV.elem++infix 4 `notElem`+-- | Inverse of `elem`+notElem :: Eq a => a -> Vector a -> Bool+{-# INLINE notElem #-}+notElem = IV.notElem++-- | Yield 'Just' the first element matching the predicate or 'Nothing' if no+-- such element exists.+find :: (a -> Bool) -> Vector a -> Maybe a+{-# INLINE find #-}+find = IV.find++-- | Yield 'Just' the index of the first element matching the predicate or+-- 'Nothing' if no such element exists.+findIndex :: (a -> Bool) -> Vector a -> Maybe Int+{-# INLINE findIndex #-}+findIndex = IV.findIndex++-- Folding+-- -------++-- | Left fold+foldl :: (a -> b -> a) -> a -> Vector b -> a+{-# INLINE foldl #-}+foldl = IV.foldl++-- | Lefgt fold on non-empty vectors+foldl1 :: (a -> a -> a) -> Vector a -> a+{-# INLINE foldl1 #-}+foldl1 = IV.foldl1++-- | Left fold with strict accumulator+foldl' :: (a -> b -> a) -> a -> Vector b -> a+{-# INLINE foldl' #-}+foldl' = IV.foldl'++-- | Left fold on non-empty vectors with strict accumulator+foldl1' :: (a -> a -> a) -> Vector a -> a+{-# INLINE foldl1' #-}+foldl1' = IV.foldl1'++-- | Right fold+foldr :: (a -> b -> b) -> b -> Vector a -> b+{-# INLINE foldr #-}+foldr = IV.foldr++-- | Right fold on non-empty vectors+foldr1 :: (a -> a -> a) -> Vector a -> a+{-# INLINE foldr1 #-}+foldr1 = IV.foldr1++-- Specialised folds+-- -----------------++and :: Vector Bool -> Bool+{-# INLINE and #-}+and = IV.and++or :: Vector Bool -> Bool+{-# INLINE or #-}+or = IV.or++sum :: Num a => Vector a -> a+{-# INLINE sum #-}+sum = IV.sum++product :: Num a => Vector a -> a+{-# INLINE product #-}+product = IV.product++maximum :: Ord a => Vector a -> a+{-# INLINE maximum #-}+maximum = IV.maximum++minimum :: Ord a => Vector a -> a+{-# INLINE minimum #-}+minimum = IV.minimum++-- Unfolding+-- ---------++unfoldr :: (b -> Maybe (a, b)) -> b -> Vector a+{-# INLINE unfoldr #-}+unfoldr = IV.unfoldr++-- Scans+-- -----++-- | Prefix scan+prescanl :: (a -> b -> a) -> a -> Vector b -> Vector a+{-# INLINE prescanl #-}+prescanl = IV.prescanl++-- | Prefix scan with strict accumulator+prescanl' :: (a -> b -> a) -> a -> Vector b -> Vector a+{-# INLINE prescanl' #-}+prescanl' = IV.prescanl'++-- Enumeration+-- -----------++enumFromTo :: Enum a => a -> a -> Vector a+{-# INLINE enumFromTo #-}+enumFromTo = IV.enumFromTo++enumFromThenTo :: Enum a => a -> a -> a -> Vector a+{-# INLINE enumFromThenTo #-}+enumFromThenTo = IV.enumFromThenTo++-- Conversion to/from lists+-- ------------------------++-- | Convert a vector to a list+toList :: Vector a -> [a]+{-# INLINE toList #-}+toList = IV.toList++-- | Convert a list to a vector+fromList :: [a] -> Vector a+{-# INLINE fromList #-}+fromList = IV.fromList
Data/Vector/Fusion/Stream.hs view
@@ -16,7 +16,7 @@ module Data.Vector.Fusion.Stream ( -- * Types- Step(..), Stream, MStream, Id(..),+ Step(..), Stream, MStream, -- * Size hints size, sized,@@ -33,8 +33,11 @@ -- * Substreams extract, init, tail, take, drop, - -- * Mapping and zipping- map, zipWith,+ -- * Mapping+ map, concatMap,+ + -- * Zipping+ zipWith, zipWith3, -- * Filtering filter, takeWhile, dropWhile,@@ -45,8 +48,11 @@ -- * Folding foldl, foldl1, foldl', foldl1', foldr, foldr1, + -- * Specialised folds+ and, or,+ -- * Unfolding- unfold,+ unfoldr, -- * Scans prescanl, prescanl',@@ -59,6 +65,7 @@ ) where import Data.Vector.Fusion.Stream.Size+import Data.Vector.Fusion.Util import Data.Vector.Fusion.Stream.Monadic ( Step(..) ) import qualified Data.Vector.Fusion.Stream.Monadic as M @@ -66,23 +73,14 @@ replicate, (++), head, last, (!!), init, tail, take, drop,- map, zipWith,+ map, concatMap,+ zipWith, zipWith3, filter, takeWhile, dropWhile, elem, notElem, foldl, foldl1, foldr, foldr1,+ and, or, mapM_ ) ---- | Identity monad-newtype Id a = Id { unId :: a }--instance Functor Id where- fmap f (Id x) = Id (f x)--instance Monad Id where- return = Id- Id x >>= f = f x- -- | The type of pure streams type Stream = M.Stream Id @@ -199,7 +197,7 @@ {-# INLINE drop #-} drop = M.drop --- Mapping/zipping+-- Mapping -- --------------- -- | Map a function over a 'Stream'@@ -207,11 +205,23 @@ {-# INLINE map #-} map = M.map +concatMap :: (a -> Stream b) -> Stream a -> Stream b+{-# INLINE concatMap #-}+concatMap = M.concatMap++-- Zipping+-- -------+ -- | Zip two 'Stream's with the given function zipWith :: (a -> b -> c) -> Stream a -> Stream b -> Stream c {-# INLINE zipWith #-} zipWith = M.zipWith +-- | Zip three 'Stream's with the given function+zipWith3 :: (a -> b -> c -> d) -> Stream a -> Stream b -> Stream c -> Stream d+{-# INLINE zipWith3 #-}+zipWith3 = M.zipWith3+ -- Filtering -- --------- @@ -290,13 +300,24 @@ {-# INLINE foldr1 #-} foldr1 f = unId . M.foldr1 f +-- Specialised folds+-- -----------------++and :: Stream Bool -> Bool+{-# INLINE and #-}+and = unId . M.and++or :: Stream Bool -> Bool+{-# INLINE or #-}+or = unId . M.or+ -- Unfolding -- --------- -- | Unfold-unfold :: (s -> Maybe (a, s)) -> s -> Stream a-{-# INLINE unfold #-}-unfold = M.unfold+unfoldr :: (s -> Maybe (a, s)) -> s -> Stream a+{-# INLINE unfoldr #-}+unfoldr = M.unfoldr -- Scans -- -----
Data/Vector/Fusion/Stream/Monadic.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ExistentialQuantification, Rank2Types #-} -- | -- Module : Data.Vector.Fusion.Stream.Monadic@@ -32,8 +32,11 @@ -- * Substreams extract, init, tail, take, drop, - -- * Mapping and zipping- map, mapM, mapM_, zipWith, zipWithM,+ -- * Mapping+ map, mapM, mapM_, trans, concatMap,+ + -- * Zipping+ zipWith, zipWithM, zipWith3, zipWith3M, -- * Filtering filter, filterM, takeWhile, takeWhileM, dropWhile, dropWhileM,@@ -46,8 +49,11 @@ foldl', foldlM', foldl1', foldl1M', foldr, foldrM, foldr1, foldr1M, + -- * Specialised folds+ and, or, concatMapM,+ -- * Unfolding- unfold, unfoldM,+ unfoldr, unfoldrM, -- * Scans prescanl, prescanlM, prescanl', prescanlM',@@ -63,10 +69,12 @@ replicate, (++), head, last, (!!), init, tail, take, drop,- map, mapM, mapM_, zipWith,+ map, mapM, mapM_, concatMap,+ zipWith, zipWith3, filter, takeWhile, dropWhile, elem, notElem,- foldl, foldl1, foldr, foldr1 )+ foldl, foldl1, foldr, foldr1,+ and, or ) import qualified Prelude -- | Result of taking a single step in a stream@@ -193,7 +201,17 @@ -- | Element at the given position (!!) :: Monad m => Stream m a -> Int -> m a {-# INLINE (!!) #-}-s !! i = head (drop i s)+Stream step s _ !! i | i < 0 = errorNegativeIndex "!!"+ | otherwise = loop s i+ where+ loop s i = i `seq`+ do+ r <- step s+ case r of+ Yield x s' | i == 0 -> return x+ | otherwise -> loop s' (i-1)+ Skip s' -> loop s' i+ Done -> errorIndexOutOfRange "!!" -- Substreams -- ----------@@ -215,7 +233,7 @@ case r of Yield x s' -> Skip (Just x, s') Skip s' -> Skip (Nothing, s')- Done -> Done -- FIXME: should be an error+ Done -> errorEmptyStream "init" ) (step s) step' (Just x, s) = liftM (\r -> @@ -235,7 +253,7 @@ case r of Yield x s' -> Skip (Right s') Skip s' -> Skip (Left s')- Done -> Done -- FIXME: should be error?+ Done -> errorEmptyStream "tail" ) (step s) step' (Right s) = liftM (\r ->@@ -281,8 +299,8 @@ ) (step s) --- Mapping/zipping--- ---------------+-- Mapping+-- ------- instance Monad m => Functor (Stream m) where {-# INLINE fmap #-}@@ -318,6 +336,15 @@ Skip s' -> mapM_go s' Done -> return () +-- | Transform a 'Stream' to use a different monad+trans :: (Monad m, Monad m') => (forall a. m a -> m' a)+ -> Stream m a -> Stream m' a+{-# INLINE_STREAM trans #-}+trans f (Stream step s n) = Stream (f . step) s n++-- Zipping+-- -------+ -- | Zip two 'Stream's with the given function zipWith :: Monad m => (a -> b -> c) -> Stream m a -> Stream m b -> Stream m c {-# INLINE zipWith #-}@@ -347,6 +374,39 @@ Skip sb' -> return $ Skip (sa, sb', Just x) Done -> return $ Done +-- | Zip three 'Stream's with the given function+zipWith3 :: Monad m => (a -> b -> c -> d) -> Stream m a -> Stream m b -> Stream m c -> Stream m d+{-# INLINE zipWith3 #-}+zipWith3 f = zipWith3M (\a b c -> return (f a b c))++-- | Zip three 'Stream's with the given monadic function+zipWith3M :: Monad m => (a -> b -> c -> m d) -> Stream m a -> Stream m b -> Stream m c -> Stream m d+{-# INLINE_STREAM zipWith3M #-}+zipWith3M f (Stream stepa sa na) (Stream stepb sb nb) (Stream stepc sc nc)+ = Stream step (sa, sb, sc, Nothing) (smaller na (smaller nb nc))+ where+ {-# INLINE step #-}+ step (sa, sb, sc, Nothing) = do+ r <- stepa sa+ return $ case r of+ Yield x sa' -> Skip (sa', sb, sc, Just (x, Nothing))+ Skip sa' -> Skip (sa', sb, sc, Nothing)+ Done -> Done++ step (sa, sb, sc, Just (x, Nothing)) = do+ r <- stepb sb+ return $ case r of+ Yield y sb' -> Skip (sa, sb', sc, Just (x, Just y))+ Skip sb' -> Skip (sa, sb', sc, Just (x, Nothing))+ Done -> Done++ step (sa, sb, sc, Just (x, Just y)) = do+ r <- stepc sc+ case r of+ Yield z sc' -> f x y z >>= (\res -> return $ Yield res (sa, sb, sc', Nothing))+ Skip sc' -> return $ Skip (sa, sb, sc', Just (x, Just y))+ Done -> return $ Done+ -- Filtering -- --------- @@ -614,18 +674,68 @@ Skip s' -> foldr1M_go1 x s' Done -> return x +-- Specialised folds+-- -----------------++and :: Monad m => Stream m Bool -> m Bool+{-# INLINE_STREAM and #-}+and (Stream step s _) = and_go s+ where+ and_go s = do+ r <- step s+ case r of+ Yield False _ -> return False+ Yield True s' -> and_go s'+ Skip s' -> and_go s'+ Done -> return True++or :: Monad m => Stream m Bool -> m Bool+{-# INLINE_STREAM or #-}+or (Stream step s _) = or_go s+ where+ or_go s = do+ r <- step s+ case r of+ Yield False s' -> or_go s'+ Yield True _ -> return True+ Skip s' -> or_go s'+ Done -> return False++concatMap :: Monad m => (a -> Stream m b) -> Stream m a -> Stream m b+{-# INLINE concatMap #-}+concatMap f = concatMapM (return . f)++concatMapM :: Monad m => (a -> m (Stream m b)) -> Stream m a -> Stream m b+{-# INLINE_STREAM concatMapM #-}+concatMapM f (Stream step s _) = Stream concatMap_go (Left s) Unknown+ where+ concatMap_go (Left s) = do+ r <- step s+ case r of+ Yield a s' -> do+ b_stream <- f a+ return $ Skip (Right (b_stream, s'))+ Skip s' -> return $ Skip (Left s')+ Done -> return Done+ concatMap_go (Right (Stream inner_step inner_s sz, s)) = do+ r <- inner_step inner_s+ case r of+ Yield b inner_s' -> return $ Yield b (Right (Stream inner_step inner_s' sz, s))+ Skip inner_s' -> return $ Skip (Right (Stream inner_step inner_s' sz, s))+ Done -> return $ Skip (Left s)+ -- Unfolding -- --------- -- | Unfold-unfold :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a-{-# INLINE_STREAM unfold #-}-unfold f = unfoldM (return . f)+unfoldr :: Monad m => (s -> Maybe (a, s)) -> s -> Stream m a+{-# INLINE_STREAM unfoldr #-}+unfoldr f = unfoldrM (return . f) -- | Unfold with a monadic function-unfoldM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a-{-# INLINE_STREAM unfoldM #-}-unfoldM f s = Stream step s Unknown+unfoldrM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Stream m a+{-# INLINE_STREAM unfoldrM #-}+unfoldrM f s = Stream step s Unknown where {-# INLINE step #-} step s = liftM (\r ->@@ -695,7 +805,16 @@ step [] = return Done +streamError :: String -> String -> a+streamError fn msg = error $ "Data.Vector.Fusion.Stream.Monadic."+ Prelude.++ fn Prelude.++ ": " Prelude.++ msg+ errorEmptyStream :: String -> a-errorEmptyStream s = error $ "Data.Vector.Fusion.Stream.Monadic."- Prelude.++ s Prelude.++ ": empty stream"+errorEmptyStream fn = streamError fn "empty stream"++errorNegativeIndex :: String -> a+errorNegativeIndex fn = streamError fn "negative index"++errorIndexOutOfRange :: String -> a+errorIndexOutOfRange fn = streamError fn "index out of range"
+ Data/Vector/Fusion/Util.hs view
@@ -0,0 +1,35 @@+-- |+-- Module : Data.Vector.Fusion.Util+-- Copyright : (c) Roman Leshchinskiy 2009+-- License : BSD-style+--+-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>+-- Stability : experimental+-- Portability : portable+-- +-- Fusion-related utility types+--++module Data.Vector.Fusion.Util ( Id(..), Box(..) )+where++-- | Identity monad+newtype Id a = Id { unId :: a }++instance Functor Id where+ fmap f (Id x) = Id (f x)++instance Monad Id where+ return = Id+ Id x >>= f = f x++-- | Box monad+data Box a = Box { unBox :: a }++instance Functor Box where+ fmap f (Box x) = Box (f x)++instance Monad Box where+ return = Box+ Box x >>= f = f x+
Data/Vector/IVector.hs view
@@ -19,38 +19,50 @@ IVector, -- * Length information- length,+ length, null, -- * Construction- empty, singleton, cons, snoc, replicate, (++),+ empty, singleton, cons, snoc, replicate, (++), copy, -- * Accessing individual elements- (!), head, last,+ (!), head, last, indexM, headM, lastM, -- * Subvectors- slice, extract, takeSlice, take, dropSlice, drop,+ slice, init, tail, take, drop, -- * Permutations- (//), update, bpermute,+ accum, (//), update, backpermute, reverse, - -- * Mapping and zipping- map, zipWith, zip,+ -- * Mapping+ map, concatMap, + -- * Zipping and unzipping+ zipWith, zipWith3, zip, zip3, unzip, unzip3,+ -- * Comparisons eq, cmp, -- * Filtering- filter, takeWhileSlice, takeWhile, dropWhileSlice, dropWhile,+ filter, takeWhile, dropWhile, -- * Searching elem, notElem, find, findIndex, -- * Folding foldl, foldl1, foldl', foldl1', foldr, foldr1,+ + -- * Specialised folds+ and, or, sum, product, maximum, minimum, + -- * Unfolding+ unfoldr,+ -- * Scans prescanl, prescanl', + -- * Enumeration+ enumFromTo, enumFromThenTo,+ -- * Conversion to/from lists toList, fromList, @@ -61,7 +73,7 @@ new, -- * Unsafe functions- unsafeSlice, unsafeIndex,+ unsafeSlice, unsafeIndexM, -- * Utility functions vlength, vnew@@ -77,17 +89,21 @@ import Data.Vector.Fusion.Stream ( Stream, MStream ) import qualified Data.Vector.Fusion.Stream.Monadic as MStream import Data.Vector.Fusion.Stream.Size+import Data.Vector.Fusion.Util import Control.Exception ( assert ) -import Prelude hiding ( length,+import Prelude hiding ( length, null, replicate, (++), head, last,- init, tail, take, drop,- map, zipWith, zip,+ init, tail, take, drop, reverse,+ map, concatMap,+ zipWith, zipWith3, zip, zip3, unzip, unzip3, filter, takeWhile, dropWhile, elem, notElem,- foldl, foldl1, foldr, foldr1 )+ foldl, foldl1, foldr, foldr1,+ and, or, sum, product, maximum, minimum,+ enumFromTo, enumFromThenTo ) -- | Class of immutable vectors. --@@ -101,26 +117,28 @@ -- | Yield a part of the vector without copying it. No range checks! unsafeSlice :: v a -> Int -> Int -> v a - -- | Apply the given function to the element at the given position. This- -- interface prevents us from being too lazy. Suppose we had+ -- | Yield the element at the given position in a monad. The monad allows us+ -- to be strict in the vector if we want. Suppose we had --- -- > unsafeIndex' :: v a -> Int -> a+ -- > unsafeIndex :: v a -> Int -> a -- -- instead. Now, if we wanted to copy a vector, we'd do something like --- -- > copy mv v ... = ... unsafeWrite mv i (unsafeIndex' v i) ...+ -- > copy mv v ... = ... unsafeWrite mv i (unsafeIndex v i) ... -- -- For lazy vectors, the indexing would not be evaluated which means that we -- would retain a reference to the original vector in each element we write.- -- This would be bad!+ -- This is not what we want! --- -- With 'unsafeIndex', we can do+ -- With 'unsafeIndexM', we can do --- -- > copy mv v ... = ... unsafeIndex v i (unsafeWrite mv i) ...+ -- > copy mv v ... = ... case unsafeIndexM v i of+ -- Box x -> unsafeWrite mv i x ... --- -- which does not have this problem.+ -- which does not have this problem because indexing (but not the returned+ -- element!) is evaluated immediately. --- unsafeIndex :: v a -> Int -> (a -> b) -> b+ unsafeIndexM :: Monad m => v a -> Int -> m a -- Fusion -- ------@@ -141,12 +159,12 @@ -- | Convert a vector to a 'Stream' stream :: IVector v a => v a -> Stream a {-# INLINE_STREAM stream #-}-stream v = v `seq` (Stream.unfold get 0 `Stream.sized` Exact n)+stream v = v `seq` (Stream.unfoldr get 0 `Stream.sized` Exact n) where n = length v {-# INLINE get #-}- get i | i < n = unsafeIndex v i $ \x -> Just (x, i+1)+ get i | i < n = case unsafeIndexM v i of Box x -> Just (x, i+1) | otherwise = Nothing -- | Create a vector from a 'Stream'@@ -201,6 +219,17 @@ #-} +null :: IVector v a => v a -> Bool+{-# INLINE_STREAM null #-}+null v = vlength v == 0++{-# RULES++"null/unstream [IVector]" forall v s.+ null (new' v (New.unstream s)) = Stream.null s++ #-}+ -- Construction -- ------------ @@ -235,6 +264,18 @@ {-# INLINE (++) #-} v ++ w = unstream (stream v Stream.++ stream w) +-- | Create a copy of a vector. Useful when dealing with slices.+copy :: IVector v a => v a -> v a+{-# INLINE_STREAM copy #-}+copy = unstream . stream++{-# RULES++"copy/unstream [IVector]" forall v s.+ copy (new' v (New.unstream s)) = new' v (New.unstream s)++ #-}+ -- Accessing individual elements -- ----------------------------- @@ -242,7 +283,7 @@ (!) :: IVector v a => v a -> Int -> a {-# INLINE_STREAM (!) #-} v ! i = assert (i >= 0 && i < length v)- $ unsafeIndex v i id+ $ unId (unsafeIndexM v i) -- | First element head :: IVector v a => v a -> a@@ -267,6 +308,34 @@ #-} +-- | Monadic indexing which can be strict in the vector while remaining lazy in+-- the element.+indexM :: (IVector v a, Monad m) => v a -> Int -> m a+{-# INLINE_STREAM indexM #-}+indexM v i = assert (i >= 0 && i < length v)+ $ unsafeIndexM v i++headM :: (IVector v a, Monad m) => v a -> m a+{-# INLINE_STREAM headM #-}+headM v = indexM v 0++lastM :: (IVector v a, Monad m) => v a -> m a+{-# INLINE_STREAM lastM #-}+lastM v = indexM v (length v - 1)++{-# RULES++"indexM/unstream [IVector]" forall v i s.+ indexM (new' v (New.unstream s)) i = return (s Stream.!! i)++"headM/unstream [IVector]" forall v s.+ headM (new' v (New.unstream s)) = return (Stream.head s)++"lastM/unstream [IVector]" forall v s.+ lastM (new' v (New.unstream s)) = return (Stream.last s)++ #-}+ -- Subarrays -- --------- @@ -281,43 +350,56 @@ slice v i n = assert (i >= 0 && n >= 0 && i+n <= length v) $ unsafeSlice v i n --- | Copy @n@ elements starting at the given position to a new vector.-extract :: IVector v a => v a -> Int -- ^ starting index- -> Int -- ^ length- -> v a-{-# INLINE extract #-}-extract v i n = unstream (Stream.extract (stream v) i n)+-- | Yield all but the last element without copying.+init :: IVector v a => v a -> v a+{-# INLINE_STREAM init #-}+init v = slice v 0 (length v - 1) --- | Yield the first @n@ elements without copying.-takeSlice :: IVector v a => Int -> v a -> v a-{-# INLINE takeSlice #-}-takeSlice n v = slice v 0 n+-- | All but the first element (without copying).+tail :: IVector v a => v a -> v a+{-# INLINE_STREAM tail #-}+tail v = slice v 1 (length v - 1) --- | Copy the first @n@ elements to a new vector.+-- | Yield the first @n@ elements without copying. take :: IVector v a => Int -> v a -> v a-{-# INLINE take #-}-take n = unstream . Stream.take n . stream+{-# INLINE_STREAM take #-}+take n v = slice v 0 (min n' (length v))+ where n' = max n 0 -- | Yield all but the first @n@ elements without copying.-dropSlice :: IVector v a => Int -> v a -> v a-{-# INLINE dropSlice #-}-dropSlice n v = slice v n (length v - n)---- | Copy all but the first @n@ elements to a new vectors. drop :: IVector v a => Int -> v a -> v a-{-# INLINE drop #-}-drop n = unstream . Stream.drop n . stream+{-# INLINE_STREAM drop #-}+drop n v = slice v (min n' len) (max 0 (len - n'))+ where n' = max n 0+ len = length v {-# RULES -"slice/unstream [IVector]" forall v i n s.- slice (new' v (New.unstream s)) i n = extract (new' v (New.unstream s)) i n+"slice/new [IVector]" forall v p i n.+ slice (new' v p) i n = new' v (New.slice p i n) +"init/new [IVector]" forall v p.+ init (new' v p) = new' v (New.init p)++"tail/new [IVector]" forall v p.+ tail (new' v p) = new' v (New.tail p)++"take/new [IVector]" forall n v p.+ take n (new' v p) = new' v (New.take n p)++"drop/new [IVector]" forall n v p.+ drop n (new' v p) = new' v (New.drop n p)+ #-} -- Permutations -- ------------ +accum :: IVector v a => (a -> b -> a) -> v a -> [(Int,b)] -> v a+{-# INLINE accum #-}+accum f v us = new (New.accum f (New.unstream (stream v))+ (Stream.fromList us))+ (//) :: IVector v a => v a -> [(Int, a)] -> v a {-# INLINE (//) #-} v // us = new (New.update (New.unstream (stream v))@@ -327,13 +409,26 @@ {-# INLINE update #-} update v w = new (New.update (New.unstream (stream v)) (stream w)) -bpermute :: (IVector v a, IVector v Int) => v a -> v Int -> v a-{-# INLINE bpermute #-}-bpermute v is = v `seq` map (v!) is+-- This somewhat non-intuitive definition ensures that the resulting vector+-- does not retain references to the original one even if it is lazy in its+-- elements. This would not be the case if we simply used+--+-- backpermute v is = map (v!) is+backpermute :: (IVector v a, IVector v Int) => v a -> v Int -> v a+{-# INLINE backpermute #-}+backpermute v is = unstream+ . MStream.trans (Id . unBox)+ . MStream.mapM (indexM v)+ . MStream.trans (Box . unId)+ $ stream is --- Mapping/zipping--- ---------------+reverse :: (IVector v a) => v a -> v a+{-# INLINE reverse #-}+reverse = new . New.reverse . New.unstream . stream +-- Mapping+-- -------+ -- | Map a function over a vector map :: (IVector v a, IVector v b) => (a -> b) -> v a -> v b {-# INLINE map #-}@@ -349,15 +444,39 @@ #-} +concatMap :: (IVector v a, IVector v b) => (a -> v b) -> v a -> v b+{-# INLINE concatMap #-}+concatMap f = unstream . Stream.concatMap (stream . f) . stream++-- Zipping/unzipping+-- -----------------+ -- | Zip two vectors with the given function. zipWith :: (IVector v a, IVector v b, IVector v c) => (a -> b -> c) -> v a -> v b -> v c {-# INLINE zipWith #-} zipWith f xs ys = unstream (Stream.zipWith f (stream xs) (stream ys)) +-- | Zip three vectors with the given function.+zipWith3 :: (IVector v a, IVector v b, IVector v c, IVector v d) => (a -> b -> c -> d) -> v a -> v b -> v c -> v d+{-# INLINE zipWith3 #-}+zipWith3 f xs ys zs = unstream (Stream.zipWith3 f (stream xs) (stream ys) (stream zs))+ zip :: (IVector v a, IVector v b, IVector v (a,b)) => v a -> v b -> v (a, b) {-# INLINE zip #-} zip = zipWith (,) +zip3 :: (IVector v a, IVector v b, IVector v c, IVector v (a, b, c)) => v a -> v b -> v c -> v (a, b, c)+{-# INLINE zip3 #-}+zip3 = zipWith3 (,,)++unzip :: (IVector v a, IVector v b, IVector v (a,b)) => v (a, b) -> (v a, v b)+{-# INLINE unzip #-}+unzip xs = (map fst xs, map snd xs)++unzip3 :: (IVector v a, IVector v b, IVector v c, IVector v (a, b, c)) => v (a, b, c) -> (v a, v b, v c)+{-# INLINE unzip3 #-}+unzip3 xs = (map (\(a, b, c) -> a) xs, map (\(a, b, c) -> b) xs, map (\(a, b, c) -> c) xs)+ -- Comparisons -- ----------- @@ -377,44 +496,16 @@ {-# INLINE filter #-} filter f = unstream . inplace (MStream.filter f) . stream --- | Yield the longest prefix of elements satisfying the predicate without--- copying.-takeWhileSlice :: IVector v a => (a -> Bool) -> v a -> v a-{-# INLINE_STREAM takeWhileSlice #-}-takeWhileSlice f v = case findIndex (not . f) v of- Just n -> takeSlice n v- Nothing -> v---- | Copy the longest prefix of elements satisfying the predicate to a new--- vector+-- | Yield the longest prefix of elements satisfying the predicate. takeWhile :: IVector v a => (a -> Bool) -> v a -> v a {-# INLINE takeWhile #-} takeWhile f = unstream . Stream.takeWhile f . stream --- | Drop the longest prefix of elements that satisfy the predicate without--- copying-dropWhileSlice :: IVector v a => (a -> Bool) -> v a -> v a-{-# INLINE_STREAM dropWhileSlice #-}-dropWhileSlice f v = case findIndex (not . f) v of- Just n -> dropSlice n v- Nothing -> v---- | Drop the longest prefix of elements that satisfy the predicate and copy--- the rest to a new vector.+-- | Drop the longest prefix of elements that satisfy the predicate. dropWhile :: IVector v a => (a -> Bool) -> v a -> v a {-# INLINE dropWhile #-} dropWhile f = unstream . Stream.dropWhile f . stream -{-# RULES--"takeWhileSlice/unstream" forall v f s.- takeWhileSlice f (new' v (New.unstream s)) = takeWhile f (new' v (New.unstream s))--"dropWhileSlice/unstream" forall v f s.- dropWhileSlice f (new' v (New.unstream s)) = dropWhile f (new' v (New.unstream s))-- #-}- -- Searching -- --------- @@ -475,6 +566,40 @@ {-# INLINE foldr1 #-} foldr1 f = Stream.foldr1 f . stream +-- Specialised folds+-- -----------------++and :: IVector v Bool => v Bool -> Bool+{-# INLINE and #-}+and = Stream.and . stream++or :: IVector v Bool => v Bool -> Bool+{-# INLINE or #-}+or = Stream.or . stream++sum :: (IVector v a, Num a) => v a -> a+{-# INLINE sum #-}+sum = Stream.foldl' (+) 0 . stream++product :: (IVector v a, Num a) => v a -> a+{-# INLINE product #-}+product = Stream.foldl' (*) 1 . stream++maximum :: (IVector v a, Ord a) => v a -> a+{-# INLINE maximum #-}+maximum = Stream.foldl1' max . stream++minimum :: (IVector v a, Ord a) => v a -> a+{-# INLINE minimum #-}+minimum = Stream.foldl1' min . stream++-- Unfolding+-- ---------++unfoldr :: IVector v a => (b -> Maybe (a, b)) -> b -> v a+{-# INLINE unfoldr #-}+unfoldr f = unstream . Stream.unfoldr f+ -- Scans -- ----- @@ -508,6 +633,27 @@ #-} ++-- Enumeration+-- -----------++enumFromTo :: (IVector v a, Enum a) => a -> a -> v a+{-# INLINE enumFromTo #-}+enumFromTo from to = from `seq` to `seq` unfoldr enumFromTo_go (fromEnum from)+ where+ to_i = fromEnum to+ enumFromTo_go i | i <= to_i = Just (toEnum i, i + 1)+ | otherwise = Nothing++enumFromThenTo :: (IVector v a, Enum a) => a -> a -> a -> v a+{-# INLINE enumFromThenTo #-}+enumFromThenTo from next to = from `seq` next `seq` to `seq` unfoldr enumFromThenTo_go from_i+ where+ from_i = fromEnum from+ to_i = fromEnum to+ step_i = fromEnum next - from_i+ enumFromThenTo_go i | i <= to_i = Just (toEnum i, i + step_i)+ | otherwise = Nothing -- | Convert a vector to a list toList :: IVector v a => v a -> [a]
Data/Vector/MVector.hs view
@@ -18,7 +18,7 @@ slice, new, newWith, read, write, copy, grow, unstream, transform,- update, reverse+ accum, update, reverse ) where import qualified Data.Vector.Fusion.Stream as Stream@@ -169,7 +169,7 @@ mstream :: MVector v m a => v a -> MStream m a {-# INLINE mstream #-}-mstream v = v `seq` (MStream.unfoldM get 0 `MStream.sized` Exact n)+mstream v = v `seq` (MStream.unfoldrM get 0 `MStream.sized` Exact n) where n = length v @@ -229,12 +229,18 @@ . double2Int $ int2Double (length v) * gROWTH_FACTOR +accum :: MVector v m a => (a -> b -> a) -> v a -> Stream (Int, b) -> m ()+{-# INLINE accum #-}+accum f v s = Stream.mapM_ upd s+ where+ {-# INLINE upd #-}+ upd (i,b) = do+ a <- read v i+ write v i (f a b)+ update :: MVector v m a => v a -> Stream (Int, a) -> m () {-# INLINE update #-}-update v s = Stream.mapM_ put s- where- {-# INLINE put #-}- put (i, x) = write v i x+update = accum (const id) reverse :: MVector v m a => v a -> m () {-# INLINE reverse #-}@@ -245,5 +251,6 @@ y <- unsafeRead v j unsafeWrite v i y unsafeWrite v j x+ reverse_loop (i + 1) (j - 1) reverse_loop _ _ = return ()
Data/Vector/MVector/New.hs view
@@ -3,11 +3,12 @@ #include "phases.h" module Data.Vector.MVector.New (- New(..), run, unstream, transform, update, reverse+ New(..), run, unstream, transform, accum, update, reverse,+ slice, init, tail, take, drop ) where import qualified Data.Vector.MVector as MVector-import Data.Vector.MVector ( MVector )+import Data.Vector.MVector ( MVector, MVectorPure ) import Data.Vector.Fusion.Stream ( Stream, MStream ) import qualified Data.Vector.Fusion.Stream as Stream@@ -15,7 +16,7 @@ import qualified Data.Vector.Fusion.Stream.Monadic as MStream import Control.Monad ( liftM )-import Prelude hiding ( reverse, map, filter )+import Prelude hiding ( init, tail, take, drop, reverse, map, filter ) newtype New a = New (forall m mv. MVector mv m a => m (mv a)) @@ -23,6 +24,10 @@ {-# INLINE run #-} run (New p) = p +apply :: (forall mv a. MVectorPure mv a => mv a -> mv a) -> New a -> New a+{-# INLINE apply #-}+apply f (New p) = New (liftM f p)+ modify :: New a -> (forall m mv. MVector mv m a => mv a -> m ()) -> New a {-# INLINE modify #-} modify (New p) q = New (do { v <- p; q v; return v })@@ -43,7 +48,55 @@ p . transform f (transform g p) = transform (f . g) p +"transform/unstream [New]"+ forall (f :: forall m. Monad m => MStream m a -> MStream m a)+ s.+ transform f (unstream s) = unstream (f s)+ #-}++slice :: New a -> Int -> Int -> New a+{-# INLINE_STREAM slice #-}+slice m i n = apply (\v -> MVector.slice v i n) m++init :: New a -> New a+{-# INLINE_STREAM init #-}+init m = apply (\v -> MVector.slice v 0 (MVector.length v - 1)) m++tail :: New a -> New a+{-# INLINE_STREAM tail #-}+tail m = apply (\v -> MVector.slice v 1 (MVector.length v - 1)) m++take :: Int -> New a -> New a+{-# INLINE_STREAM take #-}+take n m = apply (\v -> MVector.slice v 0 (min n (MVector.length v))) m++drop :: Int -> New a -> New a+{-# INLINE_STREAM drop #-}+drop n m = apply (\v -> MVector.slice v n (max 0 (MVector.length v - n))) m++{-# RULES++"slice/unstream [New]" forall s i n.+ slice (unstream s) i n = unstream (Stream.extract s i n)++"init/unstream [New]" forall s.+ init (unstream s) = unstream (Stream.init s)++"tail/unstream [New]" forall s.+ tail (unstream s) = unstream (Stream.tail s)++"take/unstream [New]" forall n s.+ take n (unstream s) = unstream (Stream.take n s)++"drop/unstream [New]" forall n s.+ drop n (unstream s) = unstream (Stream.drop n s)++ #-}++accum :: (a -> b -> a) -> New a -> Stream (Int, b) -> New a+{-# INLINE_STREAM accum #-}+accum f m s = modify m (\v -> MVector.accum f v s) update :: New a -> Stream (Int, a) -> New a {-# INLINE_STREAM update #-}
− Data/Vector/Mutable.hs
@@ -1,77 +0,0 @@-{-# LANGUAGE MagicHash, UnboxedTuples, MultiParamTypeClasses, FlexibleInstances #-}---- |--- Module : Data.Vector.Mutable--- Copyright : (c) Roman Leshchinskiy 2008--- License : BSD-style------ Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable--- --- Mutable boxed vectors.-----module Data.Vector.Mutable ( Vector(..) )-where--import qualified Data.Vector.MVector as MVector-import Data.Vector.MVector ( MVector, MVectorPure )--import GHC.Prim ( MutableArray#,- newArray#, readArray#, writeArray#, sameMutableArray#, (+#) )--import GHC.ST ( ST(..) )--import GHC.Base ( Int(..) )---- | Mutable boxed vectors. They live in the 'ST' monad.-data Vector s a = Vector {-# UNPACK #-} !Int- {-# UNPACK #-} !Int- (MutableArray# s a)--instance MVectorPure (Vector s) a where- length (Vector _ n _) = n- unsafeSlice (Vector i _ arr#) j m = Vector (i+j) m arr#-- {-# INLINE overlaps #-}- overlaps (Vector i m arr1#) (Vector j n arr2#)- = sameMutableArray# arr1# arr2#- && (between i j (j+n) || between j i (i+m))- where- between x y z = x >= y && x < z---instance MVector (Vector s) (ST s) a where- {-# INLINE unsafeNew #-}- unsafeNew = unsafeNew-- {-# INLINE unsafeNewWith #-}- unsafeNewWith = unsafeNewWith-- {-# INLINE unsafeRead #-}- unsafeRead (Vector (I# i#) _ arr#) (I# j#) = ST (readArray# arr# (i# +# j#))-- {-# INLINE unsafeWrite #-}- unsafeWrite (Vector (I# i#) _ arr#) (I# j#) x = ST (\s# ->- case writeArray# arr# (i# +# j#) x s# of s2# -> (# s2#, () #)- )-- {-# INLINE clear #-}- clear v = MVector.set v uninitialised---uninitialised :: a-uninitialised = error "Data.Vector.Mutable: uninitialised elemen t"--unsafeNew :: Int -> ST s (Vector s a)-{-# INLINE unsafeNew #-}-unsafeNew n = unsafeNewWith n uninitialised--unsafeNewWith :: Int -> a -> ST s (Vector s a)-{-# INLINE unsafeNewWith #-}-unsafeNewWith (I# n#) x = ST (\s# ->- case newArray# n# x s# of- (# s2#, arr# #) -> (# s2#, Vector 0 (I# n#) arr# #)- )-
+ Data/Vector/Mutable/IO.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}++-- |+-- Module : Data.Vector.Mutable.IO+-- Copyright : (c) Roman Leshchinskiy 2009+-- License : BSD-style+--+-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>+-- Stability : experimental+-- Portability : non-portable+-- +-- Mutable boxed vectors in the IO monad.+--++module Data.Vector.Mutable.IO ( Vector(..) )+where++import Data.Vector.MVector ( MVector(..), MVectorPure(..) )+import qualified Data.Vector.Mutable.ST as STV++import GHC.Base ( RealWorld )+import GHC.ST ( ST(..) )+import GHC.IOBase ( IO(..) )++import Prelude hiding ( length )++-- | IO-based mutable vectors+newtype Vector a = Vector (STV.Vector RealWorld a)++instance MVectorPure Vector a where+ {-# INLINE length #-}+ length (Vector v) = length v++ {-# INLINE unsafeSlice #-}+ unsafeSlice (Vector v) j m = Vector (unsafeSlice v j m)++ {-# INLINE overlaps #-}+ overlaps (Vector v1) (Vector v2) = overlaps v1 v2++instance MVector Vector IO a where+ {-# INLINE unsafeNew #-}+ unsafeNew n = Vector `fmap` stToIO (unsafeNew n)++ {-# INLINE unsafeNewWith #-}+ unsafeNewWith n x = Vector `fmap` stToIO (unsafeNewWith n x)++ {-# INLINE unsafeRead #-}+ unsafeRead (Vector v) i = stToIO (unsafeRead v i)++ {-# INLINE unsafeWrite #-}+ unsafeWrite (Vector v) i x = stToIO (unsafeWrite v i x)++ {-# INLINE clear #-}+ clear (Vector v) = stToIO (clear v)++stToIO :: ST RealWorld a -> IO a+stToIO (ST m) = IO m+
+ Data/Vector/Mutable/ST.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE MagicHash, UnboxedTuples, MultiParamTypeClasses, FlexibleInstances #-}++-- |+-- Module : Data.Vector.Mutable.ST+-- Copyright : (c) Roman Leshchinskiy 2008+-- License : BSD-style+--+-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>+-- Stability : experimental+-- Portability : non-portable+-- +-- Mutable boxed vectors in the ST monad.+--++module Data.Vector.Mutable.ST ( Vector(..) )+where++import qualified Data.Vector.MVector as MVector+import Data.Vector.MVector ( MVector, MVectorPure )++import GHC.Prim ( MutableArray#,+ newArray#, readArray#, writeArray#, sameMutableArray#, (+#) )++import GHC.ST ( ST(..) )++import GHC.Base ( Int(..) )++-- | Mutable boxed vectors. They live in the 'ST' monad.+data Vector s a = Vector {-# UNPACK #-} !Int+ {-# UNPACK #-} !Int+ (MutableArray# s a)++instance MVectorPure (Vector s) a where+ length (Vector _ n _) = n+ unsafeSlice (Vector i _ arr#) j m = Vector (i+j) m arr#++ {-# INLINE overlaps #-}+ overlaps (Vector i m arr1#) (Vector j n arr2#)+ = sameMutableArray# arr1# arr2#+ && (between i j (j+n) || between j i (i+m))+ where+ between x y z = x >= y && x < z+++instance MVector (Vector s) (ST s) a where+ {-# INLINE unsafeNew #-}+ unsafeNew = unsafeNew++ {-# INLINE unsafeNewWith #-}+ unsafeNewWith = unsafeNewWith++ {-# INLINE unsafeRead #-}+ unsafeRead (Vector (I# i#) _ arr#) (I# j#) = ST (readArray# arr# (i# +# j#))++ {-# INLINE unsafeWrite #-}+ unsafeWrite (Vector (I# i#) _ arr#) (I# j#) x = ST (\s# ->+ case writeArray# arr# (i# +# j#) x s# of s2# -> (# s2#, () #)+ )++ {-# INLINE clear #-}+ clear v = MVector.set v uninitialised+++uninitialised :: a+uninitialised = error "Data.Vector.Mutable: uninitialised elemen t"++unsafeNew :: Int -> ST s (Vector s a)+{-# INLINE unsafeNew #-}+unsafeNew n = unsafeNewWith n uninitialised++unsafeNewWith :: Int -> a -> ST s (Vector s a)+{-# INLINE unsafeNewWith #-}+unsafeNewWith (I# n#) x = ST (\s# ->+ case newArray# n# x s# of+ (# s2#, arr# #) -> (# s2#, Vector 0 (I# n#) arr# #)+ )+
Data/Vector/Unboxed.hs view
@@ -13,11 +13,57 @@ -- module Data.Vector.Unboxed (- Vector(..), module Data.Vector.IVector+ Vector,++ -- * Length information+ length, null,++ -- * Construction+ empty, singleton, cons, snoc, replicate, (++), copy,++ -- * Accessing individual elements+ (!), head, last,++ -- * Subvectors+ slice, init, tail, take, drop,++ -- * Permutations+ accum, (//), backpermute, reverse,++ -- * Mapping+ map, concatMap,++ -- * Zipping and unzipping+ zipWith, zipWith3,++ -- * Filtering+ filter, takeWhile, dropWhile,++ -- * Searching+ elem, notElem, find, findIndex,++ -- * Folding+ foldl, foldl1, foldl', foldl1', foldr, foldr1,++ -- * Specialised folds+ {-and, or,-} sum, product, maximum, minimum,++ -- * Unfolding+ unfoldr,++ -- * Scans+ prescanl, prescanl',++ -- * Enumeration+ enumFromTo, enumFromThenTo,++ -- * Conversion to/from lists+ toList, fromList ) where -import Data.Vector.IVector-import qualified Data.Vector.Unboxed.Mutable as Mut+import Data.Vector.IVector ( IVector(..) )+import qualified Data.Vector.IVector as IV+import qualified Data.Vector.Unboxed.Mutable.ST as Mut import Data.Vector.Unboxed.Unbox import Control.Monad.ST ( runST )@@ -26,11 +72,28 @@ import GHC.Prim ( ByteArray#, unsafeFreezeByteArray#, (+#) ) import GHC.Base ( Int(..) ) +import Prelude hiding ( length, null,+ replicate, (++),+ head, last,+ init, tail, take, drop, reverse,+ map, concatMap,+ zipWith, zipWith3, zip, zip3, unzip, unzip3,+ filter, takeWhile, dropWhile,+ elem, notElem,+ foldl, foldl1, foldr, foldr1,+ and, or, sum, product, minimum, maximum,+ enumFromTo, enumFromThenTo )++import qualified Prelude+ -- | Unboxed vectors data Vector a = Vector {-# UNPACK #-} !Int {-# UNPACK #-} !Int ByteArray# +instance (Show a, Unbox a) => Show (Vector a) where+ show = (Prelude.++ " :: Data.Vector.Unboxed.Vector") . ("fromList " Prelude.++) . show . toList+ instance Unbox a => IVector Vector a where {-# INLINE vnew #-} vnew init = runST (do@@ -44,14 +107,310 @@ {-# INLINE unsafeSlice #-} unsafeSlice (Vector i _ arr#) j n = Vector (i+j) n arr# - {-# INLINE unsafeIndex #-}- unsafeIndex (Vector (I# i#) _ arr#) (I# j#) f = f (at# arr# (i# +# j#))+ {-# INLINE unsafeIndexM #-}+ unsafeIndexM (Vector (I# i#) _ arr#) (I# j#) = return (at# arr# (i# +# j#)) instance (Unbox a, Eq a) => Eq (Vector a) where {-# INLINE (==) #-}- (==) = eq+ (==) = IV.eq instance (Unbox a, Ord a) => Ord (Vector a) where {-# INLINE compare #-}- compare = cmp+ compare = IV.cmp++-- Length+-- ------++length :: Unbox a => Vector a -> Int+{-# INLINE length #-}+length = IV.length++null :: Unbox a => Vector a -> Bool+{-# INLINE null #-}+null = IV.null++-- Construction+-- ------------++-- | Empty vector+empty :: Unbox a => Vector a+{-# INLINE empty #-}+empty = IV.empty++-- | Vector with exaclty one element+singleton :: Unbox a => a -> Vector a+{-# INLINE singleton #-}+singleton = IV.singleton++-- | Vector of the given length with the given value in each position+replicate :: Unbox a => Int -> a -> Vector a+{-# INLINE replicate #-}+replicate = IV.replicate++-- | Prepend an element+cons :: Unbox a => a -> Vector a -> Vector a+{-# INLINE cons #-}+cons = IV.cons++-- | Append an element+snoc :: Unbox a => Vector a -> a -> Vector a+{-# INLINE snoc #-}+snoc = IV.snoc++infixr 5 +++-- | Concatenate two vectors+(++) :: Unbox a => Vector a -> Vector a -> Vector a+{-# INLINE (++) #-}+(++) = (IV.++)++-- | Create a copy of a vector. Useful when dealing with slices.+copy :: Unbox a => Vector a -> Vector a+{-# INLINE copy #-}+copy = IV.copy++-- Accessing individual elements+-- -----------------------------++-- | Indexing+(!) :: Unbox a => Vector a -> Int -> a+{-# INLINE (!) #-}+(!) = (IV.!)++-- | First element+head :: Unbox a => Vector a -> a+{-# INLINE head #-}+head = IV.head++-- | Last element+last :: Unbox a => Vector a -> a+{-# INLINE last #-}+last = IV.last++-- Subarrays+-- ---------++-- | Yield a part of the vector without copying it. Safer version of+-- 'unsafeSlice'.+slice :: Unbox a => Vector a -> Int -- ^ starting index+ -> Int -- ^ length+ -> Vector a+{-# INLINE slice #-}+slice = IV.slice++-- | Yield all but the last element without copying.+init :: Unbox a => Vector a -> Vector a+{-# INLINE init #-}+init = IV.init++-- | All but the first element (without copying).+tail :: Unbox a => Vector a -> Vector a+{-# INLINE tail #-}+tail = IV.tail++-- | Yield the first @n@ elements without copying.+take :: Unbox a => Int -> Vector a -> Vector a+{-# INLINE take #-}+take = IV.take++-- | Yield all but the first @n@ elements without copying.+drop :: Unbox a => Int -> Vector a -> Vector a+{-# INLINE drop #-}+drop = IV.drop++-- Permutations+-- ------------++accum :: Unbox a => (a -> b -> a) -> Vector a -> [(Int,b)] -> Vector a+{-# INLINE accum #-}+accum = IV.accum++(//) :: Unbox a => Vector a -> [(Int, a)] -> Vector a+{-# INLINE (//) #-}+(//) = (IV.//)++backpermute :: Unbox a => Vector a -> Vector Int -> Vector a+{-# INLINE backpermute #-}+backpermute = IV.backpermute++reverse :: Unbox a => Vector a -> Vector a+{-# INLINE reverse #-}+reverse = IV.reverse++-- Mapping+-- -------++-- | Map a function over a vector+map :: (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b+{-# INLINE map #-}+map = IV.map++concatMap :: (Unbox a, Unbox b) => (a -> Vector b) -> Vector a -> Vector b+{-# INLINE concatMap #-}+concatMap = IV.concatMap++-- Zipping/unzipping+-- -----------------++-- | Zip two vectors with the given function.+zipWith :: (Unbox a, Unbox b, Unbox c)+ => (a -> b -> c) -> Vector a -> Vector b -> Vector c+{-# INLINE zipWith #-}+zipWith = IV.zipWith++-- | Zip three vectors with the given function.+zipWith3 :: (Unbox a, Unbox b, Unbox c, Unbox d)+ => (a -> b -> c -> d) -> Vector a -> Vector b -> Vector c -> Vector d+{-# INLINE zipWith3 #-}+zipWith3 = IV.zipWith3++-- Filtering+-- ---------++-- | Drop elements which do not satisfy the predicate+filter :: Unbox a => (a -> Bool) -> Vector a -> Vector a+{-# INLINE filter #-}+filter = IV.filter++-- | Yield the longest prefix of elements satisfying the predicate.+takeWhile :: Unbox a => (a -> Bool) -> Vector a -> Vector a+{-# INLINE takeWhile #-}+takeWhile = IV.takeWhile++-- | Drop the longest prefix of elements that satisfy the predicate.+dropWhile :: Unbox a => (a -> Bool) -> Vector a -> Vector a+{-# INLINE dropWhile #-}+dropWhile = IV.dropWhile++-- Searching+-- ---------++infix 4 `elem`+-- | Check whether the vector contains an element+elem :: (Unbox a, Eq a) => a -> Vector a -> Bool+{-# INLINE elem #-}+elem = IV.elem++infix 4 `notElem`+-- | Inverse of `elem`+notElem :: (Unbox a, Eq a) => a -> Vector a -> Bool+{-# INLINE notElem #-}+notElem = IV.notElem++-- | Yield 'Just' the first element matching the predicate or 'Nothing' if no+-- such element exists.+find :: Unbox a => (a -> Bool) -> Vector a -> Maybe a+{-# INLINE find #-}+find = IV.find++-- | Yield 'Just' the index of the first element matching the predicate or+-- 'Nothing' if no such element exists.+findIndex :: Unbox a => (a -> Bool) -> Vector a -> Maybe Int+{-# INLINE findIndex #-}+findIndex = IV.findIndex++-- Folding+-- -------++-- | Left fold+foldl :: Unbox b => (a -> b -> a) -> a -> Vector b -> a+{-# INLINE foldl #-}+foldl = IV.foldl++-- | Lefgt fold on non-empty vectors+foldl1 :: Unbox a => (a -> a -> a) -> Vector a -> a+{-# INLINE foldl1 #-}+foldl1 = IV.foldl1++-- | Left fold with strict accumulator+foldl' :: Unbox b => (a -> b -> a) -> a -> Vector b -> a+{-# INLINE foldl' #-}+foldl' = IV.foldl'++-- | Left fold on non-empty vectors with strict accumulator+foldl1' :: Unbox a => (a -> a -> a) -> Vector a -> a+{-# INLINE foldl1' #-}+foldl1' = IV.foldl1'++-- | Right fold+foldr :: Unbox a => (a -> b -> b) -> b -> Vector a -> b+{-# INLINE foldr #-}+foldr = IV.foldr++-- | Right fold on non-empty vectors+foldr1 :: Unbox a => (a -> a -> a) -> Vector a -> a+{-# INLINE foldr1 #-}+foldr1 = IV.foldr1++-- Specialised folds+-- -----------------++{-+and :: Vector Bool -> Bool+{-# INLINE and #-}+and = IV.and++or :: Vector Bool -> Bool+{-# INLINE or #-}+or = IV.or+-}++sum :: (Unbox a, Num a) => Vector a -> a+{-# INLINE sum #-}+sum = IV.sum++product :: (Unbox a, Num a) => Vector a -> a+{-# INLINE product #-}+product = IV.product++maximum :: (Unbox a, Ord a) => Vector a -> a+{-# INLINE maximum #-}+maximum = IV.maximum++minimum :: (Unbox a, Ord a) => Vector a -> a+{-# INLINE minimum #-}+minimum = IV.minimum++-- Unfolding+-- ---------++unfoldr :: Unbox a => (b -> Maybe (a, b)) -> b -> Vector a+{-# INLINE unfoldr #-}+unfoldr = IV.unfoldr++-- Scans+-- -----++-- | Prefix scan+prescanl :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a+{-# INLINE prescanl #-}+prescanl = IV.prescanl++-- | Prefix scan with strict accumulator+prescanl' :: (Unbox a, Unbox b) => (a -> b -> a) -> a -> Vector b -> Vector a+{-# INLINE prescanl' #-}+prescanl' = IV.prescanl'++-- Enumeration+-- -----------++enumFromTo :: (Unbox a, Enum a) => a -> a -> Vector a+{-# INLINE enumFromTo #-}+enumFromTo = IV.enumFromTo++enumFromThenTo :: (Unbox a, Enum a) => a -> a -> a -> Vector a+{-# INLINE enumFromThenTo #-}+enumFromThenTo = IV.enumFromThenTo++-- Conversion to/from lists+-- ------------------------++-- | Convert a vector to a list+toList :: Unbox a => Vector a -> [a]+{-# INLINE toList #-}+toList = IV.toList++-- | Convert a list to a vector+fromList :: Unbox a => [a] -> Vector a+{-# INLINE fromList #-}+fromList = IV.fromList
− Data/Vector/Unboxed/Mutable.hs
@@ -1,63 +0,0 @@-{-# LANGUAGE MagicHash, UnboxedTuples, MultiParamTypeClasses, FlexibleInstances, ScopedTypeVariables #-}---- |--- Module : Data.Vector.Unboxed.Mutable--- Copyright : (c) Roman Leshchinskiy 2008--- License : BSD-style------ Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>--- Stability : experimental--- Portability : non-portable--- --- Mutable unboxed vectors based on 'Unbox'.-----module Data.Vector.Unboxed.Mutable ( Vector(..) )-where--import qualified Data.Vector.MVector as MVector-import Data.Vector.MVector ( MVector, MVectorPure )-import Data.Vector.Unboxed.Unbox--import GHC.Prim ( MutableByteArray#,- newByteArray#, sameMutableByteArray#, (+#) )--import GHC.ST ( ST(..) )--import GHC.Base ( Int(..) )---- | Mutable unboxed vectors. They live in the 'ST' monad.-data Vector s a = Vector {-# UNPACK #-} !Int- {-# UNPACK #-} !Int- (MutableByteArray# s)--instance Unbox a => MVectorPure (Vector s) a where- length (Vector _ n _) = n- unsafeSlice (Vector i _ arr#) j m = Vector (i+j) m arr#-- {-# INLINE overlaps #-}- overlaps (Vector i m arr1#) (Vector j n arr2#)- = sameMutableByteArray# arr1# arr2#- && (between i j (j+n) || between j i (i+m))- where- between x y z = x >= y && x < z---instance Unbox a => MVector (Vector s) (ST s) a where- {-# INLINE unsafeNew #-}- unsafeNew (I# n#) = ST (\s# ->- case newByteArray# (size# (undefined :: a) n#) s# of- (# s2#, arr# #) -> (# s2#, Vector 0 (I# n#) arr# #)- )-- {-# INLINE unsafeRead #-}- unsafeRead (Vector (I# i#) _ arr#) (I# j#) = ST (read# arr# (i# +# j#))-- {-# INLINE unsafeWrite #-}- unsafeWrite (Vector (I# i#) _ arr#) (I# j#) x = ST (\s# ->- case write# arr# (i# +# j#) x s# of s2# -> (# s2#, () #)- )-- {-# INLINE clear #-}- clear _ = return ()-
+ Data/Vector/Unboxed/Mutable/IO.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}++-- |+-- Module : Data.Vector.Mutable.Unboxed.IO+-- Copyright : (c) Roman Leshchinskiy 2009+-- License : BSD-style+--+-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>+-- Stability : experimental+-- Portability : non-portable+-- +-- Mutable unboxed vectors in the IO monad.+--++module Data.Vector.Unboxed.Mutable.IO ( Vector(..) )+where++import Data.Vector.MVector ( MVector(..), MVectorPure(..) )+import qualified Data.Vector.Unboxed.Mutable.ST as STV+import Data.Vector.Unboxed.Unbox ( Unbox )++import GHC.Base ( RealWorld )+import GHC.ST ( ST(..) )+import GHC.IOBase ( IO(..) )++import Prelude hiding ( length )++-- | IO-based mutable vectors+newtype Vector a = Vector (STV.Vector RealWorld a)++instance Unbox a => MVectorPure Vector a where+ {-# INLINE length #-}+ length (Vector v) = length v++ {-# INLINE unsafeSlice #-}+ unsafeSlice (Vector v) j m = Vector (unsafeSlice v j m)++ {-# INLINE overlaps #-}+ overlaps (Vector v1) (Vector v2) = overlaps v1 v2++instance Unbox a => MVector Vector IO a where+ {-# INLINE unsafeNew #-}+ unsafeNew n = Vector `fmap` stToIO (unsafeNew n)++ {-# INLINE unsafeNewWith #-}+ unsafeNewWith n x = Vector `fmap` stToIO (unsafeNewWith n x)++ {-# INLINE unsafeRead #-}+ unsafeRead (Vector v) i = stToIO (unsafeRead v i)++ {-# INLINE unsafeWrite #-}+ unsafeWrite (Vector v) i x = stToIO (unsafeWrite v i x)++ {-# INLINE clear #-}+ clear (Vector v) = stToIO (clear v)++stToIO :: ST RealWorld a -> IO a+stToIO (ST m) = IO m+
+ Data/Vector/Unboxed/Mutable/ST.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE MagicHash, UnboxedTuples, MultiParamTypeClasses, FlexibleInstances, ScopedTypeVariables #-}++-- |+-- Module : Data.Vector.Unboxed.Mutable.ST+-- Copyright : (c) Roman Leshchinskiy 2008+-- License : BSD-style+--+-- Maintainer : Roman Leshchinskiy <rl@cse.unsw.edu.au>+-- Stability : experimental+-- Portability : non-portable+-- +-- Mutable unboxed vectors based on 'Unbox' in the ST monad.+--++module Data.Vector.Unboxed.Mutable.ST ( Vector(..) )+where++import qualified Data.Vector.MVector as MVector+import Data.Vector.MVector ( MVector, MVectorPure )+import Data.Vector.Unboxed.Unbox++import GHC.Prim ( MutableByteArray#,+ newByteArray#, sameMutableByteArray#, (+#) )++import GHC.ST ( ST(..) )++import GHC.Base ( Int(..) )++-- | Mutable unboxed vectors. They live in the 'ST' monad.+data Vector s a = Vector {-# UNPACK #-} !Int+ {-# UNPACK #-} !Int+ (MutableByteArray# s)++instance Unbox a => MVectorPure (Vector s) a where+ length (Vector _ n _) = n+ unsafeSlice (Vector i _ arr#) j m = Vector (i+j) m arr#++ {-# INLINE overlaps #-}+ overlaps (Vector i m arr1#) (Vector j n arr2#)+ = sameMutableByteArray# arr1# arr2#+ && (between i j (j+n) || between j i (i+m))+ where+ between x y z = x >= y && x < z+++instance Unbox a => MVector (Vector s) (ST s) a where+ {-# INLINE unsafeNew #-}+ unsafeNew (I# n#) = ST (\s# ->+ case newByteArray# (size# (undefined :: a) n#) s# of+ (# s2#, arr# #) -> (# s2#, Vector 0 (I# n#) arr# #)+ )++ {-# INLINE unsafeRead #-}+ unsafeRead (Vector (I# i#) _ arr#) (I# j#) = ST (read# arr# (i# +# j#))++ {-# INLINE unsafeWrite #-}+ unsafeWrite (Vector (I# i#) _ arr#) (I# j#) x = ST (\s# ->+ case write# arr# (i# +# j#) x s# of s2# -> (# s2#, () #)+ )++ {-# INLINE clear #-}+ clear _ = return ()+
Data/Vector/Unboxed/Unbox.hs view
@@ -22,11 +22,15 @@ import GHC.Float ( Float(..), Double(..) )+import GHC.Word (+ Word(..)+ ) import GHC.Prim ( ByteArray#, MutableByteArray#, State#, Int#, indexIntArray#, readIntArray#, writeIntArray#,+ indexWordArray#, readWordArray#, writeWordArray#, indexFloatArray#, readFloatArray#, writeFloatArray#, indexDoubleArray#, readDoubleArray#, writeDoubleArray# )@@ -49,6 +53,14 @@ -- | Store the given element at the given position write# :: MutableByteArray# s -> Int# -> a -> State# s -> State# s++instance Unbox Word where+ size# _ = wORD_SCALE+ at# arr# i# = W# (indexWordArray# arr# i#)+ read# arr# i# s# = case readWordArray# arr# i# s# of+ (# s1#, n# #) -> (# s1#, W# n# #)+ write# arr# i# (W# n#) s# = writeWordArray# arr# i# n# s#+ instance Unbox Int where size# _ = wORD_SCALE
LICENSE view
@@ -1,5 +1,4 @@-Copyright (c) 2001-2002, Manuel M T Chakravarty & Gabriele Keller-Copyright (c) 2006-2007, Manuel M T Chakravarty & Roman Leshchinskiy+Copyright (c) 2008-2009, Roman Leshchinskiy All rights reserved. Redistribution and use in source and binary forms, with or without
vector.cabal view
@@ -1,5 +1,5 @@ Name: vector-Version: 0.2+Version: 0.3 License: BSD3 License-File: LICENSE Author: Roman Leshchinskiy@@ -10,18 +10,23 @@ Synopsis: Efficient Arrays Description: .- An efficient implementation of Int-indexed arrays with a powerful- loop fusion framework.+ An efficient but highly experimental implementation of Int-indexed+ arrays with a powerful loop fusion framework. .- This code is highly experimental and for the most part untested. Use- at your own risk! Cabal-Version: >= 1.2 Build-Type: Simple +Flag EnableAssertions+ Description: Enable assertions that check parameters to functions are reasonable.+ These will impose a moderate performance cost on users of the library,+ with the benefit that you get reasonable errors rather than segmentation faults!+ Default: False+ Library Extensions: CPP Exposed-Modules:+ Data.Vector.Fusion.Util Data.Vector.Fusion.Stream.Size Data.Vector.Fusion.Stream.Monadic Data.Vector.Fusion.Stream@@ -31,10 +36,12 @@ Data.Vector.IVector Data.Vector.Unboxed.Unbox- Data.Vector.Unboxed.Mutable+ Data.Vector.Unboxed.Mutable.ST+ Data.Vector.Unboxed.Mutable.IO Data.Vector.Unboxed - Data.Vector.Mutable+ Data.Vector.Mutable.ST+ Data.Vector.Mutable.IO Data.Vector Include-Dirs: include@@ -42,6 +49,23 @@ Install-Includes: phases.h - Build-Depends: base, array, ghc-prim,+ Build-Depends: base >= 2 && < 4, array, ghc-prim, ghc >= 6.9 +-- -finline-if-enough-args is ESSENTIAL. If we don't have this the partial application+-- of e.g. Stream.Monadic.++ to the monad dictionary at the use site in Stream.++ causes+-- it to be fruitlessly inlined. This in turn leads to a huge RHS for Stream.++, so it+-- doesn't get inlined at the final call site and fusion fails to occur.+ Ghc-Options: -finline-if-enough-args+ +-- It's probably a good idea to compile the library with -O2 as well. However, it's probably+-- not as essential as you think because most of the optimisation occurs when the library+-- functions from here are inlined into the user programs (which SHOULD be compiled with -O2!).+--+-- We have to fiddle with the assertion stuff at this point too because -O2 implies -fno-ignore-asserts,+-- meaning that their relative ordering is CRUCIAL. Setting them together guarantees it.+ if flag(enableassertions)+ -- Asserts are ignored by default at -O1 or higher+ Ghc-Options: -O2 -fno-ignore-asserts+ else+ Ghc-Options: -O2