packages feed

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 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