{-# LANGUAGE UndecidableInstances #-} -- | Low level interface to parallel array filling operators. module Data.Array.Repa.Eval ( -- * Element types Elt (..) -- * Parallel array filling , Fillable (..) , Fill (..) , FillRange (..) , fromList -- * Converting between representations , computeS, computeP, suspendedComputeP , copyS, copyP, suspendedCopyP , now -- * Chunked filling , fillChunkedS , fillChunkedP , fillChunkedIOP -- * 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.Fill import Data.Array.Repa.Eval.Chunked 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 :: (Shape sh, Fill r1 r2 sh e, Repr r2 e, Monad m) => Array r1 sh e -> m (Array r2 sh e) computeP arr = now $ suspendedComputeP arr {-# INLINE [4] computeP #-} -- | Sequential computation of array elements. computeS :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh e computeS arr1 = arr1 `deepSeqArray` unsafePerformIO $ do marr2 <- newMArr (size $ extent arr1) fillS arr1 marr2 unsafeFreezeMArr (extent arr1) marr2 {-# 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 :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh e suspendedComputeP arr1 = arr1 `deepSeqArray` unsafePerformIO $ do marr2 <- newMArr (size $ extent arr1) fillP arr1 marr2 unsafeFreezeMArr (extent arr1) marr2 {-# 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 :: (Shape sh, Fill D r2 sh e, Repr r1 e, Repr r2 e, Monad m) => Array r1 sh e -> m (Array r2 sh e) copyP arr = now $ suspendedCopyP arr {-# INLINE [4] copyP #-} -- | Sequential copying of arrays. copyS :: (Repr r1 e, Fill D r2 sh e) => Array r1 sh e -> Array r2 sh e copyS arr1 = computeS $ delay arr1 {-# INLINE [4] copyS #-} -- | Suspended parallel copy of array elements. suspendedCopyP :: (Repr r1 e, Fill D r2 sh e) => Array r1 sh e -> Array r2 sh e suspendedCopyP arr1 = suspendedComputeP $ delay 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, Repr r e, Monad m) => Array r sh e -> m (Array r sh e) now arr = do arr `deepSeqArray` return () return arr {-# INLINE [4] now #-}