1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
{-# LANGUAGE MagicHash #-}
module Data.Array.Repa.Repr.Delayed
( D, Array(..)
, fromFunction, toFunction
, delay)
where
import Data.Array.Repa.Eval.Load
import Data.Array.Repa.Eval.Target
import Data.Array.Repa.Eval.Chunked
import Data.Array.Repa.Eval.Cursored
import Data.Array.Repa.Eval.Elt
import Data.Array.Repa.Index
import Data.Array.Repa.Shape
import Data.Array.Repa.Base
import Debug.Trace
import GHC.Exts
-- | Delayed arrays are represented as functions from the index to element value.
--
-- Every time you index into a delayed array the element at that position
-- is recomputed.
data D
-- | Compute elements of a delayed array.
instance Source D a where
data Array D sh a
= ADelayed
!sh
(sh -> a)
index (ADelayed _ f) ix = f ix
{-# INLINE index #-}
linearIndex (ADelayed sh f) ix = f (fromIndex sh ix)
{-# INLINE linearIndex #-}
extent (ADelayed sh _)
= sh
{-# INLINE extent #-}
deepSeqArray (ADelayed sh f) y
= sh `deepSeq` f `seq` y
{-# INLINE deepSeqArray #-}
-- Load -----------------------------------------------------------------------
-- | Compute all elements in an array.
instance Shape sh => Load D sh e where
loadP (ADelayed sh getElem) mvec
= mvec `deepSeqMVec`
do traceEventIO "Repa.loadP[Delayed]: start"
fillChunkedP (size sh) (unsafeWriteMVec mvec) (getElem . fromIndex sh)
touchMVec mvec
traceEventIO "Repa.loadP[Delayed]: end"
{-# INLINE [4] loadP #-}
loadS (ADelayed sh getElem) mvec
= mvec `deepSeqMVec`
do traceEventIO "Repa.loadS[Delayed]: start"
fillLinearS (size sh) (unsafeWriteMVec mvec) (getElem . fromIndex sh)
touchMVec mvec
traceEventIO "Repa.loadS[Delayed]: end"
{-# INLINE [4] loadS #-}
-- | Compute a range of elements in a rank-2 array.
instance Elt e => LoadRange D DIM2 e where
loadRangeP (ADelayed (Z :. _h :. (I# w)) getElem) mvec
(Z :. (I# y0) :. (I# x0)) (Z :. (I# h0) :. (I# w0))
= mvec `deepSeqMVec`
do traceEventIO "Repa.loadRangeP[Delayed]: start"
fillBlock2P (unsafeWriteMVec mvec)
getElem
w x0 y0 w0 h0
touchMVec mvec
traceEventIO "Repa.loadRangeP[Delayed]: end"
{-# INLINE [1] loadRangeP #-}
loadRangeS (ADelayed (Z :. _h :. (I# w)) getElem) mvec
(Z :. (I# y0) :. (I# x0)) (Z :. (I# h0) :. (I# w0))
= mvec `deepSeqMVec`
do traceEventIO "Repa.loadRangeS[Delayed]: start"
fillBlock2S (unsafeWriteMVec mvec)
getElem
w x0 y0 w0 h0
touchMVec mvec
traceEventIO "Repa.loadRangeS[Delayed]: end"
{-# INLINE [1] loadRangeS #-}
-- Conversions ----------------------------------------------------------------
-- | O(1). Wrap a function as a delayed array.
fromFunction :: sh -> (sh -> a) -> Array D sh a
fromFunction sh f
= ADelayed sh f
{-# INLINE fromFunction #-}
-- | O(1). Produce the extent of an array, and a function to retrieve an
-- arbitrary element.
toFunction
:: (Shape sh, Source r1 a)
=> Array r1 sh a -> (sh, sh -> a)
toFunction arr
= case delay arr of
ADelayed sh f -> (sh, f)
{-# INLINE toFunction #-}
-- | O(1). Delay an array.
-- This wraps the internal representation to be a function from
-- indices to elements, so consumers don't need to worry about
-- what the previous representation was.
--
delay :: Shape sh => Source r e
=> Array r sh e -> Array D sh e
delay arr = ADelayed (extent arr) (unsafeIndex arr)
{-# INLINE delay #-}
|