repa-array-4.2.3.1: Data/Repa/Array/Meta/Delayed.hs
{-# LANGUAGE UndecidableInstances #-}
module Data.Repa.Array.Meta.Delayed
( D(..), Array(..)
, fromFunction, toFunction
, delay
, map
, reverse)
where
import Data.Repa.Array.Generic.Index
import Data.Repa.Array.Internals.Bulk
import Data.Repa.Array.Internals.Load
import Data.Repa.Array.Internals.Target
import Debug.Trace
import GHC.Exts
import qualified Data.Repa.Eval.Generic.Par as Par
import qualified Data.Repa.Eval.Generic.Seq as Seq
import Prelude hiding (map, zipWith, reverse)
#include "repa-array.h"
-------------------------------------------------------------------------------
-- | Delayed arrays wrap functions from an index to element value.
-- The index space is specified by an inner layout, @l@.
--
-- Every time you index into a delayed array the element at that position
-- is recomputed.
data D l
= Delayed
{ delayedLayout :: l }
deriving instance Eq l => Eq (D l)
deriving instance Show l => Show (D l)
-------------------------------------------------------------------------------
-- | Delayed arrays.
instance Layout l => Layout (D l) where
data Name (D l) = D (Name l)
type Index (D l) = Index l
name = D name
create (D n) len = Delayed (create n len)
extent (Delayed l) = extent l
toIndex (Delayed l) ix = toIndex l ix
fromIndex (Delayed l) i = fromIndex l i
{-# INLINE_ARRAY name #-}
{-# INLINE_ARRAY create #-}
{-# INLINE_ARRAY extent #-}
{-# INLINE_ARRAY toIndex #-}
{-# INLINE_ARRAY fromIndex #-}
deriving instance Eq (Name l) => Eq (Name (D l))
deriving instance Show (Name l) => Show (Name (D l))
-------------------------------------------------------------------------------
-- | Delayed arrays.
instance Layout l => Bulk (D l) a where
data Array (D l) a
= ADelayed !l (Index l -> a)
layout (ADelayed l _) = Delayed l
index (ADelayed _l f) ix = f ix
{-# INLINE_ARRAY index #-}
{-# INLINE_ARRAY layout #-}
-- Load -----------------------------------------------------------------------
instance (Layout l1, Target l2 a)
=> Load (D l1) l2 a where
loadS (ADelayed l1 get) !buf
= do let !(I# len) = size (extent l1)
let write ix x = unsafeWriteBuffer buf (I# ix) x
get' ix = get $ fromIndex l1 (I# ix)
{-# INLINE write #-}
{-# INLINE get' #-}
Seq.fillLinear write get' len
touchBuffer buf
{-# INLINE_ARRAY loadS #-}
loadP gang (ADelayed l1 get) !buf
= do traceEventIO "Repa.loadP[Delayed]: start"
let !(I# len) = size (extent l1)
let write ix x = unsafeWriteBuffer buf (I# ix) x
get' ix = get $ fromIndex l1 (I# ix)
{-# INLINE write #-}
{-# INLINE get' #-}
Par.fillChunked gang write get' len
touchBuffer buf
traceEventIO "Repa.loadP[Delayed]: end"
{-# INLINE_ARRAY loadP #-}
-- Conversions ----------------------------------------------------------------
-- | Wrap a function as a delayed array.
--
-- @> toList $ fromFunction (Linear 10) (* 2)
-- = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]@
--
fromFunction :: l -> (Index l -> a) -> Array (D l) a
fromFunction l f
= ADelayed l f
{-# INLINE_ARRAY fromFunction #-}
-- | Produce the extent of an array, and a function to retrieve an
-- arbitrary element.
toFunction :: Array (D l) a -> (l, Index l -> a)
toFunction (ADelayed l f) = (l, f)
{-# INLINE_ARRAY toFunction #-}
-- Operators ------------------------------------------------------------------
-- | Wrap an existing array in a delayed one.
delay :: Bulk l a
=> Array l a -> Array (D l) a
delay arr = map id arr
{-# INLINE delay #-}
-- | Apply a worker function to each element of an array,
-- yielding a new array with the same extent.
--
-- The resulting array is delayed, meaning every time you index into
-- it the element at that index is recomputed.
--
map :: Bulk l a
=> (a -> b) -> Array l a -> Array (D l) b
map f arr
= ADelayed (layout arr) (f . index arr)
{-# INLINE_ARRAY map #-}
-- | O(1). View the elements of a vector in reverse order.
--
-- @
-- > toList $ reverse $ fromList U [0..10 :: Int]
-- [10,9,8,7,6,5,4,3,2,1,0]
-- @
reverse :: BulkI l a
=> Array l a -> Array (D l) a
reverse !arr
= let !len = size (extent $ layout arr)
get ix = arr `index` (len - ix - 1)
in fromFunction (layout arr) get
{-# INLINE_ARRAY reverse #-}