module Data.RangeMin.Common.Unf (generateUnf, postscanlUnf', toUnf, unfold, unfoldM, unfoldInto, Unf(..)) where
import Control.Monad
import Control.Monad.Primitive
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as GM
import Data.RangeMin.Common.Vector
data Unf a = forall b . Unf !Int b (Int -> b -> Maybe (a, b))
generateUnf :: Int -> (Int -> a) -> Unf a
generateUnf n f = Unf n () (\ i _ -> Just (f i, ()))
postscanlUnf' :: (a -> b -> a) -> a -> Unf b -> Unf a
postscanlUnf' f z0 (Unf n s0 suc) =
Unf n (z0, s0) (\ i (z, s) -> do
(x, s') <- suc i s
let !z' = f z x
return (z', (z', s')))
toUnf :: G.Vector v a => v a -> Unf a
toUnf !xs = generateUnf (G.length xs) (xs !)
unfold :: G.Vector v a => Unf a -> v a
unfold unf = inlineCreate (unfoldM unf)
unfoldM :: (GM.MVector v a, PrimMonad m) => Unf a -> m (v (PrimState m) a)
unfoldM unf@(Unf n _ _) = do
!dest <- new n
unfoldInto0 dest unf
return dest
unfoldInto0 :: (GM.MVector v a, PrimMonad m) => v (PrimState m) a -> Unf a -> m ()
unfoldInto0 !dest (Unf n s0 suc) = do
let go i s = when (i < n) $ case suc i s of
Nothing -> return ()
Just (x, s') -> write dest i x >> go (i+1) s'
go 0 s0
return ()
unfoldInto :: (G.Vector v a, PrimMonad m) => G.Mutable v (PrimState m) a -> Unf a -> m (v a)
unfoldInto dest unf@(Unf n _ _) = do
unfoldInto0 dest unf
unsafeFreeze (sliceM 0 n dest)