module Data.RangeMin.Fusion where
import Control.Monad.ST
import Control.Monad.Primitive
import Data.RangeMin.Common.Types
import Data.RangeMin.Common.Vector
import Data.RangeMin.Common.Combinators
import qualified Data.Vector.Generic as G
import Data.RangeMin.Fusion.Stream (Stream)
import qualified Data.RangeMin.Fusion.Stream as S
import qualified Data.RangeMin.Fusion.Stream.Monadic as SM
import Prelude hiding (mapM_, map, replicate)
convert :: (Vector v a, Vector v' a) => v a -> v' a
convert xs = unstream (stream xs)
unstream :: Vector v a => Stream a -> v a
unstream !str = create $ do
!dest <- new (S.length str)
fill dest str
stream :: Vector v a => v a -> Stream a
stream !src = S.generate (G.length src) (G.unsafeIndex src)
unzip :: (Vector v (a, b), Vector va a, Vector vb b) =>
v (a, b) -> (va a, vb b)
unzip xs = runST $ do
!destA <- new n
!destB <- new n
S.imapM_ (\ i (a, b) -> do
write destA i a
write destB i b) str
liftM2 (,) (unsafeFreeze destA) (unsafeFreeze destB)
where str = stream xs
n = S.length str
unzip3 :: (Vector v (a, b, c), Vector va a, Vector vb b, Vector vc c) =>
v (a, b, c) -> (va a, vb b, vc c)
unzip3 xs = runST $ do
!destA <- new n
!destB <- new n
!destC <- new n
S.imapM_ (\ i (a, b, c) -> do
write destA i a
write destB i b
write destC i c) str
liftM3 (,,) (unsafeFreeze destA) (unsafeFreeze destB) (unsafeFreeze destC)
where str = stream xs
n = S.length str
enumN :: Length -> VVector Int
enumN n = unstream (S.enumN n)
generate :: Length -> (Index -> a) -> VVector a
generate n f = unstream (S.generate n f)
imap :: (Vector v a) => (Index -> a -> a') -> v a -> VVector a'
imap f xs = unstream (S.imap f (stream xs))
map :: (Vector v a) => (a -> a') -> v a -> VVector a'
map f = imap (const f)
imapAccumL :: (Vector v a) => (b -> Index -> a -> (c, b)) -> b -> v a -> VVector c
imapAccumL f z xs = unstream (S.imapAccumL f z (stream xs))
imapM_ :: (Monad m, Vector v a) => (Index -> a -> m b) -> v a -> m ()
imapM_ f xs = S.imapM_ f (stream xs)
ipostscanl :: (Vector v a) => (b -> Index -> a -> b) -> b -> v a -> VVector b
ipostscanl f = imapAccumL (\ z i a -> let z' = f z i a in (z', z'))
mapM_ :: (Monad m, Vector v a) => (a -> m b) -> v a -> m ()
mapM_ f = imapM_ (const f)
postscanl :: (Vector v a) => (b -> a -> b) -> b -> v a -> VVector b
postscanl f = ipostscanl (\ z _ -> f z)
replicate :: Int -> a -> VVector a
replicate n a = generate n (const a)
snoc :: Vector v a => v a -> a -> VVector a
xs `snoc` x = unstream (stream xs `S.snoc` x)
snoc' :: Vector v a => v a -> a -> VVector a
xs `snoc'` x = x `seq` (xs `snoc` x)
iunfoldN :: Length -> (Index -> b -> Maybe (a, b)) -> b -> VVector a
iunfoldN n f z = unstream (S.iunfoldN n f z)
unfoldN :: Int -> (b -> Maybe (a, b)) -> b -> VVector a
unfoldN n f = iunfoldN n (const f)
ifoldl :: Vector v a => (b -> Index -> a -> b) -> b -> v a -> b
ifoldl f z xs = S.ifoldl f z (stream xs)
foldl :: Vector v a => (b -> a -> b) -> b -> v a -> b
foldl f = ifoldl (\ z _ -> f z)
fromListN :: Length -> [a] -> VVector a
fromListN n xs = unstream (S.fromListN n xs)
munstream :: (PrimMonad m, Vector v a) => S.MStream m a -> m (v a)
munstream str = do
let !n = SM.length str
!dest <- new n
_ <- fillM dest str
unsafeFreeze (sliceM 0 n dest)
replicateM :: (PrimMonad m, Vector v a) => Length -> m a -> m (v a)
replicateM n m = munstream (SM.generateM n (const m))
fillM :: (PrimMonad m, MVector v a) => v (PrimState m) a -> S.MStream m a -> m (v (PrimState m) a)
fillM !dest !str = do
let !n = SM.length str
SM.imapM_ (write dest) str
return (sliceM 0 n dest)
fill :: (PrimMonad m, MVector v a) => v (PrimState m) a -> Stream a -> m (v (PrimState m) a)
fill dest str = fillM dest (S.liftStream str)