{-# LANGUAGE TupleSections #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Massiv.Array.Manifest.Vector.Stream
(
Steps(..)
, Stream(..)
, steps
, isteps
, fromStream
, fromStreamM
, fromStreamExactM
, unstreamExact
, unstreamMax
, unstreamMaxM
, unstreamUnknown
, unstreamUnknownM
, unstreamIntoM
, toBundle
, fromBundle
, fromBundleM
, length
, empty
, singleton
, generate
, cons
, uncons
, snoc
, drop
, take
, slice
, traverse
, mapM
, concatMap
, append
, zipWith
, zipWithM
, foldl
, foldr
, foldlM
, foldrM
, unfoldr
, unfoldrN
, toList
, fromList
, fromListN
, mapMaybe
, mapMaybeA
, mapMaybeM
, filter
, filterA
, filterM
, transStepsId
, module Data.Vector.Fusion.Bundle.Size
, module Data.Vector.Fusion.Util
) where
import Data.Maybe (catMaybes)
import qualified Control.Monad as M
import Control.Monad.ST
import Data.Massiv.Core.Common hiding (empty, singleton)
import qualified Data.Traversable as Traversable (traverse)
import qualified Data.Vector.Fusion.Bundle.Monadic as B
import Data.Vector.Fusion.Bundle.Size
import qualified Data.Vector.Fusion.Stream.Monadic as S
import Data.Vector.Fusion.Util
import Prelude hiding (zipWith, mapM, traverse, length, foldl, foldr, filter, concatMap, drop, take)
steps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m e
steps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
where
k = totalElem $ size arr
step i
| i < k =
let e = unsafeLinearIndex arr i
in e `seq` return $ S.Yield e (i + 1)
| otherwise = return S.Done
{-# INLINE step #-}
{-# INLINE steps #-}
isteps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m (ix, e)
isteps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
where
sz = size arr
k = totalElem sz
step i
| i < k =
let e = unsafeLinearIndex arr i
in e `seq` return $ S.Yield (fromLinearIndex sz i, e) (i + 1)
| otherwise = return S.Done
{-# INLINE step #-}
{-# INLINE isteps #-}
toBundle :: (Monad m, Source r ix e) => Array r ix e -> B.Bundle m v e
toBundle arr =
let Steps str k = steps arr
in B.fromStream str k
{-# INLINE toBundle #-}
fromBundle :: Mutable r Ix1 e => B.Bundle Id v e -> Array r Ix1 e
fromBundle bundle = fromStream (B.sSize bundle) (B.sElems bundle)
{-# INLINE fromBundle #-}
fromBundleM :: (Monad m, Mutable r Ix1 e) => B.Bundle m v e -> m (Array r Ix1 e)
fromBundleM bundle = fromStreamM (B.sSize bundle) (B.sElems bundle)
{-# INLINE fromBundleM #-}
fromStream :: forall r e . Mutable r Ix1 e => Size -> S.Stream Id e -> Array r Ix1 e
fromStream sz str =
case upperBound sz of
Nothing -> unstreamUnknown str
Just k -> unstreamMax k str
{-# INLINE fromStream #-}
fromStreamM :: forall r e m. (Monad m, Mutable r Ix1 e) => Size -> S.Stream m e -> m (Array r Ix1 e)
fromStreamM sz str = do
xs <- S.toList str
case upperBound sz of
Nothing -> pure $! unstreamUnknown (S.fromList xs)
Just k -> pure $! unstreamMax k (S.fromList xs)
{-# INLINE fromStreamM #-}
fromStreamExactM ::
forall r ix e m. (Monad m, Mutable r ix e)
=> Sz ix
-> S.Stream m e
-> m (Array r ix e)
fromStreamExactM sz str = do
xs <- S.toList str
pure $! unstreamExact sz (S.fromList xs)
{-# INLINE fromStreamExactM #-}
unstreamIntoM ::
(Mutable r Ix1 a, PrimMonad m)
=> MArray (PrimState m) r Ix1 a
-> Size
-> S.Stream Id a
-> m (MArray (PrimState m) r Ix1 a)
unstreamIntoM marr sz str =
case sz of
Exact _ -> marr <$ unstreamMaxM marr str
Max _ -> unsafeLinearShrink marr . SafeSz =<< unstreamMaxM marr str
Unknown -> unstreamUnknownM marr str
{-# INLINE unstreamIntoM #-}
unstreamMax ::
forall r e. (Mutable r Ix1 e)
=> Int
-> S.Stream Id e
-> Array r Ix1 e
unstreamMax kMax str =
runST $ do
marr <- unsafeNew (SafeSz kMax)
k <- unstreamMaxM marr str
unsafeLinearShrink marr (SafeSz k) >>= unsafeFreeze Seq
{-# INLINE unstreamMax #-}
unstreamMaxM ::
(Mutable r ix a, PrimMonad m) => MArray (PrimState m) r ix a -> S.Stream Id a -> m Int
unstreamMaxM marr (S.Stream step s) = stepLoad s 0
where
stepLoad t i =
case unId (step t) of
S.Yield e' t' -> do
unsafeLinearWrite marr i e'
stepLoad t' (i + 1)
S.Skip t' -> stepLoad t' i
S.Done -> return i
{-# INLINE stepLoad #-}
{-# INLINE unstreamMaxM #-}
unstreamUnknown :: Mutable r Ix1 a => S.Stream Id a -> Array r Ix1 a
unstreamUnknown str =
runST $ do
marr <- unsafeNew zeroSz
unstreamUnknownM marr str >>= unsafeFreeze Seq
{-# INLINE unstreamUnknown #-}
unstreamUnknownM ::
(Mutable r Ix1 a, PrimMonad m)
=> MArray (PrimState m) r Ix1 a
-> S.Stream Id a
-> m (MArray (PrimState m) r Ix1 a)
unstreamUnknownM marrInit (S.Stream step s) = stepLoad s 0 (unSz (msize marrInit)) marrInit
where
stepLoad t i kMax marr
| i < kMax =
case unId (step t) of
S.Yield e' t' -> do
unsafeLinearWrite marr i e'
stepLoad t' (i + 1) kMax marr
S.Skip t' -> stepLoad t' i kMax marr
S.Done -> unsafeLinearShrink marr (SafeSz i)
| otherwise = do
let kMax' = max 1 (kMax * 2)
marr' <- unsafeLinearGrow marr (SafeSz kMax')
stepLoad t i kMax' marr'
{-# INLINE stepLoad #-}
{-# INLINE unstreamUnknownM #-}
unstreamExact ::
forall r ix e. (Mutable r ix e)
=> Sz ix
-> S.Stream Id e
-> Array r ix e
unstreamExact sz str =
runST $ do
marr <- unsafeNew sz
_ <- unstreamMaxM marr str
unsafeFreeze Seq marr
{-# INLINE unstreamExact #-}
length :: Steps Id a -> Int
length (Steps str sz) =
case sz of
Exact k -> k
_ -> unId (S.length str)
{-# INLINE length #-}
empty :: Monad m => Steps m e
empty = Steps S.empty (Exact 0)
{-# INLINE empty #-}
singleton :: Monad m => e -> Steps m e
singleton e = Steps (S.singleton e) (Exact 1)
{-# INLINE singleton #-}
generate :: Monad m => Int -> (Int -> e) -> Steps m e
generate k f = Steps (S.generate k f) (Exact k)
{-# INLINE generate #-}
cons :: Monad m => e -> Steps m e -> Steps m e
cons e (Steps str k) = Steps (S.cons e str) (k + 1)
{-# INLINE cons #-}
uncons :: Monad m => Steps m e -> m (Maybe (e, Steps m e))
uncons sts@(Steps str _) = do
mx <- str S.!? 0
pure $ fmap (, drop 1 sts) mx
{-# INLINE uncons #-}
snoc :: Monad m => Steps m e -> e -> Steps m e
snoc (Steps str k) e = Steps (S.snoc str e) (k + 1)
{-# INLINE snoc #-}
traverse :: (Monad m, Applicative f) => (e -> f a) -> Steps Id e -> f (Steps m a)
traverse f (Steps str k) = (`Steps` k) <$> liftListA (Traversable.traverse f) str
{-# INLINE traverse #-}
append :: Monad m => Steps m e -> Steps m e -> Steps m e
append (Steps str1 k1) (Steps str2 k2) = Steps (str1 S.++ str2) (k1 + k2)
{-# INLINE append #-}
mapM :: Monad m => (e -> m a) -> Steps m e -> Steps m a
mapM f (Steps str k) = Steps (S.mapM f str) k
{-# INLINE mapM #-}
zipWith :: Monad m => (a -> b -> e) -> Steps m a -> Steps m b -> Steps m e
zipWith f (Steps str1 k1) (Steps str2 k2) = Steps (S.zipWith f str1 str2) (smaller k1 k2)
{-# INLINE zipWith #-}
zipWithM :: Monad m => (a -> b -> m c) -> Steps m a -> Steps m b -> Steps m c
zipWithM f (Steps str1 k1) (Steps str2 k2) = Steps (S.zipWithM f str1 str2) (smaller k1 k2)
{-# INLINE zipWithM #-}
transStepsId :: Monad m => Steps Id e -> Steps m e
transStepsId (Steps sts k) = Steps (S.trans (pure . unId) sts) k
{-# INLINE transStepsId #-}
foldr :: (a -> b -> b) -> b -> Steps Id a -> b
foldr f acc sts = unId (S.foldr f acc (stepsStream sts))
{-# INLINE foldr #-}
foldl :: (b -> a -> b) -> b -> Steps Id a -> b
foldl f acc sts = unId (S.foldl f acc (stepsStream sts))
{-# INLINE foldl #-}
foldlM :: Monad m => (a -> b -> m a) -> a -> Steps m b -> m a
foldlM f acc (Steps sts _) = S.foldlM f acc sts
{-# INLINE foldlM #-}
foldrM :: Monad m => (b -> a -> m a) -> a -> Steps m b -> m a
foldrM f acc (Steps sts _) = S.foldrM f acc sts
{-# INLINE foldrM #-}
mapMaybe :: Monad m => (a -> Maybe e) -> Steps m a -> Steps m e
mapMaybe f (Steps str k) = Steps (S.mapMaybe f str) (toMax k)
{-# INLINE mapMaybe #-}
concatMap :: Monad m => (a -> Steps m e) -> Steps m a -> Steps m e
concatMap f (Steps str _) = Steps (S.concatMap (stepsStream . f) str) Unknown
{-# INLINE concatMap #-}
mapMaybeA :: (Monad m, Applicative f) => (a -> f (Maybe e)) -> Steps Id a -> f (Steps m e)
mapMaybeA f (Steps str k) = (`Steps` toMax k) <$> liftListA (mapMaybeListA f) str
{-# INLINE mapMaybeA #-}
mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Steps m a -> Steps m b
mapMaybeM f (Steps str k) = Steps (mapMaybeStreamM f str) (toMax k)
{-# INLINE mapMaybeM #-}
mapMaybeListA :: Applicative f => (a -> f (Maybe b)) -> [a] -> f [b]
mapMaybeListA f = fmap catMaybes . Traversable.traverse f
{-# INLINE mapMaybeListA #-}
mapMaybeStreamM :: Monad m => (a -> m (Maybe b)) -> S.Stream m a -> S.Stream m b
mapMaybeStreamM f (S.Stream step t) = S.Stream step' t
where
step' s = do
r <- step s
case r of
S.Yield x s' -> do
b <- f x
return $
case b of
Nothing -> S.Skip s'
Just b' -> S.Yield b' s'
S.Skip s' -> return $ S.Skip s'
S.Done -> return S.Done
{-# INLINE step' #-}
{-# INLINE mapMaybeStreamM #-}
filter :: Monad m => (a -> Bool) -> Steps m a -> Steps m a
filter f (Steps str k) = Steps (S.filter f str) (toMax k)
{-# INLINE filter #-}
filterA :: (Monad m, Applicative f) => (e -> f Bool) -> Steps Id e -> f (Steps m e)
filterA f (Steps str k) = (`Steps` toMax k) <$> liftListA (M.filterM f) str
{-# INLINE filterA #-}
filterM :: Monad m => (e -> m Bool) -> Steps m e -> Steps m e
filterM f (Steps str k) = Steps (S.filterM f str) (toMax k)
{-# INLINE filterM #-}
take :: Monad m => Int -> Steps m a -> Steps m a
take n (Steps str _) = Steps (S.take n str) (Max n)
{-# INLINE take #-}
drop :: Monad m => Int -> Steps m a -> Steps m a
drop n (Steps str k) = Steps (S.drop n str) (k `clampedSubtract` Exact n)
{-# INLINE drop #-}
slice :: Monad m => Int -> Int -> Steps m a -> Steps m a
slice i k (Steps str _) = Steps (S.slice i k str) (Max k)
{-# INLINE slice #-}
unfoldr :: Monad m => (s -> Maybe (e, s)) -> s -> Steps m e
unfoldr f e0 = Steps (S.unfoldr f e0) Unknown
{-# INLINE unfoldr #-}
unfoldrN :: Monad m => Sz1 -> (s -> Maybe (e, s)) -> s -> Steps m e
unfoldrN n f e0 = Steps (S.unfoldrN (unSz n) f e0) (Max (unSz n))
{-# INLINE unfoldrN #-}
toList :: Steps Id e -> [e]
toList (Steps str _) = unId (S.toList str)
{-# INLINE toList #-}
fromList :: Monad m => [e] -> Steps m e
fromList = (`Steps` Unknown) . S.fromList
{-# INLINE fromList #-}
fromListN :: Monad m => Int -> [e] -> Steps m e
fromListN n = (`Steps` Exact n) . S.fromListN n
{-# INLINE fromListN #-}
liftListA :: (Monad m, Functor f) => ([a] -> f [b]) -> S.Stream Id a -> f (S.Stream m b)
liftListA f str = S.fromList <$> f (unId (S.toList str))
{-# INLINE liftListA #-}