repa-stream 4.1.0.1 → 4.2.2.1
raw patch · 13 files changed
+460/−417 lines, 13 filesdep +repa-scalardep ~basedep ~primitivePVP ok
version bump matches the API change (PVP)
Dependencies added: repa-scalar
Dependency ranges changed: base, primitive
API changes (from Hackage documentation)
- Data.Repa.Chain: _lenSeg :: Folds sLens sVals n a b -> !Int
- Data.Repa.Chain: _nameSeg :: Folds sLens sVals n a b -> !(Option n)
- Data.Repa.Chain: _stateLens :: Folds sLens sVals n a b -> !sLens
- Data.Repa.Chain: _stateVals :: Folds sLens sVals n a b -> !sVals
- Data.Repa.Chain: _valSeg :: Folds sLens sVals n a b -> !b
- Data.Repa.Chain: mchainSize :: Chain m s a -> Size
- Data.Repa.Chain: mchainState :: Chain m s a -> s
- Data.Repa.Chain: mchainStep :: Chain m s a -> s -> m (Step s a)
- Data.Repa.Option: None :: Option a
- Data.Repa.Option: None2 :: Option2 a b
- Data.Repa.Option: None3 :: Option3 a b c
- Data.Repa.Option: Some :: !a -> Option a
- Data.Repa.Option: Some2 :: !a -> !b -> Option2 a b
- Data.Repa.Option: Some3 :: !a -> !b -> !c -> Option3 a b c
- Data.Repa.Option: data Option a
- Data.Repa.Option: data Option2 a b
- Data.Repa.Option: data Option3 a b c
- Data.Repa.Option: fromOption :: Option a -> Maybe a
- Data.Repa.Option: fromOption2 :: Option2 a b -> Maybe (a, b)
- Data.Repa.Option: fromOption3 :: Option3 a b c -> Maybe (a, b, c)
- Data.Repa.Option: instance (Show a, Show b) => Show (Option2 a b)
- Data.Repa.Option: instance (Show a, Show b, Show c) => Show (Option3 a b c)
- Data.Repa.Option: instance Show a => Show (Option a)
- Data.Repa.Option: toOption :: Maybe a -> Option a
- Data.Repa.Option: toOption2 :: Maybe (a, b) -> Option2 a b
- Data.Repa.Option: toOption3 :: Maybe (a, b, c) -> Option3 a b c
- 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.Unboxed: _lenSeg :: Folds sLens sVals n a b -> !Int
- Data.Repa.Vector.Unboxed: _nameSeg :: Folds sLens sVals n a b -> !(Option n)
- Data.Repa.Vector.Unboxed: _stateLens :: Folds sLens sVals n a b -> !sLens
- Data.Repa.Vector.Unboxed: _stateVals :: Folds sLens sVals n a b -> !sVals
- Data.Repa.Vector.Unboxed: _valSeg :: Folds sLens sVals n a b -> !b
+ Data.Repa.Chain: StepUnfoldBump :: s -> StepUnfold s a
+ Data.Repa.Chain: StepUnfoldFinish :: s -> StepUnfold s a
+ Data.Repa.Chain: StepUnfoldGive :: a -> s -> StepUnfold s a
+ Data.Repa.Chain: StepUnfoldNext :: a -> s -> StepUnfold s a
+ Data.Repa.Chain: [_lenSeg] :: Folds sLens sVals n a b -> !Int
+ Data.Repa.Chain: [_nameSeg] :: Folds sLens sVals n a b -> !(Option n)
+ Data.Repa.Chain: [_stateLens] :: Folds sLens sVals n a b -> !sLens
+ Data.Repa.Chain: [_stateVals] :: Folds sLens sVals n a b -> !sVals
+ Data.Repa.Chain: [_valSeg] :: Folds sLens sVals n a b -> !b
+ Data.Repa.Chain: [mchainSize] :: Chain m s a -> Size
+ Data.Repa.Chain: [mchainState] :: Chain m s a -> s
+ Data.Repa.Chain: [mchainStep] :: Chain m s a -> s -> m (Step s a)
+ Data.Repa.Chain: data StepUnfold s a
+ Data.Repa.Chain: unfoldsC :: Monad m => (a -> k -> m (StepUnfold k b)) -> k -> Chain m s a -> Chain m (s, k, Option a) b
+ Data.Repa.Stream: replicatesS :: Monad m => Stream m (Int, a) -> Stream m a
+ 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: replicates :: (Vector v (Int, a), Vector v a) => v (Int, a) -> v a
+ Data.Repa.Vector.Unboxed: [_lenSeg] :: Folds sLens sVals n a b -> !Int
+ Data.Repa.Vector.Unboxed: [_nameSeg] :: Folds sLens sVals n a b -> !(Option n)
+ Data.Repa.Vector.Unboxed: [_stateLens] :: Folds sLens sVals n a b -> !sLens
+ Data.Repa.Vector.Unboxed: [_stateVals] :: Folds sLens sVals n a b -> !sVals
+ Data.Repa.Vector.Unboxed: [_valSeg] :: Folds sLens sVals n a b -> !b
- Data.Repa.Stream: compactInS :: Monad m => (a -> a -> (Maybe a, a)) -> Stream m a -> Stream m a
+ Data.Repa.Stream: compactInS :: Monad m => (a -> a -> (a, Maybe 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: compactS :: Monad m => (s -> a -> (s, Maybe b)) -> s -> Stream m a -> Stream m 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: compact :: (Vector v a, Vector v b) => (s -> a -> (s, Maybe b)) -> 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: compactIn :: Vector v a => (a -> a -> (a, Maybe a)) -> v a -> v a
- Data.Repa.Vector.Unboxed: compact :: (Unbox a, Unbox b) => (s -> a -> (Maybe b, s)) -> s -> Vector a -> Vector b
+ Data.Repa.Vector.Unboxed: compact :: (Unbox a, Unbox b) => (s -> a -> (s, Maybe b)) -> 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: compactIn :: Unbox a => (a -> a -> (a, Maybe a)) -> Vector a -> Vector a
Files
- Data/Repa/Chain.hs +4/−0
- Data/Repa/Chain/Folds.hs +1/−1
- Data/Repa/Chain/Scan.hs +52/−1
- Data/Repa/Chain/Weave.hs +1/−1
- Data/Repa/Option.hs +0/−86
- Data/Repa/Stream.hs +26/−8
- Data/Repa/Stream/Compact.hs +6/−8
- Data/Repa/Stream/Merge.hs +1/−1
- Data/Repa/Stream/Pad.hs +1/−1
- Data/Repa/Stream/Replicate.hs +40/−0
- Data/Repa/Vector/Generic.hs +294/−279
- Data/Repa/Vector/Unboxed.hs +28/−26
- repa-stream.cabal +6/−5
Data/Repa/Chain.hs view
@@ -14,6 +14,10 @@ -- * Folding , foldsC, Folds(..) + -- * Unfolding+ , unfoldsC+ , StepUnfold (..)+ -- * Scanning , scanMaybeC
Data/Repa/Chain/Folds.hs view
@@ -2,8 +2,8 @@ module Data.Repa.Chain.Folds (foldsC, Folds (..)) where-import Data.Repa.Option import Data.Repa.Chain.Base+import Data.Repa.Scalar.Option import Data.Vector.Fusion.Stream.Size as S #include "repa-stream.h"
Data/Repa/Chain/Scan.hs view
@@ -1,12 +1,63 @@ module Data.Repa.Chain.Scan- ( scanMaybeC+ ( StepUnfold (..)+ , unfoldsC+ , scanMaybeC , groupsByC) where import Data.Repa.Chain.Base+import Data.Repa.Scalar.Option import qualified Data.Vector.Fusion.Stream.Size as S #include "repa-stream.h" ++-------------------------------------------------------------------------------+-- | Segmented unfold.+-- +-- The worker function takes the current element from the input stream +-- and current state. +--+-- If the worker returns Just x then that output element will be placed+-- in the output stream, and it will be called again with the same+-- input elemenent and next state. +--+-- If the worker returns Nothing then we advance to the next element+-- of the input stream.+--+unfoldsC+ :: Monad m+ => (a -> k -> m (StepUnfold k b)) -- ^ Worker function.+ -> k -- ^ Initial state for the unfold.+ -> Chain m s a -- ^ Input elements.+ -> Chain m (s, k, Option a) b -- ^ Output elements.++unfoldsC f k0 (Chain _ s0 istep)+ = Chain S.Unknown (s0, k0, None) ostep+ where+ ostep (s1, k1, None)+ = istep s1 >>= \rs+ -> case rs of+ Yield xa s2 -> return $ Skip (s2, k1, Some xa)+ Skip s2 -> return $ Skip (s2, k1, None)+ Done s2 -> return $ Done (s2, k1, None)++ ostep (s1, k1, Some xa)+ = f xa k1 >>= \kmb+ -> case kmb of+ StepUnfoldGive xb k2 -> return $ Yield xb (s1, k2, Some xa)+ StepUnfoldNext xb k2 -> return $ Yield xb (s1, k2, None) + StepUnfoldBump k2 -> return $ Skip (s1, k2, Some xa)+ StepUnfoldFinish k2 -> return $ Skip (s1, k2, None)+ {-# INLINE_INNER ostep #-}+{-# INLINE_STREAM unfoldsC #-}+++data StepUnfold s a+ = StepUnfoldGive a s+ | StepUnfoldNext a s+ | StepUnfoldBump s+ | StepUnfoldFinish s+ deriving Show ------------------------------------------------------------------------------- -- | Perform a left-to-right scan through an input vector, maintaining a state
Data/Repa/Chain/Weave.hs view
@@ -6,8 +6,8 @@ , Move (..), move , Option (..)) where-import Data.Repa.Option import Data.Repa.Chain.Base+import Data.Repa.Scalar.Option import qualified Data.Vector.Fusion.Stream.Size as S #include "repa-stream.h"
− Data/Repa/Option.hs
@@ -1,86 +0,0 @@---- | Data types used during low-level fusion optimisations.--- --- These types are synonyms for @Maybe (a, b)@, which are strict in the--- components. They can be used to ensure that we do not suspend the--- computation that produces these components in fused code.----module Data.Repa.Option- ( -- * Single component- Option (..)- , fromOption, toOption-- -- * Two components- , Option2 (..)- , fromOption2, toOption2-- -- * Three components- , Option3 (..)- , fromOption3, toOption3)-where------------------------------------------------------------------------------------- | A strict `Maybe` type.-data Option a- = Some !a- | None - deriving Show---- | Convert a `Maybe` to an `Option`.-toOption :: Maybe a -> Option a-toOption Nothing = None-toOption (Just x) = Some x-{-# INLINE toOption #-}----- | Convert an `Option` to a `Maybe`.-fromOption :: Option a -> Maybe a-fromOption None = Nothing-fromOption (Some x) = Just x-{-# INLINE fromOption #-}------------------------------------------------------------------------------------- | A strict `Maybe` type, with two parameters.-data Option2 a b- = Some2 !a !b- | None2 - deriving Show----- | Convert a `Maybe` to an `Option2`.-toOption2 :: Maybe (a, b) -> Option2 a b-toOption2 Nothing = None2-toOption2 (Just (x, y)) = Some2 x y-{-# INLINE toOption2 #-}----- | Convert an `Option2` to a `Maybe`.-fromOption2 :: Option2 a b -> Maybe (a, b)-fromOption2 None2 = Nothing-fromOption2 (Some2 x y) = Just (x, y)-{-# INLINE fromOption2 #-}------------------------------------------------------------------------------------- | A strict `Maybe` type with three parameters.-data Option3 a b c- = Some3 !a !b !c- | None3 - deriving Show----- | Convert a `Maybe` to an `Option3`.-toOption3 :: Maybe (a, b, c) -> Option3 a b c-toOption3 Nothing = None3-toOption3 (Just (x, y, z)) = Some3 x y z-{-# INLINE toOption3 #-}----- | Convert an `Option2` to a `Maybe`.-fromOption3 :: Option3 a b c -> Maybe (a, b, c)-fromOption3 None3 = Nothing-fromOption3 (Some3 x y z) = Just (x, y, z)-{-# INLINE fromOption3 #-}-
Data/Repa/Stream.hs view
@@ -2,20 +2,37 @@ -- | * See the "Data.Repa.Vector.Unboxed" module for examples of how these -- functions can be used. module Data.Repa.Stream- ( extractS- , insertS- , mergeS- , compactS+ ( -- * Compacting+ compactS , compactInS++ -- * Concatenating , catMaybesS- , findSegmentsS++ -- * Dicing , diceSepS- , startLengthsOfSegsS++ -- * Extracting+ , extractS++ -- * Inserting+ , insertS++ -- * Merging+ , mergeS++ -- * Padding , padForwardS - -- * Unsafe operators- , unsafeRatchetS)+ -- * Ratcheting+ , unsafeRatchetS + -- * Replicating+ , replicatesS++ -- * Segmenting+ , findSegmentsS+ , startLengthsOfSegsS) where import Data.Repa.Stream.Concat import Data.Repa.Stream.Compact@@ -25,5 +42,6 @@ import Data.Repa.Stream.Merge import Data.Repa.Stream.Pad import Data.Repa.Stream.Ratchet+import Data.Repa.Stream.Replicate import Data.Repa.Stream.Segment
Data/Repa/Stream/Compact.hs view
@@ -15,7 +15,7 @@ -- compactS :: Monad m- => (s -> a -> (Maybe b, s)) -- ^ Worker function.+ => (s -> a -> (s, Maybe b)) -- ^ Worker function. -> s -- ^ Starting state -> Stream m a -- ^ Input elements. -> Stream m b@@ -28,9 +28,8 @@ -> 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')-+ (s', Nothing) -> return $ Skip (si', s')+ (s', Just y) -> return $ Yield y (si', s') Skip si' -> return $ Skip (si', s) Done -> return $ Done {-# INLINE_INNER ostep #-}@@ -41,7 +40,7 @@ -- initial state, and add the final state to the end of the output. compactInS :: Monad m- => (a -> a -> (Maybe a, a)) -- ^ Worker function.+ => (a -> a -> (a, Maybe a)) -- ^ Worker function. -> Stream m a -- ^ Input elements. -> Stream m a @@ -60,9 +59,8 @@ -> 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')-+ (s', Nothing) -> return $ Skip (si', Just s')+ (s', Just y) -> return $ Yield y (si', Just s') Skip si' -> return $ Skip (si', ms) Done -> return $ Yield s (si, Nothing) {-# INLINE_INNER ostep #-}
Data/Repa/Stream/Merge.hs view
@@ -3,7 +3,7 @@ (mergeS) where import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))-import Data.Repa.Option+import Data.Repa.Scalar.Option import qualified Data.Vector.Fusion.Stream.Size as S #include "repa-stream.h"
Data/Repa/Stream/Pad.hs view
@@ -3,7 +3,7 @@ (padForwardS) where import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))-import Data.Repa.Option+import Data.Repa.Scalar.Option import qualified Data.Vector.Fusion.Stream.Size as S #include "repa-stream.h"
+ Data/Repa/Stream/Replicate.hs view
@@ -0,0 +1,40 @@++module Data.Repa.Stream.Replicate+ (replicatesS)+where+import Data.Vector.Fusion.Stream.Monadic (Stream(..), Step(..))+import qualified Data.Vector.Fusion.Stream.Size as S+#include "repa-stream.h"+++-- | Segmented replicate.+-- +-- Given a stream of counts and values, produce a result stream where+-- each value is replciated the associated number of times.+--+replicatesS + :: Monad m+ => Stream m (Int, a)+ -> Stream m a++replicatesS (Stream istepA sA0 _)+ = Stream ostep (sA0, 0, Nothing) S.Unknown+ where+ -- Pull the next element from the source stream.+ ostep (sA, 0, mv)+ = istepA sA >>= \rA+ -> case rA of+ Done -> return Done+ Skip sA' -> return $ Skip (sA', 0, mv)+ Yield (len, val) sA' -> return $ Skip (sA', len, Just val)++ -- Should never be entered, as we'll always have a value+ -- when the count is non-zero.+ ostep (_, _, Nothing) + = return Done++ ostep (sA, len, mv@(Just val))+ = return $ Yield val (sA, len - 1, mv)+ {-# INLINE_INNER ostep #-}+{-# INLINE_STREAM replicatesS #-}+
Data/Repa/Vector/Generic.hs view
@@ -4,48 +4,49 @@ -- * NOTE: Support for streams of unknown length is not complete. -- module Data.Repa.Vector.Generic- ( -- * Stream functions+ ( -- * Stream operators unstreamToVector2 , unstreamToMVector2 - -- * Chain functions- , chainOfVector- , unchainToVector- , unchainToMVector+ -- ** Compacting+ , compact+ , compactIn - -- * Generating- , ratchet+ -- ** Dicing+ , findSegments+ , findSegmentsFrom+ , diceSep - -- * Extracting+ -- ** Extracting , extract - -- * Inserting+ -- ** Inserting , insert - -- * Merging+ -- ** Merging , merge , mergeMaybe - -- * Splitting- , findSegments- , findSegmentsFrom- , diceSep-- -- * Compacting- , compact- , compactIn-- -- * Padding+ -- ** Padding , padForward - -- * Scanning- , scanMaybe+ -- ** Ratcheting+ , ratchet - -- * Grouping- , groupsBy+ -- ** Replicating+ , replicates + -- * Chain operators+ , chainOfVector+ , unchainToVector+ , unchainToMVector+ -- * Folding- , folds, C.Folds(..))+ , folds, C.Folds(..)++ -- * Scanning+ , scanMaybe+ , groupsBy) where import Data.Repa.Stream.Compact import Data.Repa.Stream.Concat@@ -55,8 +56,9 @@ import Data.Repa.Stream.Merge import Data.Repa.Stream.Pad import Data.Repa.Stream.Ratchet+import Data.Repa.Stream.Replicate import Data.Repa.Stream.Segment-import Data.Repa.Option+import Data.Repa.Scalar.Option import Data.IORef import System.IO.Unsafe import Control.Monad.ST@@ -138,141 +140,100 @@ ---------------------------------------------------------------------------------- | Produce a chain from a generic vector.-chainOfVector - :: (Monad m, GV.Vector v a)- => v a -> Chain m Int a--chainOfVector vec- = Chain (S.Exact len) 0 step- where- !len = GV.length vec-- step !i- | i >= len- = return $ Done i-- | otherwise - = return $ Yield (GV.unsafeIndex vec i) (i + 1)- {-# INLINE_INNER step #-}-{-# INLINE_STREAM chainOfVector #-}-+-- | 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 -> (s, Maybe b)) -- ^ Worker function+ -> s -- ^ Starting state+ -> v a -- ^ Input vector+ -> v b ----------------------------------------------------------------------------------- | Compute a chain into a generic vector.-unchainToVector- :: (PrimMonad m, GV.Vector v a)- => C.Chain m s a -> m (v a, s)-unchainToVector chain- = do (mvec, c') <- unchainToMVector chain- vec <- GV.unsafeFreeze mvec- return (vec, c')-{-# INLINE_STREAM unchainToVector #-}+compact f s0 vec+ = GV.unstream $ compactS f s0 $ GV.stream vec+{-# INLINE compact #-} --- | Compute a chain into a generic mutable vector.-unchainToMVector- :: (PrimMonad m, GM.MVector v a)- => Chain m s a- -> m (v (PrimState m) a, s)+-- | 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 -> (a, Maybe a)) -- ^ Worker function.+ -> v a -- ^ Input elements.+ -> v a -unchainToMVector (Chain sz s0 step)- = case sz of- S.Exact i -> unchainToMVector_max i s0 step- S.Max i -> unchainToMVector_max i s0 step- S.Unknown -> unchainToMVector_unknown 32 s0 step-{-# INLINE_STREAM unchainToMVector #-}+compactIn f vec+ = GV.unstream $ compactInS f $ GV.stream vec+{-# INLINE compactIn #-} --- unchain when we known the maximum size of the vector.-unchainToMVector_max nMax s0 step - = GM.unsafeNew nMax >>= \vec- -> let - go !sPEC !i !s- = step s >>= \m- -> case m of- Yield e s'- -> do GM.unsafeWrite vec i e- go sPEC (i + 1) s'-- Skip s' -> go sPEC i s'- Done s' -> return (GM.unsafeSlice 0 i vec, s')- {-# INLINE_INNER go #-}+-------------------------------------------------------------------------------+-- | 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) - in go SM.SPEC 0 s0-{-# INLINE_STREAM unchainToMVector_max #-}+findSegments pStart pEnd src+ = GV.unzip+ $ GV.unstream+ $ startLengthsOfSegsS+ $ findSegmentsS pStart pEnd (GV.length src - 1)+ $ SM.indexed + $ GV.stream src+{-# INLINE findSegments #-} --- unchain when we don't know the maximum size of the vector.-unchainToMVector_unknown nStart s0 step- = GM.unsafeNew nStart >>= \vec0- -> let - go !sPEC !vec !i !n !s- = step s >>= \m- -> case m of- Yield e s'- | i >= n - -> do vec' <- GM.unsafeGrow vec n- GM.unsafeWrite vec' i e- go sPEC vec' (i + 1) (n + n) s'-- | otherwise- -> do GM.unsafeWrite vec i e- go sPEC vec (i + 1) n s'-- Skip s' -> go sPEC vec i n s'- Done s' -> return (GM.unsafeSlice 0 i vec, s')- {-# INLINE_INNER go #-}+-------------------------------------------------------------------------------+-- | 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) - in go SM.SPEC vec0 0 nStart s0-{-# INLINE_STREAM unchainToMVector_unknown #-}+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 #-} ---------------------------------------------------------------------------------- | 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--- @+-- | Dice a vector stream into rows and columns. ---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+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 - -- 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 #-}+diceSep pEndInner pEndBoth vec+ = runST+ $ unstreamToVector2+ $ diceSepS pEndInner pEndBoth + $ S.liftStream+ $ GV.stream vec+{-# INLINE diceSep #-} -------------------------------------------------------------------------------@@ -359,155 +320,174 @@ ---------------------------------------------------------------------------------- | 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+-- | 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) - (vec1 :: v2 b, k1 :: (Int, s))- = runST $ unchainToVector $ C.liftChain - $ C.scanMaybeC f' k0 $ chainOfVector vec0-{-# INLINE scanMaybe #-}+padForward ksucc vec+ = GV.unstream+ $ padForwardS ksucc+ $ GV.stream vec+{-# INLINE padForward #-} ---------------------------------------------------------------------------------- | From a stream of values which has consecutive runs of idential values,--- produce a stream of the lengths of these runs.--- +-- | 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.+-- -- @--- groupsBy (==) (Just ('a', 4)) --- [\'a\', \'a\', \'a\', \'b\', \'b\', \'c\', \'d\', \'d\'] --- => ([('a', 7), ('b', 2), ('c', 1)], Just (\'d\', 2))+-- 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 -- @ ---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))+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 -groupsBy f !c !vec0- = (vec1, snd k1)- where - f' x y = return $ f x y+ -- Make a vector for the output lengths.+ mvLens <- GM.unsafeNew (GV.length vStartsMax)+ rmvLens <- newIORef mvLens - (vec1 :: v2 (a, Int), k1)- = runST $ unchainToVector $ C.liftChain - $ C.groupsByC f' c $ chainOfVector vec0-{-# INLINE groupsBy #-}+ -- 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 #-} + ---------------------------------------------------------------------------------- | 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)+-- | Segmented replicate.+replicates+ :: (GV.Vector v (Int, a), GV.Vector v a)+ => v (Int, a)+ -> v a -findSegments pStart pEnd src- = GV.unzip- $ GV.unstream- $ startLengthsOfSegsS- $ findSegmentsS pStart pEnd (GV.length src - 1)- $ SM.indexed - $ GV.stream src-{-# INLINE findSegments #-}+replicates vec+ = GV.unstream+ $ replicatesS+ $ GV.stream vec+{-# INLINE replicates #-} ---------------------------------------------------------------------------------- | 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)+-- | Produce a chain from a generic vector.+chainOfVector + :: (Monad m, GV.Vector v a)+ => v a -> Chain m Int a -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 #-}+chainOfVector vec+ = Chain (S.Exact len) 0 step+ where+ !len = GV.length vec + step !i+ | i >= len+ = return $ Done i + | otherwise + = return $ Yield (GV.unsafeIndex vec i) (i + 1)+ {-# INLINE_INNER step #-}+{-# INLINE_STREAM chainOfVector #-}++ ---------------------------------------------------------------------------------- | 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+-- | Compute a chain into a generic vector.+unchainToVector+ :: (PrimMonad m, GV.Vector v a)+ => C.Chain m s a -> m (v a, s)+unchainToVector chain+ = do (mvec, c') <- unchainToMVector chain+ vec <- GV.unsafeFreeze mvec+ return (vec, c')+{-# INLINE_STREAM unchainToVector #-} -diceSep pEndInner pEndBoth vec- = runST- $ unstreamToVector2- $ diceSepS pEndInner pEndBoth - $ S.liftStream- $ GV.stream vec-{-# INLINE diceSep #-} +-- | Compute a chain into a generic mutable vector.+unchainToMVector+ :: (PrimMonad m, GM.MVector v a)+ => Chain m s a+ -> m (v (PrimState m) a, s) ----------------------------------------------------------------------------------- | 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+unchainToMVector (Chain sz s0 step)+ = case sz of+ S.Exact i -> unchainToMVector_max i s0 step+ S.Max i -> unchainToMVector_max i s0 step+ S.Unknown -> unchainToMVector_unknown 32 s0 step+{-# INLINE_STREAM unchainToMVector #-} -compact f s0 vec- = GV.unstream $ compactS f s0 $ GV.stream vec-{-# INLINE compact #-} +-- unchain when we known the maximum size of the vector.+unchainToMVector_max nMax s0 step + = GM.unsafeNew nMax >>= \vec+ -> let + go !sPEC !i !s+ = step s >>= \m+ -> case m of+ Yield e s'+ -> do GM.unsafeWrite vec i e+ go sPEC (i + 1) s' --- | 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+ Skip s' -> go sPEC i s'+ Done s' -> return (GM.unsafeSlice 0 i vec, s')+ {-# INLINE_INNER go #-} -compactIn f vec- = GV.unstream $ compactInS f $ GV.stream vec-{-# INLINE compactIn #-}+ in go SM.SPEC 0 s0+{-# INLINE_STREAM unchainToMVector_max #-} +-- unchain when we don't know the maximum size of the vector.+unchainToMVector_unknown nStart s0 step+ = GM.unsafeNew nStart >>= \vec0+ -> let + go !sPEC !vec !i !n !s+ = step s >>= \m+ -> case m of+ Yield e s'+ | i >= n + -> do vec' <- GM.unsafeGrow vec n+ GM.unsafeWrite vec' i e+ go sPEC vec' (i + 1) (n + n) s'++ | otherwise+ -> do GM.unsafeWrite vec i e+ go sPEC vec (i + 1) n s'++ Skip s' -> go sPEC vec i n s'+ Done s' -> return (GM.unsafeSlice 0 i vec, s')+ {-# INLINE_INNER go #-}++ in go SM.SPEC vec0 0 nStart s0+{-# INLINE_STREAM unchainToMVector_unknown #-}++ ------------------------------------------------------------------------------- -- | Segmented fold over vectors of segment lengths and input values. --@@ -545,18 +525,53 @@ ---------------------------------------------------------------------------------- | 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)+-- | 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. -padForward ksucc vec- = GV.unstream- $ padForwardS ksucc- $ GV.stream vec-{-# INLINE padForward #-}+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 #-}
Data/Repa/Vector/Unboxed.hs view
@@ -1,48 +1,50 @@ module Data.Repa.Vector.Unboxed- ( -- * Conversion- chainOfVector- , unchainToVector- , unchainToMVector+ ( -- * Stream operators+ -- ** Compacting+ compact+ , compactIn - -- * Generating- , ratchet+ -- ** Dicing+ , findSegments+ , findSegmentsFrom+ , diceSep - -- * Extracting+ -- ** Extracting , extract - -- * Inserting+ -- ** Inserting , insert - -- * Merging+ -- ** Merging , merge , mergeMaybe - -- * Splitting- , findSegments- , findSegmentsFrom- , diceSep+ -- ** Padding+ , padForward - -- * Compacting- , compact- , compactIn+ -- ** Ratcheting+ , ratchet - -- * Padding- , padForward+ -- * Chain operators+ , unchainToVector+ , unchainToMVector - -- * Scanning- , scanMaybe+ -- ** Folding+ , folds, C.Folds(..) - -- * Grouping+ -- ** Scanning+ , scanMaybe , groupsBy - -- * Folding- , folds, C.Folds(..))+ -- ** Conversion+ , chainOfVector+ ) where-import Data.Repa.Option import Data.Vector.Unboxed (Unbox, Vector) import Data.Vector.Unboxed.Mutable (MVector) import Data.Repa.Chain (Chain)+import Data.Repa.Scalar.Option import qualified Data.Repa.Vector.Generic as G import qualified Data.Repa.Chain as C import qualified Data.Vector.Unboxed as U@@ -257,7 +259,7 @@ -- compact :: (Unbox a, Unbox b)- => (s -> a -> (Maybe b, s)) -- ^ Worker function+ => (s -> a -> (s, Maybe b)) -- ^ Worker function -> s -- ^ Starting state -> Vector a -- ^ Input vector -> Vector b@@ -270,7 +272,7 @@ -- initial state, and add the final state to the end of the output. compactIn :: Unbox a- => (a -> a -> (Maybe a, a)) -- ^ Worker function.+ => (a -> a -> (a, Maybe a)) -- ^ Worker function. -> Vector a -- ^ Input elements. -> Vector a
repa-stream.cabal view
@@ -1,5 +1,5 @@ Name: repa-stream-Version: 4.1.0.1+Version: 4.2.2.1 License: BSD3 License-file: LICENSE Author: The Repa Development Team@@ -19,14 +19,14 @@ Library build-Depends: - base == 4.7.*,+ base == 4.8.*, vector == 0.10.*,- primitive == 0.5.4.*,- mtl == 2.2.*+ primitive == 0.6.*,+ mtl == 2.2.*,+ repa-scalar == 4.2.2.* exposed-modules: Data.Repa.Chain- Data.Repa.Option Data.Repa.Stream Data.Repa.Vector.Generic Data.Repa.Vector.Unboxed@@ -46,6 +46,7 @@ Data.Repa.Stream.Merge Data.Repa.Stream.Pad Data.Repa.Stream.Ratchet+ Data.Repa.Stream.Replicate Data.Repa.Stream.Segment include-dirs: