{-# 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 arr = now $ suspendedComputeP 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 arr1 = arr1 `deepSeqArray` unsafePerformIO $ do mvec2 <- newMVec (size $ extent arr1) loadS arr1 mvec2 unsafeFreezeMVec (extent arr1) 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 arr1 = arr1 `deepSeqArray` unsafePerformIO $ do mvec2 <- newMVec (size $ extent arr1) loadP arr1 mvec2 unsafeFreezeMVec (extent arr1) 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 arr = now $ suspendedCopyP 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 arr1 = computeS $ delay 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 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, Source r e, Monad m) => Array r sh e -> m (Array r sh e) now arr = do arr `deepSeqArray` return () return arr {-# INLINE [4] now #-}