repa-3.1.0.1: Data/Array/Repa/Eval.hs
{-# 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 #-}