{-# LANGUAGE UndecidableInstances #-}

-- | Low level interface to parallel array filling operators.
module Data.Array.Repa.Eval
        ( -- * Element types
          Elt       (..)

        -- * Parallel array filling
        , Target    (..)
        , Load      (..)
        , LoadRange (..)
        , fromList
        
        -- * Converting between representations
        , computeS, computeP, suspendedComputeP
        , copyS,    copyP,    suspendedCopyP
        , now
        
        -- * Chunked filling
        , fillLinearS
        , fillChunkedP
        , fillChunkedIOP

        -- * Interleaved filling
        , fillInterleavedP

        -- * Blockwise filling
        , fillBlock2P
        , fillBlock2S
        
        -- * Cursored blockwise filling
        , fillCursoredBlock2S
        , fillCursoredBlock2P
        
        -- * Chunked selection
        , selectChunkedS
        , selectChunkedP)
where
import Data.Array.Repa.Eval.Elt
import Data.Array.Repa.Eval.Target
import Data.Array.Repa.Eval.Load
import Data.Array.Repa.Eval.Chunked
import Data.Array.Repa.Eval.Interleaved
import Data.Array.Repa.Eval.Cursored
import Data.Array.Repa.Eval.Selection
import Data.Array.Repa.Repr.Delayed
import Data.Array.Repa.Base
import Data.Array.Repa.Shape
import System.IO.Unsafe


-- | Parallel computation of array elements.
--
--   * The source array must have a delayed representation like `D`, `C` or `P`, 
--     and the result a manifest representation like `U` or `F`.
--
--   * If you want to copy data between manifest representations then use
--    `copyP` instead.
--
--   * If you want to convert a manifest array back to a delayed representation
--     then use `delay` instead.
--
computeP 
        :: ( Load r1 sh e
           , Target r2 e, Source r2 e, Monad m)
        => Array r1 sh e -> m (Array r2 sh e)
computeP :: Array r1 sh e -> m (Array r2 sh e)
computeP Array r1 sh e
arr = Array r2 sh e -> m (Array r2 sh e)
forall sh r e (m :: * -> *).
(Shape sh, Source r e, Monad m) =>
Array r sh e -> m (Array r sh e)
now (Array r2 sh e -> m (Array r2 sh e))
-> Array r2 sh e -> m (Array r2 sh e)
forall a b. (a -> b) -> a -> b
$ Array r1 sh e -> Array r2 sh e
forall r1 sh e r2.
(Load r1 sh e, Target r2 e) =>
Array r1 sh e -> Array r2 sh e
suspendedComputeP Array r1 sh e
arr
{-# INLINE [4] computeP #-}


-- | Sequential computation of array elements.
computeS 
        :: (Load r1 sh e, Target r2 e)
        => Array r1 sh e -> Array r2 sh e
computeS :: Array r1 sh e -> Array r2 sh e
computeS Array r1 sh e
arr1
 = Array r1 sh e
arr1 Array r1 sh e
-> (IO (Array r2 sh e) -> Array r2 sh e)
-> IO (Array r2 sh e)
-> Array r2 sh e
forall r e sh b. (Source r e, Shape sh) => Array r sh e -> b -> b
`deepSeqArray` 
   IO (Array r2 sh e) -> Array r2 sh e
forall a. IO a -> a
unsafePerformIO
 (IO (Array r2 sh e) -> Array r2 sh e)
-> IO (Array r2 sh e) -> Array r2 sh e
forall a b. (a -> b) -> a -> b
$ do   MVec r2 e
mvec2   <- Int -> IO (MVec r2 e)
forall r e. Target r e => Int -> IO (MVec r e)
newMVec (sh -> Int
forall sh. Shape sh => sh -> Int
size (sh -> Int) -> sh -> Int
forall a b. (a -> b) -> a -> b
$ Array r1 sh e -> sh
forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
extent Array r1 sh e
arr1) 
        Array r1 sh e -> MVec r2 e -> IO ()
forall r1 sh e r2.
(Load r1 sh e, Target r2 e) =>
Array r1 sh e -> MVec r2 e -> IO ()
loadS Array r1 sh e
arr1 MVec r2 e
mvec2
        sh -> MVec r2 e -> IO (Array r2 sh e)
forall r e sh. Target r e => sh -> MVec r e -> IO (Array r sh e)
unsafeFreezeMVec (Array r1 sh e -> sh
forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
extent Array r1 sh e
arr1) MVec r2 e
mvec2
{-# INLINE [4] computeS #-}


-- | Suspended parallel computation of array elements.
--
--   This version creates a thunk that will evaluate the array on demand.
--   If you force it when another parallel computation is already running
--   then you  will get a runtime warning and evaluation will be sequential. 
--   Use `deepSeqArray` and `now` to ensure that each array is evaluated
--   before proceeding to the next one. 
--  
--   If unsure then just use the monadic version `computeP`. This one ensures
--   that each array is fully evaluated before continuing.
--
suspendedComputeP 
        :: (Load r1 sh e, Target r2 e)
        => Array r1 sh e -> Array r2 sh e
suspendedComputeP :: Array r1 sh e -> Array r2 sh e
suspendedComputeP Array r1 sh e
arr1
 = Array r1 sh e
arr1 Array r1 sh e
-> (IO (Array r2 sh e) -> Array r2 sh e)
-> IO (Array r2 sh e)
-> Array r2 sh e
forall r e sh b. (Source r e, Shape sh) => Array r sh e -> b -> b
`deepSeqArray` 
   IO (Array r2 sh e) -> Array r2 sh e
forall a. IO a -> a
unsafePerformIO
 (IO (Array r2 sh e) -> Array r2 sh e)
-> IO (Array r2 sh e) -> Array r2 sh e
forall a b. (a -> b) -> a -> b
$ do   MVec r2 e
mvec2    <- Int -> IO (MVec r2 e)
forall r e. Target r e => Int -> IO (MVec r e)
newMVec (sh -> Int
forall sh. Shape sh => sh -> Int
size (sh -> Int) -> sh -> Int
forall a b. (a -> b) -> a -> b
$ Array r1 sh e -> sh
forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
extent Array r1 sh e
arr1) 
        Array r1 sh e -> MVec r2 e -> IO ()
forall r1 sh e r2.
(Load r1 sh e, Target r2 e) =>
Array r1 sh e -> MVec r2 e -> IO ()
loadP Array r1 sh e
arr1 MVec r2 e
mvec2
        sh -> MVec r2 e -> IO (Array r2 sh e)
forall r e sh. Target r e => sh -> MVec r e -> IO (Array r sh e)
unsafeFreezeMVec (Array r1 sh e -> sh
forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
extent Array r1 sh e
arr1) MVec r2 e
mvec2
{-# INLINE [4] suspendedComputeP #-}


-- | Parallel copying of arrays.
--
--   * This is a wrapper that delays an array before calling `computeP`. 
-- 
--   * You can use it to copy manifest arrays between representations.
--
copyP  :: ( Source r1 e, Source r2 e
          , Load D sh e, Target r2 e
          , Monad m)
        => Array r1 sh e -> m (Array r2 sh e)
copyP :: Array r1 sh e -> m (Array r2 sh e)
copyP Array r1 sh e
arr = Array r2 sh e -> m (Array r2 sh e)
forall sh r e (m :: * -> *).
(Shape sh, Source r e, Monad m) =>
Array r sh e -> m (Array r sh e)
now (Array r2 sh e -> m (Array r2 sh e))
-> Array r2 sh e -> m (Array r2 sh e)
forall a b. (a -> b) -> a -> b
$ Array r1 sh e -> Array r2 sh e
forall r1 e sh r2.
(Source r1 e, Load D sh e, Target r2 e) =>
Array r1 sh e -> Array r2 sh e
suspendedCopyP Array r1 sh e
arr
{-# INLINE [4] copyP #-}


-- | Sequential copying of arrays.
copyS   :: ( Source r1 e
           , Load D sh e, Target r2 e)
        => Array r1 sh e -> Array r2 sh e
copyS :: Array r1 sh e -> Array r2 sh e
copyS Array r1 sh e
arr1  = Array D sh e -> Array r2 sh e
forall r1 sh e r2.
(Load r1 sh e, Target r2 e) =>
Array r1 sh e -> Array r2 sh e
computeS (Array D sh e -> Array r2 sh e) -> Array D sh e -> Array r2 sh e
forall a b. (a -> b) -> a -> b
$ Array r1 sh e -> Array D sh e
forall sh r e.
(Shape sh, Source r e) =>
Array r sh e -> Array D sh e
delay Array r1 sh e
arr1
{-# INLINE [4] copyS #-}


-- | Suspended parallel copy of array elements.
suspendedCopyP   
        :: ( Source r1 e
           , Load D sh e, Target r2 e)
        => Array r1 sh e -> Array r2 sh e
suspendedCopyP :: Array r1 sh e -> Array r2 sh e
suspendedCopyP Array r1 sh e
arr1  = Array D sh e -> Array r2 sh e
forall r1 sh e r2.
(Load r1 sh e, Target r2 e) =>
Array r1 sh e -> Array r2 sh e
suspendedComputeP (Array D sh e -> Array r2 sh e) -> Array D sh e -> Array r2 sh e
forall a b. (a -> b) -> a -> b
$ Array r1 sh e -> Array D sh e
forall sh r e.
(Shape sh, Source r e) =>
Array r sh e -> Array D sh e
delay Array r1 sh e
arr1
{-# INLINE [4] suspendedCopyP #-}


-- | Monadic version of `deepSeqArray`. 
-- 
--   Forces an suspended array computation to be completed at this point
--   in a monadic computation.
--
-- @ do  let arr2 = suspendedComputeP arr1
--     ...
--     arr3 <- now $ arr2
--     ...
-- @
--
now     :: (Shape sh, Source r e, Monad m)
        => Array r sh e -> m (Array r sh e)
now :: Array r sh e -> m (Array r sh e)
now Array r sh e
arr
 = do   Array r sh e
arr Array r sh e -> m () -> m ()
forall r e sh b. (Source r e, Shape sh) => Array r sh e -> b -> b
`deepSeqArray` () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        Array r sh e -> m (Array r sh e)
forall (m :: * -> *) a. Monad m => a -> m a
return Array r sh e
arr
{-# INLINE [4] now #-}