repa-stream 4.0.0.1 → 4.1.0.1
raw patch · 8 files changed
+632/−125 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Repa.Stream: catMaybesS :: Monad m => Stream m (Maybe a) -> Stream m a
+ Data.Repa.Stream: compactInS :: Monad m => (a -> a -> (Maybe a, a)) -> Stream m a -> Stream m a
+ Data.Repa.Stream: compactS :: Monad m => (s -> a -> (Maybe b, s)) -> s -> Stream m a -> Stream m b
+ Data.Repa.Stream: insertS :: Monad m => (Int -> Maybe a) -> Stream m a -> Stream m a
+ Data.Repa.Vector.Generic: Folds :: !sLens -> !sVals -> !(Option n) -> !Int -> !b -> Folds sLens sVals n a b
+ Data.Repa.Vector.Generic: _lenSeg :: Folds sLens sVals n a b -> !Int
+ Data.Repa.Vector.Generic: _nameSeg :: Folds sLens sVals n a b -> !(Option n)
+ Data.Repa.Vector.Generic: _stateLens :: Folds sLens sVals n a b -> !sLens
+ Data.Repa.Vector.Generic: _stateVals :: Folds sLens sVals n a b -> !sVals
+ Data.Repa.Vector.Generic: _valSeg :: Folds sLens sVals n a b -> !b
+ Data.Repa.Vector.Generic: compact :: (Vector v a, Vector v b) => (s -> a -> (Maybe b, s)) -> s -> v a -> v b
+ Data.Repa.Vector.Generic: compactIn :: Vector v a => (a -> a -> (Maybe a, a)) -> v a -> v a
+ Data.Repa.Vector.Generic: data Folds sLens sVals n a b
+ Data.Repa.Vector.Generic: diceSep :: (Vector v a, Vector v (Int, Int)) => (a -> Bool) -> (a -> Bool) -> v a -> (v (Int, Int), v (Int, Int))
+ Data.Repa.Vector.Generic: extract :: (Vector v (Int, Int), Vector v a) => (Int -> a) -> v (Int, Int) -> v a
+ Data.Repa.Vector.Generic: findSegments :: (Vector v a, Vector v Int, Vector v (Int, Int)) => (a -> Bool) -> (a -> Bool) -> v a -> (v Int, v Int)
+ Data.Repa.Vector.Generic: findSegmentsFrom :: (Vector v Int, Vector v (Int, Int)) => (a -> Bool) -> (a -> Bool) -> Int -> (Int -> a) -> (v Int, v Int)
+ Data.Repa.Vector.Generic: folds :: (Vector v (n, Int), Vector v a, Vector v (n, b)) => (a -> b -> b) -> b -> Option3 n Int b -> v (n, Int) -> v a -> (v (n, b), Folds Int Int n a b)
+ Data.Repa.Vector.Generic: groupsBy :: (Vector v1 a, Vector v2 (a, Int)) => (a -> a -> Bool) -> Maybe (a, Int) -> v1 a -> (v2 (a, Int), Maybe (a, Int))
+ Data.Repa.Vector.Generic: insert :: Vector v a => (Int -> Maybe a) -> v a -> v a
+ Data.Repa.Vector.Generic: merge :: (Ord k, Vector v k, Vector v (k, a), Vector v (k, b), Vector v (k, c)) => (k -> a -> b -> c) -> (k -> a -> c) -> (k -> b -> c) -> v (k, a) -> v (k, b) -> v (k, c)
+ Data.Repa.Vector.Generic: mergeMaybe :: (Ord k, Vector v k, Vector v (k, a), Vector v (k, b), Vector v (k, c)) => (k -> a -> b -> Maybe c) -> (k -> a -> Maybe c) -> (k -> b -> Maybe c) -> v (k, a) -> v (k, b) -> v (k, c)
+ Data.Repa.Vector.Generic: padForward :: (Ord k, Vector v (k, a)) => (k -> k) -> v (k, a) -> v (k, a)
+ Data.Repa.Vector.Generic: ratchet :: (Vector v Int, Vector v (Int, Int)) => v (Int, Int) -> (v Int, v Int)
+ Data.Repa.Vector.Generic: scanMaybe :: (Vector v1 a, Vector v2 b) => (s -> a -> (s, Maybe b)) -> s -> v1 a -> (v2 b, s)
+ Data.Repa.Vector.Unboxed: compact :: (Unbox a, Unbox b) => (s -> a -> (Maybe b, s)) -> s -> Vector a -> Vector b
+ Data.Repa.Vector.Unboxed: compactIn :: Unbox a => (a -> a -> (Maybe a, a)) -> Vector a -> Vector a
+ Data.Repa.Vector.Unboxed: insert :: Unbox a => (Int -> Maybe a) -> Vector a -> Vector a
+ Data.Repa.Vector.Unboxed: mergeMaybe :: (Ord k, Unbox k, Unbox a, Unbox b, Unbox c) => (k -> a -> b -> Maybe c) -> (k -> a -> Maybe c) -> (k -> b -> Maybe c) -> Vector (k, a) -> Vector (k, b) -> Vector (k, c)
- Data.Repa.Stream: unsafeRatchetS :: IOVector Int -> Vector Int -> IORef (IOVector Int) -> Stream IO Int
+ Data.Repa.Stream: unsafeRatchetS :: (MVector vm Int, Vector vv Int) => vm (PrimState IO) Int -> vv Int -> IORef (vm (PrimState IO) Int) -> Stream IO Int
Files
- Data/Repa/Stream.hs +9/−2
- Data/Repa/Stream/Compact.hs +69/−0
- Data/Repa/Stream/Concat.hs +28/−0
- Data/Repa/Stream/Insert.hs +38/−0
- Data/Repa/Stream/Ratchet.hs +12/−12
- Data/Repa/Vector/Generic.hs +393/−12
- Data/Repa/Vector/Unboxed.hs +75/−95
- repa-stream.cabal +8/−4
Data/Repa/Stream.hs view
@@ -3,7 +3,11 @@ -- functions can be used. module Data.Repa.Stream ( extractS+ , insertS , mergeS+ , compactS+ , compactInS+ , catMaybesS , findSegmentsS , diceSepS , startLengthsOfSegsS@@ -13,10 +17,13 @@ , unsafeRatchetS) where+import Data.Repa.Stream.Concat+import Data.Repa.Stream.Compact+import Data.Repa.Stream.Dice import Data.Repa.Stream.Extract+import Data.Repa.Stream.Insert import Data.Repa.Stream.Merge+import Data.Repa.Stream.Pad import Data.Repa.Stream.Ratchet import Data.Repa.Stream.Segment-import Data.Repa.Stream.Dice-import Data.Repa.Stream.Pad
+ Data/Repa/Stream/Compact.hs view
@@ -0,0 +1,69 @@++module Data.Repa.Stream.Compact+ ( compactS+ , compactInS )+where+import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))+import qualified Data.Vector.Fusion.Stream.Size as S+#include "repa-stream.h"+++-- | Combination of `fold` and `filter`. +-- +-- We walk over the stream front to back, maintaining an accumulator.+-- At each point we can chose to emit an element (or not)+--+compactS+ :: Monad m+ => (s -> a -> (Maybe b, s)) -- ^ Worker function.+ -> s -- ^ Starting state+ -> Stream m a -- ^ Input elements.+ -> Stream m b++compactS f s0 (Stream istep si0 sz)+ = Stream ostep (si0, s0) (S.toMax sz)+ where+ ostep (si, s)+ = istep si >>= \m+ -> case m of+ Yield x si' + -> case f s x of+ (Nothing, s') -> return $ Skip (si', s')+ (Just y, s') -> return $ Yield y (si', s')++ Skip si' -> return $ Skip (si', s)+ Done -> return $ Done+ {-# INLINE_INNER ostep #-}+{-# INLINE_STREAM compactS #-}+++-- | Like `compact` but use the first value of the stream as the +-- initial state, and add the final state to the end of the output.+compactInS+ :: Monad m+ => (a -> a -> (Maybe a, a)) -- ^ Worker function.+ -> Stream m a -- ^ Input elements.+ -> Stream m a++compactInS f (Stream istep si0 sz)+ = Stream ostep (si0, Nothing) (S.toMax sz)+ where+ ostep (si, ms@Nothing)+ = istep si >>= \m+ -> case m of+ Yield x si' -> return $ Skip (si', Just x)+ Skip si' -> return $ Skip (si', ms)+ Done -> return $ Done++ ostep (si, ms@(Just s))+ = istep si >>= \m+ -> case m of+ Yield x si' + -> case f s x of+ (Nothing, s') -> return $ Skip (si', Just s')+ (Just y, s') -> return $ Yield y (si', Just s')++ Skip si' -> return $ Skip (si', ms)+ Done -> return $ Yield s (si, Nothing)+ {-# INLINE_INNER ostep #-}+{-# INLINE_STREAM compactInS #-}
+ Data/Repa/Stream/Concat.hs view
@@ -0,0 +1,28 @@++module Data.Repa.Stream.Concat+ (catMaybesS)+where+import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))+import qualified Data.Vector.Fusion.Stream.Size as S+#include "repa-stream.h"+++-- | Return the `Just` elements from a stream, dropping the `Nothing`s.+catMaybesS+ :: Monad m+ => Stream m (Maybe a)+ -> Stream m a++catMaybesS (Stream istep si0 sz)+ = Stream ostep si0 (S.toMax sz)+ where+ ostep si+ = istep si >>= \m+ -> case m of+ Yield Nothing si' -> return $ Skip si'+ Yield (Just x) si' -> return $ Yield x si'+ Skip si' -> return $ Skip si'+ Done -> return $ Done+ {-# INLINE_INNER ostep #-}+{-# INLINE_STREAM catMaybesS #-}+
+ Data/Repa/Stream/Insert.hs view
@@ -0,0 +1,38 @@++module Data.Repa.Stream.Insert+ (insertS)+where+import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))+import qualified Data.Vector.Fusion.Stream.Size as S+#include "repa-stream.h"+++-- | Insert elements produced by the given function in to a stream.+insertS :: Monad m+ => (Int -> Maybe a) -- ^ Produce a new element for this index.+ -> Stream m a -- ^ Source stream.+ -> Stream m a++insertS fNew (Stream istep si0 _)+ = Stream ostep (si0, 0, True, False) S.Unknown+ where+ ostep (si, ix, tryNew, srcDone)+ | tryNew+ = case fNew ix of+ Just x -> return $ Yield x (si, ix + 1, True, srcDone)+ Nothing+ | srcDone -> return Done+ | otherwise -> ostep_next si ix++ | otherwise+ = ostep_next si ix+ {-# INLINE_INNER ostep #-}++ ostep_next !si !ix+ = istep si >>= \m+ -> case m of+ Yield x si' -> return $ Yield x (si', ix + 1, True, False)+ Skip si' -> return $ Skip (si', ix, False, False)+ Done -> return $ Skip (si, ix, True, True)+ {-# INLINE_INNER ostep_next #-}+{-# INLINE_STREAM insertS #-}
Data/Repa/Stream/Ratchet.hs view
@@ -2,12 +2,11 @@ module Data.Repa.Stream.Ratchet ( unsafeRatchetS) where+import Control.Monad.Primitive import Data.IORef import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))-import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic as GV import qualified Data.Vector.Generic.Mutable as GM-import qualified Data.Vector.Unboxed as U-import qualified Data.Vector.Unboxed.Mutable as UM import qualified Data.Vector.Fusion.Stream.Size as S #include "repa-stream.h" @@ -42,9 +41,10 @@ -- but this is not checked. -- unsafeRatchetS - :: UM.IOVector Int -- ^ Starting values. Overwritten duing computation.- -> U.Vector Int -- ^ Ending values- -> IORef (UM.IOVector Int) -- ^ Vector holding segment lengths.+ :: (GM.MVector vm Int, GV.Vector vv Int)+ => vm (PrimState IO) Int -- ^ Starting values. Overwritten duing computation.+ -> vv Int -- ^ Ending values+ -> IORef (vm (PrimState IO) Int) -- ^ Vector holding segment lengths. -> Stream IO Int unsafeRatchetS !mvStarts !vMax !rmvLens@@ -59,7 +59,7 @@ ostep' !iSeg !mvmLens !oSeg !oLen | iSeg <= iSegMax = do !iVal <- GM.unsafeRead mvStarts iSeg- let !iNext = vMax `G.unsafeIndex` iSeg+ let !iNext = vMax `GV.unsafeIndex` iSeg if iVal >= iNext then return $ Skip (iSeg + 1, mvmLens, oSeg, oLen) else do@@ -75,16 +75,16 @@ Just vmLens -> return $ vmLens -- If the output vector is full then we need to grow it.- let !oSegLen = UM.length vmLens+ let !oSegLen = GM.length vmLens if oSeg >= oSegLen then do- !vmLens' <- UM.unsafeGrow vmLens (UM.length vmLens)+ !vmLens' <- GM.unsafeGrow vmLens (GM.length vmLens) writeIORef rmvLens vmLens'- UM.unsafeWrite vmLens' oSeg oLen+ GM.unsafeWrite vmLens' oSeg oLen return $ Skip (0, Just vmLens', oSeg + 1, 0) else do- UM.unsafeWrite vmLens oSeg oLen+ GM.unsafeWrite vmLens oSeg oLen return $ Skip (0, Just vmLens, oSeg + 1, 0) | otherwise@@ -92,7 +92,7 @@ Nothing -> readIORef rmvLens Just vmLens -> return $ vmLens - let !vmLens' = UM.unsafeSlice 0 oSeg vmLens+ let !vmLens' = GM.unsafeSlice 0 oSeg vmLens writeIORef rmvLens vmLens' return Done {-# INLINE_INNER ostep' #-}
Data/Repa/Vector/Generic.hs view
@@ -11,14 +11,62 @@ -- * Chain functions , chainOfVector , unchainToVector- , unchainToMVector)+ , unchainToMVector++ -- * Generating+ , ratchet++ -- * Extracting+ , extract++ -- * Inserting+ , insert++ -- * Merging+ , merge+ , mergeMaybe++ -- * Splitting+ , findSegments+ , findSegmentsFrom+ , diceSep++ -- * Compacting+ , compact+ , compactIn++ -- * Padding+ , padForward++ -- * Scanning+ , scanMaybe++ -- * Grouping+ , groupsBy++ -- * Folding+ , folds, C.Folds(..)) where+import Data.Repa.Stream.Compact+import Data.Repa.Stream.Concat+import Data.Repa.Stream.Dice+import Data.Repa.Stream.Extract+import Data.Repa.Stream.Insert+import Data.Repa.Stream.Merge+import Data.Repa.Stream.Pad+import Data.Repa.Stream.Ratchet+import Data.Repa.Stream.Segment+import Data.Repa.Option+import Data.IORef+import System.IO.Unsafe+import Control.Monad.ST+import Control.Monad.Primitive import Data.Repa.Chain as C import qualified Data.Vector.Generic as GV import qualified Data.Vector.Generic.Mutable as GM-import qualified Data.Vector.Fusion.Stream.Monadic as S+import qualified Data.Vector.Fusion.Stream.Monadic as SM import qualified Data.Vector.Fusion.Stream.Size as S-import Control.Monad.Primitive+import qualified Data.Vector.Fusion.Stream as S #include "repa-stream.h" @@ -29,7 +77,7 @@ -- unstreamToVector2 :: (PrimMonad m, GV.Vector v a, GV.Vector v b)- => S.Stream m (Maybe a, Maybe b)+ => SM.Stream m (Maybe a, Maybe b) -- ^ Source data. -> m (v a, v b) -- ^ Resulting vectors. @@ -47,12 +95,12 @@ -- unstreamToMVector2 :: (PrimMonad m, GM.MVector v a, GM.MVector v b)- => S.Stream m (Maybe a, Maybe b) + => SM.Stream m (Maybe a, Maybe b) -- ^ Source data. -> m (v (PrimState m) a, v (PrimState m) b) -- ^ Resulting vectors. -unstreamToMVector2 (S.Stream step s0 sz)+unstreamToMVector2 (SM.Stream step s0 sz) = case sz of S.Exact i -> unstreamToMVector2_max i s0 step S.Max i -> unstreamToMVector2_max i s0 step@@ -66,7 +114,7 @@ go !sPEC !iL !iR !s = step s >>= \m -> case m of- S.Yield (mL, mR) s'+ SM.Yield (mL, mR) s' -> do !iL' <- case mL of Nothing -> return iL Just xL -> do GM.unsafeWrite vecL iL xL@@ -79,13 +127,13 @@ go sPEC iL' iR' s' - S.Skip s' + SM.Skip s' -> go sPEC iL iR s' - S.Done+ SM.Done -> return ( GM.unsafeSlice 0 iL vecL , GM.unsafeSlice 0 iR vecR)- in go S.SPEC 0 0 s0+ in go SM.SPEC 0 0 s0 {-# INLINE_STREAM unstreamToMVector2_max #-} @@ -151,7 +199,7 @@ Done s' -> return (GM.unsafeSlice 0 i vec, s') {-# INLINE_INNER go #-} - in go S.SPEC 0 s0+ in go SM.SPEC 0 s0 {-# INLINE_STREAM unchainToMVector_max #-} @@ -176,6 +224,339 @@ Done s' -> return (GM.unsafeSlice 0 i vec, s') {-# INLINE_INNER go #-} - in go S.SPEC vec0 0 nStart s0+ in go SM.SPEC vec0 0 nStart s0 {-# INLINE_STREAM unchainToMVector_unknown #-}+++-------------------------------------------------------------------------------+-- | Interleaved `enumFromTo`. +--+-- Given a vector of starting values, and a vector of stopping values, +-- produce an stream of elements where we increase each of the starting+-- values to the stopping values in a round-robin order. Also produce a+-- vector of result segment lengths.+--+-- @+-- unsafeRatchetS [10,20,30,40] [15,26,33,47]+-- = [10,20,30,40 -- 4+-- ,11,21,31,41 -- 4+-- ,12,22,32,42 -- 4+-- ,13,23 ,43 -- 3+-- ,14,24 ,44 -- 3+-- ,25 ,45 -- 2+-- ,46] -- 1+--+-- ^^^^ ^^^+-- Elements Lengths+-- @+--+ratchet :: (GV.Vector v Int, GV.Vector v (Int, Int))+ => v (Int, Int) -- ^ Starting and ending values.+ -> (v Int, v Int) -- ^ Elements and Lengths vectors.+ratchet vStartsMax + = unsafePerformIO+ $ do + -- Make buffers for the start values and unpack the max values.+ let (vStarts, vMax) = GV.unzip vStartsMax+ mvStarts <- GV.thaw vStarts++ -- Make a vector for the output lengths.+ mvLens <- GM.unsafeNew (GV.length vStartsMax)+ rmvLens <- newIORef mvLens++ -- Run the computation+ mvStarts' <- GM.munstream $ unsafeRatchetS mvStarts vMax rmvLens++ -- Read back the output segment lengths and freeze everything.+ mvLens' <- readIORef rmvLens+ vStarts' <- GV.unsafeFreeze mvStarts'+ vLens' <- GV.unsafeFreeze mvLens'+ return (vStarts', vLens')+{-# INLINE ratchet #-}+++-------------------------------------------------------------------------------+-- | Extract segments from some source array and concatenate them.+-- +-- @+-- let arr = [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]+-- in extractS (index arr) [(0, 1), (3, 3), (2, 6)]+-- +-- => [10, 13, 14, 15, 12, 13, 14, 15, 16, 17]+-- @+--+extract :: (GV.Vector v (Int, Int), GV.Vector v a)+ => (Int -> a) -- ^ Function to get elements from the source.+ -> v (Int, Int) -- ^ Segment starts and lengths.+ -> v a -- ^ Result elements.++extract get vStartLen+ = GV.unstream $ extractS get $ GV.stream vStartLen+{-# INLINE extract #-}+++-------------------------------------------------------------------------------+-- | Insert elements produced by the given function into a vector.+insert :: GV.Vector v a+ => (Int -> Maybe a) -- ^ Produce a new element for this index.+ -> v a -- ^ Source vector.+ -> v a++insert fNew vec+ = GV.unstream $ insertS fNew $ GV.stream vec+{-# INLINE insert #-}+++-------------------------------------------------------------------------------+-- | Merge two pre-sorted key-value streams.+merge :: ( Ord k+ , GV.Vector v k+ , GV.Vector v (k, a)+ , GV.Vector v (k, b)+ , GV.Vector v (k, c))+ => (k -> a -> b -> c) -- ^ Combine two values with the same key.+ -> (k -> a -> c) -- ^ Handle a left value without a right value.+ -> (k -> b -> c) -- ^ Handle a right value without a left value.+ -> v (k, a) -- ^ Vector of keys and left values.+ -> v (k, b) -- ^ Vector of keys and right values.+ -> v (k, c) -- ^ Vector of keys and results.++merge fBoth fLeft fRight vA vB+ = GV.unstream + $ mergeS fBoth fLeft fRight + (GV.stream vA) + (GV.stream vB)+{-# INLINE merge #-}+++-- | Like `merge`, but only produce the elements where the worker functions+-- return `Just`.+mergeMaybe + :: ( Ord k+ , GV.Vector v k+ , GV.Vector v (k, a)+ , GV.Vector v (k, b)+ , GV.Vector v (k, c))+ => (k -> a -> b -> Maybe c) -- ^ Combine two values with the same key.+ -> (k -> a -> Maybe c) -- ^ Handle a left value without a right value.+ -> (k -> b -> Maybe c) -- ^ Handle a right value without a left value.+ -> v (k, a) -- ^ Vector of keys and left values.+ -> v (k, b) -- ^ Vector of keys and right values.+ -> v (k, c) -- ^ Vector of keys and results.++mergeMaybe fBoth fLeft fRight vA vB+ = GV.unstream+ $ catMaybesS+ $ SM.map munge_mergeMaybe+ $ mergeS fBoth fLeft fRight+ (GV.stream vA)+ (GV.stream vB)++ where munge_mergeMaybe (_k, Nothing) = Nothing+ munge_mergeMaybe (k, Just x) = Just (k, x)+ {-# INLINE munge_mergeMaybe #-}+{-# INLINE mergeMaybe #-}+++-------------------------------------------------------------------------------+-- | Perform a left-to-right scan through an input vector, maintaining a state+-- value between each element. For each element of input we may or may not+-- produce an element of output.+scanMaybe + :: forall v1 v2 a b s+ . (GV.Vector v1 a, GV.Vector v2 b)+ => (s -> a -> (s, Maybe b)) -- ^ Worker function.+ -> s -- ^ Initial state for scan.+ -> v1 a -- ^ Input elements.+ -> (v2 b, s) -- ^ Output elements.++scanMaybe f k0 vec0+ = (vec1, snd k1)+ where + f' s x = return $ f s x++ (vec1 :: v2 b, k1 :: (Int, s))+ = runST $ unchainToVector $ C.liftChain + $ C.scanMaybeC f' k0 $ chainOfVector vec0+{-# INLINE scanMaybe #-}+++-------------------------------------------------------------------------------+-- | From a stream of values which has consecutive runs of idential values,+-- produce a stream of the lengths of these runs.+-- +-- @+-- groupsBy (==) (Just ('a', 4)) +-- [\'a\', \'a\', \'a\', \'b\', \'b\', \'c\', \'d\', \'d\'] +-- => ([('a', 7), ('b', 2), ('c', 1)], Just (\'d\', 2))+-- @+--+groupsBy+ :: forall v1 v2 a+ . (GV.Vector v1 a, GV.Vector v2 (a, Int))+ => (a -> a -> Bool) -- ^ Comparison function.+ -> Maybe (a, Int) -- ^ Starting element and count.+ -> v1 a -- ^ Input elements.+ -> (v2 (a, Int), Maybe (a, Int))++groupsBy f !c !vec0+ = (vec1, snd k1)+ where + f' x y = return $ f x y++ (vec1 :: v2 (a, Int), k1)+ = runST $ unchainToVector $ C.liftChain + $ C.groupsByC f' c $ chainOfVector vec0+{-# INLINE groupsBy #-}+++-------------------------------------------------------------------------------+-- | Given predicates that detect the beginning and end of some interesting+-- segment of information, scan through a vector looking for when these+-- segments begin and end. Return vectors of the segment starting positions+-- and lengths.+--+-- * As each segment must end on a element where the ending predicate returns+-- True, the miniumum segment length returned is 1.+--+findSegments + :: (GV.Vector v a, GV.Vector v Int, GV.Vector v (Int, Int))+ => (a -> Bool) -- ^ Predicate to check for start of segment.+ -> (a -> Bool) -- ^ Predicate to check for end of segment.+ -> v a -- ^ Input vector.+ -> (v Int, v Int)++findSegments pStart pEnd src+ = GV.unzip+ $ GV.unstream+ $ startLengthsOfSegsS+ $ findSegmentsS pStart pEnd (GV.length src - 1)+ $ SM.indexed + $ GV.stream src+{-# INLINE findSegments #-}+++-------------------------------------------------------------------------------+-- | Given predicates that detect the beginning and end of some interesting+-- segment of information, scan through a vector looking for when these+-- segments begin and end. Return vectors of the segment starting positions+-- and lengths.+findSegmentsFrom+ :: (GV.Vector v Int, GV.Vector v (Int, Int))+ => (a -> Bool) -- ^ Predicate to check for start of segment.+ -> (a -> Bool) -- ^ Predicate to check for end of segment.+ -> Int -- ^ Input length.+ -> (Int -> a) -- ^ Get an element from the input.+ -> (v Int, v Int)++findSegmentsFrom pStart pEnd len get+ = GV.unzip+ $ GV.unstream+ $ startLengthsOfSegsS+ $ findSegmentsS pStart pEnd (len - 1)+ $ SM.map (\ix -> (ix, get ix))+ $ SM.enumFromStepN 0 1 len+{-# INLINE findSegmentsFrom #-}+++-------------------------------------------------------------------------------+-- | Dice a vector stream into rows and columns.+--+diceSep :: (GV.Vector v a, GV.Vector v (Int, Int))+ => (a -> Bool) -- ^ Detect the end of a column.+ -> (a -> Bool) -- ^ Detect the end of a row.+ -> v a+ -> (v (Int, Int), v (Int, Int)) -- ^ Segment starts and lengths++diceSep pEndInner pEndBoth vec+ = runST+ $ unstreamToVector2+ $ diceSepS pEndInner pEndBoth + $ S.liftStream+ $ GV.stream vec+{-# INLINE diceSep #-}+++-------------------------------------------------------------------------------+-- | Combination of `fold` and `filter`. +-- +-- We walk over the stream front to back, maintaining an accumulator.+-- At each point we can chose to emit an element (or not)+--+compact+ :: (GV.Vector v a, GV.Vector v b)+ => (s -> a -> (Maybe b, s)) -- ^ Worker function+ -> s -- ^ Starting state+ -> v a -- ^ Input vector+ -> v b++compact f s0 vec+ = GV.unstream $ compactS f s0 $ GV.stream vec+{-# INLINE compact #-}+++-- | Like `compact` but use the first value of the stream as the +-- initial state, and add the final state to the end of the output.+compactIn+ :: GV.Vector v a+ => (a -> a -> (Maybe a, a)) -- ^ Worker function.+ -> v a -- ^ Input elements.+ -> v a++compactIn f vec+ = GV.unstream $ compactInS f $ GV.stream vec+{-# INLINE compactIn #-}+++-------------------------------------------------------------------------------+-- | Segmented fold over vectors of segment lengths and input values.+--+-- The total lengths of all segments need not match the length of the+-- input elements vector. The returned `C.Folds` state can be inspected+-- to determine whether all segments were completely folded, or the +-- vector of segment lengths or elements was too short relative to the+-- other. In the resulting state, `C.foldLensState` is the index into+-- the lengths vector *after* the last one that was consumed. If this+-- equals the length of the lengths vector then all segment lengths were+-- consumed. Similarly for the elements vector.+--+folds :: forall v n a b+ . (GV.Vector v (n, Int), GV.Vector v a, GV.Vector v (n, b))+ => (a -> b -> b) -- ^ Worker function to fold each segment.+ -> b -- ^ Initial state when folding segments.+ -> Option3 n Int b -- ^ Length and initial state for first segment.+ -> v (n, Int) -- ^ Segment names and lengths.+ -> v a -- ^ Elements.+ -> (v (n, b), C.Folds Int Int n a b)++folds f zN s0 vLens vVals+ = let + f' x y = return $ f x y+ {-# INLINE f' #-}++ (vResults :: v (n, b), state) + = runST $ unchainToVector+ $ C.foldsC f' zN s0+ (chainOfVector vLens)+ (chainOfVector vVals)++ in (vResults, state)+{-# INLINE folds #-}+++-------------------------------------------------------------------------------+-- | Given a stream of keys and values, and a successor function for keys, +-- if the stream is has keys missing in the sequence then insert +-- the missing key, copying forward the the previous value.+padForward + :: (Ord k, GV.Vector v (k, a))+ => (k -> k) -- ^ Successor function.+ -> v (k, a) -- ^ Input keys and values.+ -> v (k, a)++padForward ksucc vec+ = GV.unstream+ $ padForwardS ksucc+ $ GV.stream vec+{-# INLINE padForward #-}
Data/Repa/Vector/Unboxed.hs view
@@ -5,24 +5,31 @@ , unchainToVector , unchainToMVector - -- * Generators+ -- * Generating , ratchet - -- * Extract+ -- * Extracting , extract + -- * Inserting+ , insert+ -- * Merging , merge+ , mergeMaybe -- * Splitting , findSegments , findSegmentsFrom , diceSep + -- * Compacting+ , compact+ , compactIn+ -- * Padding , padForward - -- * Scanning , scanMaybe @@ -33,26 +40,13 @@ , folds, C.Folds(..)) where import Data.Repa.Option-import Data.Repa.Stream.Extract-import Data.Repa.Stream.Ratchet-import Data.Repa.Stream.Segment-import Data.Repa.Stream.Dice-import Data.Repa.Stream.Merge-import Data.Repa.Stream.Pad import Data.Vector.Unboxed (Unbox, Vector) import Data.Vector.Unboxed.Mutable (MVector) import Data.Repa.Chain (Chain) import qualified Data.Repa.Vector.Generic as G import qualified Data.Repa.Chain as C import qualified Data.Vector.Unboxed as U-import qualified Data.Vector.Unboxed.Mutable as UM-import qualified Data.Vector.Generic as G-import qualified Data.Vector.Generic.Mutable as GM-import qualified Data.Vector.Fusion.Stream as S-import Control.Monad.ST import Control.Monad.Primitive-import System.IO.Unsafe-import Data.IORef #include "repa-stream.h" @@ -82,7 +76,6 @@ {-# INLINE unchainToMVector #-} - ------------------------------------------------------------------------------- -- | Interleaved `enumFromTo`. --@@ -107,25 +100,7 @@ -- ratchet :: U.Vector (Int, Int) -- ^ Starting and ending values. -> (U.Vector Int, U.Vector Int) -- ^ Elements and Lengths vectors.-ratchet vStartsMax - = unsafePerformIO- $ do - -- Make buffers for the start values and unpack the max values.- let (vStarts, vMax) = U.unzip vStartsMax- mvStarts <- U.thaw vStarts-- -- Make a vector for the output lengths.- mvLens <- UM.unsafeNew (U.length vStartsMax)- rmvLens <- newIORef mvLens-- -- Run the computation- mvStarts' <- GM.munstream $ unsafeRatchetS mvStarts vMax rmvLens-- -- Read back the output segment lengths and freeze everything.- mvLens' <- readIORef rmvLens- vStarts' <- G.unsafeFreeze mvStarts'- vLens' <- G.unsafeFreeze mvLens'- return (vStarts', vLens')+ratchet = G.ratchet {-# INLINE ratchet #-} @@ -144,12 +119,22 @@ -> U.Vector (Int, Int) -- ^ Segment starts and lengths. -> U.Vector a -- ^ Result elements. -extract get vStartLen- = G.unstream $ extractS get $ G.stream vStartLen+extract = G.extract {-# INLINE extract #-} -------------------------------------------------------------------------------+-- | Insert elements produced by the given function into a vector.+insert :: Unbox a+ => (Int -> Maybe a) -- ^ Produce a new element for this index.+ -> U.Vector a -- ^ Source vector.+ -> U.Vector a++insert = G.insert+{-# INLINE insert #-}+++------------------------------------------------------------------------------- -- | Merge two pre-sorted key-value streams. merge :: (Ord k, Unbox k, Unbox a, Unbox b, Unbox c) => (k -> a -> b -> c) -- ^ Combine two values with the same key.@@ -159,14 +144,25 @@ -> U.Vector (k, b) -- ^ Vector of keys and right values. -> U.Vector (k, c) -- ^ Vector of keys and results. -merge fBoth fLeft fRight vA vB- = G.unstream - $ mergeS fBoth fLeft fRight - (G.stream vA) - (G.stream vB)+merge = G.merge {-# INLINE merge #-} +-- | Like `merge`, but only produce the elements where the worker functions+-- return `Just`.+mergeMaybe + :: (Ord k, Unbox k, Unbox a, Unbox b, Unbox c)+ => (k -> a -> b -> Maybe c) -- ^ Combine two values with the same key.+ -> (k -> a -> Maybe c) -- ^ Handle a left value without a right value.+ -> (k -> b -> Maybe c) -- ^ Handle a right value without a left value.+ -> U.Vector (k, a) -- ^ Vector of keys and left values.+ -> U.Vector (k, b) -- ^ Vector of keys and right values.+ -> U.Vector (k, c) -- ^ Vector of keys and results.++mergeMaybe = G.mergeMaybe+{-# INLINE mergeMaybe #-}++ ------------------------------------------------------------------------------- -- | Perform a left-to-right scan through an input vector, maintaining a state -- value between each element. For each element of input we may or may not@@ -178,14 +174,7 @@ -> U.Vector a -- ^ Input elements. -> (U.Vector b, s) -- ^ Output elements. -scanMaybe f k0 vec0- = (vec1, snd k1)- where - f' s x = return $ f s x-- (vec1, k1)- = runST $ unchainToVector $ C.liftChain - $ C.scanMaybeC f' k0 $ chainOfVector vec0+scanMaybe = G.scanMaybe {-# INLINE scanMaybe #-} @@ -206,14 +195,7 @@ -> U.Vector a -- ^ Input elements. -> (U.Vector (a, Int), Maybe (a, Int)) -groupsBy f !c !vec0- = (vec1, snd k1)- where - f' x y = return $ f x y-- (vec1, k1)- = runST $ unchainToVector $ C.liftChain - $ C.groupsByC f' c $ chainOfVector vec0+groupsBy = G.groupsBy {-# INLINE groupsBy #-} @@ -233,13 +215,7 @@ -> U.Vector a -- ^ Input vector. -> (U.Vector Int, U.Vector Int) -findSegments pStart pEnd src- = U.unzip- $ G.unstream- $ startLengthsOfSegsS- $ findSegmentsS pStart pEnd (U.length src - 1)- $ S.indexed - $ G.stream src+findSegments = G.findSegments {-# INLINE findSegments #-} @@ -255,13 +231,7 @@ -> (Int -> a) -- ^ Get an element from the input. -> (U.Vector Int, U.Vector Int) -findSegmentsFrom pStart pEnd len get- = U.unzip- $ G.unstream- $ startLengthsOfSegsS- $ findSegmentsS pStart pEnd (len - 1)- $ S.map (\ix -> (ix, get ix))- $ S.enumFromStepN 0 1 len+findSegmentsFrom = G.findSegmentsFrom {-# INLINE findSegmentsFrom #-} @@ -275,16 +245,40 @@ -> (U.Vector (Int, Int), U.Vector (Int, Int)) -- ^ Segment starts and lengths -diceSep pEndInner pEndBoth vec- = runST- $ G.unstreamToVector2- $ diceSepS pEndInner pEndBoth - $ S.liftStream- $ G.stream vec+diceSep = G.diceSep {-# INLINE diceSep #-} -------------------------------------------------------------------------------+-- | Combination of `fold` and `filter`. +-- +-- We walk over the stream front to back, maintaining an accumulator.+-- At each point we can chose to emit an element (or not)+--+compact+ :: (Unbox a, Unbox b)+ => (s -> a -> (Maybe b, s)) -- ^ Worker function+ -> s -- ^ Starting state+ -> Vector a -- ^ Input vector+ -> Vector b++compact = G.compact+{-# INLINE compact #-}+++-- | Like `compact` but use the first value of the stream as the +-- initial state, and add the final state to the end of the output.+compactIn+ :: Unbox a+ => (a -> a -> (Maybe a, a)) -- ^ Worker function.+ -> Vector a -- ^ Input elements.+ -> Vector a++compactIn = G.compactIn+{-# INLINE compactIn #-}+++------------------------------------------------------------------------------- -- | Segmented fold over vectors of segment lengths and input values. -- -- The total lengths of all segments need not match the length of the@@ -304,18 +298,7 @@ -> U.Vector a -- ^ Elements. -> (U.Vector (n, b), C.Folds Int Int n a b) -folds f zN s0 vLens vVals- = let - f' x y = return $ f x y- {-# INLINE f' #-}-- (vResults, state) - = runST $ unchainToVector- $ C.foldsC f' zN s0- (chainOfVector vLens)- (chainOfVector vVals)-- in (vResults, state)+folds = G.folds {-# INLINE folds #-} @@ -329,9 +312,6 @@ -> U.Vector (k, v) -- ^ Input keys and values. -> U.Vector (k, v) -padForward ksucc vec- = G.unstream- $ padForwardS ksucc- $ G.stream vec+padForward = G.padForward {-# INLINE padForward #-}
repa-stream.cabal view
@@ -1,5 +1,5 @@ Name: repa-stream-Version: 4.0.0.1+Version: 4.1.0.1 License: BSD3 License-file: LICENSE Author: The Repa Development Team@@ -38,12 +38,15 @@ Data.Repa.Chain.Weave Data.Repa.Chain.Folds + Data.Repa.Stream.Compact+ Data.Repa.Stream.Concat+ Data.Repa.Stream.Dice Data.Repa.Stream.Extract+ Data.Repa.Stream.Insert+ Data.Repa.Stream.Merge+ Data.Repa.Stream.Pad Data.Repa.Stream.Ratchet Data.Repa.Stream.Segment- Data.Repa.Stream.Dice- Data.Repa.Stream.Pad- Data.Repa.Stream.Merge include-dirs: include@@ -63,5 +66,6 @@ FlexibleContexts PatternGuards MultiWayIf+ ScopedTypeVariables