repa 3.0.0.1 → 3.1.0.1
raw patch · 26 files changed
+604/−362 lines, 26 files
Files
- Data/Array/Repa.hs +53/−22
- Data/Array/Repa/Base.hs +30/−1
- Data/Array/Repa/Eval.hs +51/−37
- Data/Array/Repa/Eval/Chunked.hs +0/−16
- Data/Array/Repa/Eval/Cursored.hs +21/−22
- Data/Array/Repa/Eval/Fill.hs +3/−0
- Data/Array/Repa/Eval/Selection.hs +16/−11
- Data/Array/Repa/Index.hs +29/−7
- Data/Array/Repa/Operators/IndexSpace.hs +88/−43
- Data/Array/Repa/Operators/Interleave.hs +3/−3
- Data/Array/Repa/Operators/Mapping.hs +6/−6
- Data/Array/Repa/Operators/Reduction.hs +85/−42
- Data/Array/Repa/Operators/Selection.hs +7/−6
- Data/Array/Repa/Operators/Traversal.hs +8/−8
- Data/Array/Repa/Repr/ByteString.hs +6/−6
- Data/Array/Repa/Repr/Cursored.hs +33/−22
- Data/Array/Repa/Repr/Delayed.hs +36/−19
- Data/Array/Repa/Repr/ForeignPtr.hs +19/−15
- Data/Array/Repa/Repr/Partitioned.hs +8/−8
- Data/Array/Repa/Repr/Unboxed.hs +34/−28
- Data/Array/Repa/Repr/Undefined.hs +4/−4
- Data/Array/Repa/Repr/Vector.hs +17/−14
- Data/Array/Repa/Specialised/Dim2.hs +15/−7
- Data/Array/Repa/Stencil/Dim2.hs +16/−14
- Data/Array/Repa/Unsafe.hs +14/−0
- repa.cabal +2/−1
Data/Array/Repa.hs view
@@ -29,11 +29,8 @@ -- contained within `D` and `C` arrays without needing to create manifest -- intermediate arrays. ----- Converting between the parallel manifest representations (eg `U` and `B`)--- is either constant time or parallel copy, depending on the compatability--- of the physical representation. ----- /Writing fast code:/+-- /Advice for writing fast code:/ -- -- 1. Repa does not support nested parallellism. -- This means that you cannot `map` a parallel worker function across@@ -43,29 +40,59 @@ -- -- 2. Arrays of type @(Array D sh a)@ or @(Array C sh a)@ are /not real arrays/. -- They are represented as functions that compute each element on demand.--- You need to use a function like `computeS`, `computeP`, `computeUnboxedP`+-- You need to use `computeS`, `computeP`, `computeUnboxedP` -- and so on to actually evaluate the elements. -- --- 3. You should add @INLINE@ pragmas to all leaf-functions in your code, --- expecially ones that compute numberic results. This ensures they are --- specialised at the appropriate element types.+-- 3. Add @INLINE@ pragmas to all leaf-functions in your code, expecially ones+-- that compute numeric results. Non-inlined lazy function calls can cost+-- upwards of 50 cycles each, while each numeric operator only costs one (or less).+-- Inlining leaf functions also ensures they are specialised at the appropriate+-- numeric types.+-- +-- 4. Add bang patterns to all function arguments, and all fields of your data+-- types. In a high-performance Haskell program, the cost of lazy evaluation+-- can easily dominate the run time if not handled correctly. You don't want+-- to rely on the strictness analyser in numeric code because if it does not+-- return a perfect result then the performance of your program will be awful.+-- This is less of a problem for general Haskell code, and in a different+-- context relying on strictness analysis is fine. ----- 4. Scheduling a parallel computation takes about 200us on an OSX machine. --- You should sequential computation for small arrays in inner loops, --- or a the bottom of a divide-and-conquer algorithm.+-- 5. Scheduling a parallel computation takes about 200us on an OSX machine. +-- You should switch to sequential evaluation functions like `computeS` and+-- `foldS` for small arrays in inner loops, and at the bottom of a +-- divide-and-conquer algorithm. Consider using a `computeP` that evaluates+-- an array defined using `computeS` or `foldS` for each element. --+-- 6. Compile the modules that use Repa with the following flags:+-- @-Odph -rtsopts -threaded@+-- @-fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000@+-- @-fllvm -optlo-O3@+-- You don't want the liberate-case transform because it tends to duplicate+-- too much intermediate code, and is not needed if you use bang patterns+-- as per point 4. The unfolding flags tell the inliner to not to fool around with +-- heuristics, and just inline everything. If the binaries become too big then +-- split the array part of your program into separate modules and only compile+-- those with the unfolding flags.+--+-- 7. Repa writes to the GHC eventlog at the start and end of each parallel computation.+-- Use threadscope to see what your program is doing.+--+-- 8. Follow the advice on program structure in the comment for `deepSeqArrays`+--+-- 9. When you're sure your program works, switch to the unsafe versions+-- of functions like `traverse`. These don't do bounds checks.+-- module Data.Array.Repa ( -- * Abstract array representation- Array(..)- , module Data.Array.Repa.Shape+ module Data.Array.Repa.Shape , module Data.Array.Repa.Index+ , Array(..) , Repr(..), (!), toList , deepSeqArrays - -- * Converting between array representations+ -- * Computation , computeP, computeS , copyP, copyS- , now -- * Concrete array representations -- ** Delayed representation@@ -84,13 +111,15 @@ -- ** Index space transformations , reshape , append, (++)+ , extract , transpose- , extend- , backpermute, unsafeBackpermute+ , backpermute , backpermuteDft + -- ** Slice transformations , module Data.Array.Repa.Slice , slice+ , extend -- from Data.Array.Repa.Operators.Mapping ------------------- -- ** Structure preserving operations@@ -101,10 +130,10 @@ -- from Data.Array.Repa.Operators.Traversal ------------------ -- ** Generic traversal- , traverse, unsafeTraverse- , traverse2, unsafeTraverse2- , traverse3, unsafeTraverse3- , traverse4, unsafeTraverse4+ , traverse + , traverse2+ , traverse3+ , traverse4 -- from Data.Array.Repa.Operators.Interleave ----------------- -- ** Interleaving@@ -118,9 +147,11 @@ , foldAllP, foldAllS , sumP, sumS , sumAllP, sumAllS+ , equalsP, equalsS -- from Data.Array.Repa.Operators.Selection ------------------- , select)+ -- ** Selection+ , selectP) where import Data.Array.Repa.Base import Data.Array.Repa.Shape
Data/Array/Repa/Base.hs view
@@ -12,10 +12,11 @@ data family Array r sh e +-- Repr ----------------------------------------------------------------------- -- | Class of array representations that we can read elements from. -- class Repr r e where- -- | O(1). Take the extent of an array.+ -- | O(1). Take the extent (size) of an array. extent :: Shape sh => Array r sh e -> sh -- | O(1). Shape polymorphic indexing.@@ -61,6 +62,32 @@ -- The implementation of this function has been hand-unwound to work for up to -- four arrays. Putting more in the list yields `error`. -- +-- For functions that are /not/ marked as INLINE, you should apply `deepSeqArrays`+-- to argument arrays before using them in a @compute@ or @copy@ expression.+-- For example:+--+-- @ processArrays +-- :: Monad m +-- => Array U DIM2 Int -> Array U DIM2 Int +-- -> m (Array U DIM2 Int)+-- processArrays arr1 arr2+-- = [arr1, arr2] \`deepSeqArrays\` +-- do arr3 <- computeP $ map f arr1+-- arr4 <- computeP $ zipWith g arr3 arr2+-- return arr4+-- @+--+-- Applying `deepSeqArrays` tells the GHC simplifier that it's ok to unbox +-- size fields and the pointers to the underlying array data at the start+-- of the function. Without this, they may be unboxed repeatedly when+-- computing elements in the result arrays, which will make your program slow.+--+-- If you INLINE @processArrays@ into the function that computes @arr1@ and @arr2@,+-- then you don't need to apply `deepSeqArrays`. This is because a pointer+-- to the underlying data will be passed directly to the consumers and never boxed.+--+-- If you're not sure, then just follow the example code above.+-- deepSeqArrays :: (Shape sh, Repr r e) => [Array r sh e] -> b -> b@@ -82,4 +109,6 @@ -> a1 `deepSeqArray` a2 `deepSeqArray` a3 `deepSeqArray` a4 `deepSeqArray` x _ -> error "deepSeqArrays: only works for up to four arrays"++
Data/Array/Repa/Eval.hs view
@@ -12,8 +12,8 @@ , fromList -- * Converting between representations- , computeP, computeS- , copyP, copyS+ , computeS, computeP, suspendedComputeP+ , copyS, copyP, suspendedCopyP , now -- * Chunked filling@@ -46,8 +46,8 @@ -- | Parallel computation of array elements. ----- * The `Fill` class is defined so that the source array must have a--- delayed representation (`D` or `C`)+-- * 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.@@ -55,30 +55,47 @@ -- * If you want to convert a manifest array back to a delayed representation -- then use `delay` instead. ---computeP :: Fill r1 r2 sh e- => Array r1 sh e -> Array r2 sh e+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 #-}-computeP arr1- = arr1 `deepSeqArray` - unsafePerformIO- $ do marr2 <- newMArr (size $ extent arr1) - fillP arr1 marr2- unsafeFreezeMArr (extent arr1) marr2 -- | Sequential computation of array elements. computeS :: Fill r1 r2 sh e => Array r1 sh e -> Array r2 sh e-{-# INLINE [4] computeS #-} 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.@@ -87,44 +104,41 @@ -- -- * You can use it to copy manifest arrays between representations. ----- * You can also use it to compute elements, but doing this may not be as--- efficient. This is because delaying it the second time can hide--- information about the structure of the original computation.----copyP :: (Repr r1 e, Fill D r2 sh e)- => Array r1 sh e -> Array r2 sh e+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 #-}-copyP arr1 = computeP $ delay arr1 -- | 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 #-}-copyS arr1 = computeS $ delay arr1 - +-- | 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 #-} --- | Apply `deepSeqArray` to an array so the result is actually constructed--- at this point in a monadic computation. ------ * Haskell's laziness means that applications of `computeP` and `copyP` are--- automatically suspended.------ * Laziness can be problematic for data parallel programs, because we want--- each array to be constructed in parallel before moving onto the next one.--- --- For example:++-- | Monadic version of `deepSeqArray`. +-- +-- Forces an suspended array computation to be completed at this point+-- in a monadic computation. ----- @ do arr2 <- now $ computeP $ map f arr1--- arr3 <- now $ computeP $ zipWith arr2 arr1--- return arr3--- @+-- @ 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)-{-# INLINE [4] now #-} now arr = do arr `deepSeqArray` return () return arr+{-# INLINE [4] now #-}
Data/Array/Repa/Eval/Chunked.hs view
@@ -4,7 +4,6 @@ module Data.Array.Repa.Eval.Chunked ( fillChunkedP , fillChunkedS- , fillChunkedS' , fillChunkedIOP) where import Data.Array.Repa.Eval.Gang@@ -29,21 +28,6 @@ | otherwise = do write (I# ix) (getElem (I# ix)) fill (ix +# 1#)--fillChunkedS'- :: Int- -> (Int -> IO ())- -> IO ()--fillChunkedS' !(I# len) eat- = fill 0#- where fill !ix- | ix >=# len = return ()- | otherwise- = do eat (I# ix)- fill (ix +# 1#)-- -- | Fill something in parallel.
Data/Array/Repa/Eval/Cursored.hs view
@@ -11,9 +11,8 @@ import Data.Array.Repa.Shape import Data.Array.Repa.Eval.Elt import Data.Array.Repa.Eval.Gang-import GHC.Base (remInt, quotInt)-import Prelude as P-import GHC.Exts+import GHC.Base+import Prelude as P -- Non-cursored interface ----------------------------------------------------- -- | Fill a block in a rank-2 array in parallel.@@ -31,11 +30,11 @@ :: Elt a => (Int -> a -> IO ()) -- ^ Update function to write into result buffer. -> (DIM2 -> a) -- ^ Function to evaluate the element at an index.- -> Int -- ^ Width of the whole array.- -> Int -- ^ x0 lower left corner of block to fill- -> Int -- ^ y0 - -> Int -- ^ x1 upper right corner of block to fill- -> Int -- ^ y1+ -> Int# -- ^ Width of the whole array.+ -> Int# -- ^ x0 lower left corner of block to fill+ -> Int# -- ^ y0 + -> Int# -- ^ x1 upper right corner of block to fill+ -> Int# -- ^ y1 -> IO () {-# INLINE [0] fillBlock2P #-}@@ -92,33 +91,33 @@ -> (DIM2 -> cursor) -- ^ Make a cursor to a particular element. -> (DIM2 -> cursor -> cursor) -- ^ Shift the cursor by an offset. -> (cursor -> a) -- ^ Function to evaluate the element at an index.- -> Int -- ^ Width of the whole array.- -> Int -- ^ x0 lower left corner of block to fill- -> Int -- ^ y0- -> Int -- ^ x1 upper right corner of block to fill- -> Int -- ^ y1+ -> Int# -- ^ Width of the whole array.+ -> Int# -- ^ x0 lower left corner of block to fill+ -> Int# -- ^ y0+ -> Int# -- ^ x1 upper right corner of block to fill+ -> Int# -- ^ y1 -> IO () {-# INLINE [0] fillCursoredBlock2P #-} fillCursoredBlock2P !write !makeCursorFCB !shiftCursorFCB !getElemFCB- !(I# imageWidth) !x0 !y0 !x1 !y1+ !imageWidth !x0 !y0 !x1 !y1 = gangIO theGang fillBlock- where !threads = gangSize theGang- !blockWidth = x1 - x0 + 1+ where !(I# threads) = gangSize theGang+ !blockWidth = x1 -# x0 +# 1# -- All columns have at least this many pixels.- !colChunkLen = blockWidth `quotInt` threads+ !colChunkLen = I# (blockWidth `quotInt#` threads) -- Extra pixels that we have to divide between some of the threads.- !colChunkSlack = blockWidth `remInt` threads+ !colChunkSlack = I# (blockWidth `remInt#` threads) -- Get the starting pixel of a column in the image. {-# INLINE colIx #-} colIx !ix- | ix < colChunkSlack = x0 + ix * (colChunkLen + 1)- | otherwise = x0 + ix * colChunkLen + colChunkSlack+ | ix < colChunkSlack = (I# x0) + ix * (colChunkLen + 1)+ | otherwise = (I# x0) + (ix * colChunkLen) + colChunkSlack -- Give one column to each thread {-# INLINE fillBlock #-}@@ -126,8 +125,8 @@ fillBlock !ix = let !(I# x0') = colIx ix !(I# x1') = colIx (ix + 1) - 1- !(I# y0') = y0- !(I# y1') = y1+ !y0' = y0+ !y1' = y1 in fillCursoredBlock2S write makeCursorFCB shiftCursorFCB getElemFCB
Data/Array/Repa/Eval/Fill.hs view
@@ -26,6 +26,9 @@ -- | Freeze the mutable array into an immutable Repa array. unsafeFreezeMArr :: sh -> MArr r e -> IO (Array r sh e) + -- | Ensure the strucure of a mutable array is fully evaluated.+ deepSeqMArr :: MArr r e -> a -> a+ -- | O(n). Construct a manifest array from a list. fromList
Data/Array/Repa/Eval/Selection.hs view
@@ -96,31 +96,36 @@ -- Fill the given chunk with elements selected from this range of indices. makeChunk :: IORef (IOVector a) -> Int -> Int -> IO () makeChunk !ref !ixSrc !ixSrcEnd- = do vecDst <- VM.new (len `div` threads)- vecDst' <- fillChunk ixSrc ixSrcEnd vecDst 0 (VM.length vecDst - 1)- writeIORef ref vecDst'+ | ixSrc > ixSrcEnd+ = do vecDst <- VM.new 0+ writeIORef ref vecDst + | otherwise+ = do vecDst <- VM.new (len `div` threads)+ vecDst' <- fillChunk ixSrc ixSrcEnd vecDst 0 (VM.length vecDst)+ writeIORef ref vecDst' + -- The main filling loop. fillChunk :: Int -> Int -> IOVector a -> Int -> Int -> IO (IOVector a)- fillChunk !ixSrc !ixSrcEnd !vecDst !ixDst !ixDstEnd+ fillChunk !ixSrc !ixSrcEnd !vecDst !ixDst !ixDstLen -- If we've finished selecting elements, then slice the vector down -- so it doesn't have any empty space at the end.- | ixSrc >= ixSrcEnd+ | ixSrc > ixSrcEnd = return $ VM.slice 0 ixDst vecDst -- If we've run out of space in the chunk then grow it some more.- | ixDst >= ixDstEnd- = do let ixDstEnd' = VM.length vecDst * 2 - 1- vecDst' <- VM.grow vecDst (ixDstEnd + 1)- fillChunk (ixSrc + 1) ixSrcEnd vecDst' (ixDst + 1) ixDstEnd'+ | ixDst >= ixDstLen+ = do let ixDstLen' = (VM.length vecDst + 1) * 2+ vecDst' <- VM.grow vecDst ixDstLen'+ fillChunk ixSrc ixSrcEnd vecDst' ixDst ixDstLen' -- We've got a maching element, so add it to the chunk. | fnMatch ixSrc = do VM.unsafeWrite vecDst ixDst (fnProduce ixSrc)- fillChunk (ixSrc + 1) ixSrcEnd vecDst (ixDst + 1) ixDstEnd+ fillChunk (ixSrc + 1) ixSrcEnd vecDst (ixDst + 1) ixDstLen -- The element doesnt match, so keep going. | otherwise- = fillChunk (ixSrc + 1) ixSrcEnd vecDst ixDst ixDstEnd+ = fillChunk (ixSrc + 1) ixSrcEnd vecDst ixDst ixDstLen
Data/Array/Repa/Index.hs view
@@ -8,12 +8,8 @@ , (:.) (..) -- * Common dimensions.- , DIM0- , DIM1- , DIM2- , DIM3- , DIM4- , DIM5)+ , DIM0, DIM1, DIM2, DIM3, DIM4, DIM5+ , ix1, ix2, ix3, ix4, ix5) where import Data.Array.Repa.Shape import GHC.Base (quotInt, remInt)@@ -39,7 +35,33 @@ type DIM5 = DIM4 :. Int --- Shape ------------------------------------------------------------------------------------------+-- | Helper for index construction.+--+-- Use this instead of explicit constructors like @(Z :. (x :: Int))@.+-- The this is sometimes needed to ensure that 'x' is constrained to +-- be in @Int@.+ix1 :: Int -> DIM1+ix1 x = Z :. x+{-# INLINE ix1 #-}++ix2 :: Int -> Int -> DIM2+ix2 y x = Z :. y :. x+{-# INLINE ix2 #-}++ix3 :: Int -> Int -> Int -> DIM3+ix3 z y x = Z :. z :. y :. x+{-# INLINE ix3 #-}++ix4 :: Int -> Int -> Int -> Int -> DIM4+ix4 a z y x = Z :. a :. z :. y :. x+{-# INLINE ix4 #-}++ix5 :: Int -> Int -> Int -> Int -> Int -> DIM5+ix5 b a z y x = Z :. b :. a :. z :. y :. x+{-# INLINE ix5 #-}+++-- Shape ---------------------------------------------------------------------- instance Shape Z where {-# INLINE [1] rank #-} rank _ = 0
Data/Array/Repa/Operators/IndexSpace.hs view
@@ -4,10 +4,11 @@ ( reshape , append, (++) , transpose- , extend- , slice+ , extract , backpermute, unsafeBackpermute- , backpermuteDft, unsafeBackpermuteDft)+ , backpermuteDft, unsafeBackpermuteDft+ , extend, unsafeExtend + , slice, unsafeSlice) where import Data.Array.Repa.Index import Data.Array.Repa.Slice@@ -29,7 +30,6 @@ -> Array r1 sh1 e -> Array D sh2 e -{-# INLINE [3] reshape #-} reshape sh2 arr | not $ S.size sh2 == S.size (extent arr) = error @@ -38,6 +38,7 @@ reshape sh2 arr = fromFunction sh2 $ unsafeIndex arr . fromIndex (extent arr) . toIndex sh2+{-# INLINE [2] reshape #-} -- | Append two arrays.@@ -48,7 +49,6 @@ -> Array r2 (sh :. Int) e -> Array D (sh :. Int) e -{-# INLINE [3] append #-} append arr1 arr2 = unsafeTraverse2 arr1 arr2 fnExtent fnElem where@@ -60,9 +60,11 @@ fnElem f1 f2 (sh :. i) | i < n = f1 (sh :. i) | otherwise = f2 (sh :. (i - n))+{-# INLINE [2] append #-} -{-# INLINE (++) #-}+ (++) arr1 arr2 = append arr1 arr2+{-# INLINE (++) #-} -- | Transpose the lowest two dimensions of an array.@@ -73,45 +75,22 @@ => Array r (sh :. Int :. Int) e -> Array D (sh :. Int :. Int) e -{-# INLINE [3] transpose #-} transpose arr = unsafeTraverse arr (\(sh :. m :. n) -> (sh :. n :.m)) (\f -> \(sh :. i :. j) -> f (sh :. j :. i))+{-# INLINE [2] transpose #-} --- | Extend an array, according to a given slice specification.-extend- :: ( Slice sl- , Shape (FullShape sl)- , Shape (SliceShape sl)- , Repr r e)- => sl- -> Array r (SliceShape sl) e- -> Array D (FullShape sl) e--{-# INLINE [3] extend #-}-extend sl arr- = unsafeBackpermute- (fullOfSlice sl (extent arr))- (sliceOfFull sl)- arr---- | Take a slice from an array, according to a given specification.-slice :: ( Slice sl- , Shape (FullShape sl)- , Shape (SliceShape sl)- , Repr r e)- => Array r (FullShape sl) e- -> sl- -> Array D (SliceShape sl) e--{-# INLINE [3] slice #-}-slice arr sl- = unsafeBackpermute- (sliceOfFull sl (extent arr))- (fullOfSlice sl)- arr+-- | Extract a sub-range of elements from an array.+extract :: (Shape sh, Repr r e)+ => sh -- ^ Starting index.+ -> sh -- ^ Size of result.+ -> Array r sh e + -> Array D sh e+extract start sz arr+ = fromFunction sz (\ix -> arr `unsafeIndex` (addDim start ix))+{-# INLINE [2] extract #-} -- | Backwards permutation of an array's elements.@@ -126,13 +105,13 @@ -> Array r sh1 e -- ^ Source array. -> Array D sh2 e -{-# INLINE [3] backpermute #-} backpermute newExtent perm arr = traverse arr (const newExtent) (. perm)+{-# INLINE [2] backpermute #-} -{-# INLINE [3] unsafeBackpermute #-} unsafeBackpermute newExtent perm arr = unsafeTraverse arr (const newExtent) (. perm)+{-# INLINE [2] unsafeBackpermute #-} -- | Default backwards permutation of an array's elements.@@ -148,19 +127,85 @@ -> Array r1 sh1 e -- ^ Source array. -> Array D sh2 e -{-# INLINE [3] backpermuteDft #-} backpermuteDft arrDft fnIndex arrSrc = fromFunction (extent arrDft) fnElem where fnElem ix = case fnIndex ix of Just ix' -> arrSrc `index` ix' Nothing -> arrDft `index` ix+{-# INLINE [2] backpermuteDft #-} -{-# INLINE [3] unsafeBackpermuteDft #-} unsafeBackpermuteDft arrDft fnIndex arrSrc = fromFunction (extent arrDft) fnElem where fnElem ix = case fnIndex ix of Just ix' -> arrSrc `unsafeIndex` ix' Nothing -> arrDft `unsafeIndex` ix+{-# INLINE [2] unsafeBackpermuteDft #-} +++-- | Extend an array, according to a given slice specification.+--+-- For example, to replicate the rows of an array use the following:+--+-- @extend arr (Any :. (5::Int) :. All)@+--+extend, unsafeExtend+ :: ( Slice sl+ , Shape (FullShape sl)+ , Shape (SliceShape sl)+ , Repr r e)+ => sl+ -> Array r (SliceShape sl) e+ -> Array D (FullShape sl) e++extend sl arr+ = backpermute+ (fullOfSlice sl (extent arr))+ (sliceOfFull sl)+ arr+{-# INLINE [2] extend #-}++unsafeExtend sl arr+ = unsafeBackpermute+ (fullOfSlice sl (extent arr))+ (sliceOfFull sl)+ arr+{-# INLINE [2] unsafeExtend #-}++++-- | Take a slice from an array, according to a given specification.+--+-- For example, to take a row from a matrix use the following:+--+-- @slice arr (Any :. (5::Int) :. All)@+--+-- To take a column use:+--+-- @slice arr (Any :. (5::Int))@+--+slice, unsafeSlice+ :: ( Slice sl+ , Shape (FullShape sl)+ , Shape (SliceShape sl)+ , Repr r e)+ => Array r (FullShape sl) e+ -> sl+ -> Array D (SliceShape sl) e++slice arr sl+ = backpermute+ (sliceOfFull sl (extent arr))+ (fullOfSlice sl)+ arr+{-# INLINE [2] slice #-}+++unsafeSlice arr sl+ = unsafeBackpermute+ (sliceOfFull sl (extent arr))+ (fullOfSlice sl)+ arr+{-# INLINE [2] unsafeSlice #-}
Data/Array/Repa/Operators/Interleave.hs view
@@ -29,7 +29,7 @@ -> Array r2 (sh :. Int) a -> Array D (sh :. Int) a -{-# INLINE [3] interleave2 #-}+{-# INLINE [2] interleave2 #-} interleave2 arr1 arr2 = arr1 `deepSeqArray` arr2 `deepSeqArray` unsafeTraverse2 arr1 arr2 shapeFn elemFn@@ -58,7 +58,7 @@ -> Array r3 (sh :. Int) a -> Array D (sh :. Int) a -{-# INLINE [3] interleave3 #-}+{-# INLINE [2] interleave3 #-} interleave3 arr1 arr2 arr3 = arr1 `deepSeqArray` arr2 `deepSeqArray` arr3 `deepSeqArray` unsafeTraverse3 arr1 arr2 arr3 shapeFn elemFn@@ -90,7 +90,7 @@ -> Array r4 (sh :. Int) a -> Array D (sh :. Int) a -{-# INLINE [3] interleave4 #-}+{-# INLINE [2] interleave4 #-} interleave4 arr1 arr2 arr3 arr4 = arr1 `deepSeqArray` arr2 `deepSeqArray` arr3 `deepSeqArray` arr4 `deepSeqArray` unsafeTraverse4 arr1 arr2 arr3 arr4 shapeFn elemFn
Data/Array/Repa/Operators/Mapping.hs view
@@ -27,7 +27,7 @@ -- map :: (Shape sh, Repr r a) => (a -> b) -> Array r sh a -> Array D sh b-{-# INLINE [4] map #-}+{-# INLINE [3] map #-} map f arr = case delay arr of ADelayed sh g -> ADelayed sh (f . g)@@ -42,7 +42,7 @@ => (a -> b -> c) -> Array r1 sh a -> Array r2 sh b -> Array D sh c-{-# INLINE [3] zipWith #-}+{-# INLINE [2] zipWith #-} zipWith f arr1 arr2 = arr1 `deepSeqArray` arr2 `deepSeqArray` let @@ -112,11 +112,11 @@ -- Cursored --------------------------- instance Combine C a C b where- {-# INLINE [4] cmap #-}+ {-# INLINE [3] cmap #-} cmap f (ACursored sh makec shiftc loadc) = ACursored sh makec shiftc (f . loadc) - {-# INLINE [3] czipWith #-}+ {-# INLINE [2] czipWith #-} czipWith f arr1 (ACursored sh makec shiftc loadc) = let {-# INLINE makec' #-} makec' ix = (ix, makec ix)@@ -149,11 +149,11 @@ , Combine r12 a r22 b) => Combine (P r11 r12) a (P r21 r22) b where - {-# INLINE [4] cmap #-}+ {-# INLINE [3] cmap #-} cmap f (APart sh range arr1 arr2) = APart sh range (cmap f arr1) (cmap f arr2) - {-# INLINE [3] czipWith #-}+ {-# INLINE [2] czipWith #-} czipWith f arr1 (APart sh range arr21 arr22) = APart sh range (czipWith f arr1 arr21) (czipWith f arr1 arr22)
Data/Array/Repa/Operators/Reduction.hs view
@@ -1,15 +1,17 @@ {-# LANGUAGE BangPatterns, ExplicitForAll, TypeOperators, MagicHash #-}-+{-# OPTIONS -fno-warn-orphans #-} module Data.Array.Repa.Operators.Reduction ( foldS, foldP , foldAllS, foldAllP , sumS, sumP- , sumAllS, sumAllP)+ , sumAllS, sumAllP+ , equalsS, equalsP) where import Data.Array.Repa.Base import Data.Array.Repa.Index-import Data.Array.Repa.Eval.Elt+import Data.Array.Repa.Eval import Data.Array.Repa.Repr.Unboxed+import Data.Array.Repa.Operators.Mapping as R import Data.Array.Repa.Shape as S import qualified Data.Vector.Unboxed as V import qualified Data.Vector.Unboxed.Mutable as M@@ -18,24 +20,26 @@ import System.IO.Unsafe import GHC.Exts --- foldS ----------------------------------------------------------------------+-- fold ---------------------------------------------------------------------- -- | Sequential reduction of the innermost dimension of an arbitrary rank array. -- -- Combine this with `transpose` to fold any other dimension.-foldS :: (Shape sh, Elt a, Unbox a, Repr r a)- => (a -> a -> a)- -> a- -> Array r (sh :. Int) a- -> Array U sh a-{-# INLINE [2] foldS #-}+foldS :: (Shape sh, Elt a, Unbox a, Repr r a)+ => (a -> a -> a)+ -> a+ -> Array r (sh :. Int) a+ -> Array U sh a+ foldS f z arr- = let sh@(sz :. n') = extent arr+ = arr `deepSeqArray`+ let sh@(sz :. n') = extent arr !(I# n) = n' in unsafePerformIO $ do mvec <- M.unsafeNew (S.size sz) E.foldS mvec (\ix -> arr `unsafeIndex` fromIndex sh (I# ix)) f z n !vec <- V.unsafeFreeze mvec- return $ fromUnboxed sz vec+ now $ fromUnboxed sz vec+{-# INLINE [1] foldS #-} -- | Parallel reduction of the innermost dimension of an arbitray rank array.@@ -45,27 +49,32 @@ -- example @0@ is neutral with respect to @(+)@ as @0 + a = a@. -- These restrictions are required to support parallel evaluation, as the -- starting element may be used multiple times depending on the number of threads.-foldP :: (Shape sh, Elt a, Unbox a, Repr r a)- => (a -> a -> a)- -> a- -> Array r (sh :. Int) a- -> Array U sh a-{-# INLINE [2] foldP #-}+foldP + :: (Shape sh, Elt a, Unbox a, Repr r a, Monad m)+ => (a -> a -> a)+ -> a+ -> Array r (sh :. Int) a+ -> m (Array U sh a)+ foldP f z arr - = let sh@(sz :. n) = extent arr+ = arr `deepSeqArray`+ let sh@(sz :. n) = extent arr in case rank sh of -- specialise rank-1 arrays, else one thread does all the work. -- We can't match against the shape constructor, -- otherwise type error: (sz ~ Z) --- 1 -> let !vec = V.singleton $ foldAllP f z arr- in fromUnboxed sz vec+ 1 -> do+ x <- foldAllP f z arr+ now $ fromUnboxed sz $ V.singleton x - _ -> unsafePerformIO + _ -> now+ $ unsafePerformIO $ do mvec <- M.unsafeNew (S.size sz) E.foldP mvec (\ix -> arr `unsafeIndex` fromIndex sh ix) f z n !vec <- V.unsafeFreeze mvec- return $ fromUnboxed sz vec+ now $ fromUnboxed sz vec+{-# INLINE [1] foldP #-} -- foldAll --------------------------------------------------------------------@@ -76,7 +85,7 @@ -> a -> Array r sh a -> a-{-# INLINE [2] foldAllS #-}+ foldAllS f z arr = arr `deepSeqArray` let !ex = extent arr@@ -84,6 +93,7 @@ in E.foldAllS (\ix -> arr `unsafeIndex` fromIndex ex (I# ix)) f z n +{-# INLINE [1] foldAllS #-} -- | Parallel reduction of an array of arbitrary rank to a single scalar value.@@ -93,17 +103,21 @@ -- for example @0@ is neutral with respect to @(+)@ as @0 + a = a@. -- These restrictions are required to support parallel evaluation, as the -- starting element may be used multiple times depending on the number of threads.-foldAllP :: (Shape sh, Elt a, Unbox a, Repr r a)- => (a -> a -> a)- -> a- -> Array r sh a- -> a-{-# INLINE [2] foldAllP #-}+foldAllP + :: (Shape sh, Elt a, Unbox a, Repr r a, Monad m)+ => (a -> a -> a)+ -> a+ -> Array r sh a+ -> m a+ foldAllP f z arr - = let sh = extent arr+ = arr `deepSeqArray`+ let sh = extent arr n = size sh- in unsafePerformIO + in return+ $ unsafePerformIO $ E.foldAllP (\ix -> arr `unsafeIndex` fromIndex sh ix) f z n+{-# INLINE [1] foldAllP #-} -- sum ------------------------------------------------------------------------@@ -111,16 +125,16 @@ sumS :: (Shape sh, Num a, Elt a, Unbox a, Repr r a) => Array r (sh :. Int) a -> Array U sh a-{-# INLINE [4] sumS #-} sumS = foldS (+) 0+{-# INLINE [3] sumS #-} --- | Sequential sum the innermost dimension of an array.-sumP :: (Shape sh, Num a, Elt a, Unbox a, Repr r a)+-- | Parallel sum the innermost dimension of an array.+sumP :: (Shape sh, Num a, Elt a, Unbox a, Repr r a, Monad m) => Array r (sh :. Int) a- -> Array U sh a-{-# INLINE [4] sumP #-}-sumP = foldP (+) 0+ -> m (Array U sh a)+sumP = foldP (+) 0 +{-# INLINE [3] sumP #-} -- sumAll ---------------------------------------------------------------------@@ -128,14 +142,43 @@ sumAllS :: (Shape sh, Elt a, Unbox a, Num a, Repr r a) => Array r sh a -> a-{-# INLINE [4] sumAllS #-} sumAllS = foldAllS (+) 0+{-# INLINE [3] sumAllS #-} -- | Parallel sum all the elements of an array.-sumAllP :: (Shape sh, Elt a, Unbox a, Num a, Repr r a)+sumAllP :: (Shape sh, Elt a, Unbox a, Num a, Repr r a, Monad m) => Array r sh a- -> a-{-# INLINE [4] sumAllP #-}+ -> m a sumAllP = foldAllP (+) 0+{-# INLINE [3] sumAllP #-}+++-- Equality ------------------------------------------------------------------+instance (Shape sh, Repr r e, Eq e) => Eq (Array r sh e) where+ (==) arr1 arr2+ = extent arr1 == extent arr2+ && (foldAllS (&&) True (R.zipWith (==) arr1 arr2))+++-- | Check whether two arrays have the same shape and contain equal elements,+-- in parallel.+equalsP :: (Shape sh, Repr r1 e, Repr r2 e, Eq e, Monad m) + => Array r1 sh e + -> Array r2 sh e+ -> m Bool+equalsP arr1 arr2+ = do same <- foldAllP (&&) True (R.zipWith (==) arr1 arr2)+ return $ (extent arr1 == extent arr2) && same+++-- | Check whether two arrays have the same shape and contain equal elements,+-- sequentially.+equalsS :: (Shape sh, Repr r1 e, Repr r2 e, Eq e) + => Array r1 sh e + -> Array r2 sh e+ -> Bool+equalsS arr1 arr2+ = extent arr1 == extent arr2+ && (foldAllS (&&) True (R.zipWith (==) arr1 arr2))
Data/Array/Repa/Operators/Selection.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE BangPatterns #-} module Data.Array.Repa.Operators.Selection- (select)+ (selectP) where import Data.Array.Repa.Index import Data.Array.Repa.Base@@ -19,15 +19,15 @@ -- -- * Use the integer as the index into the array you're filtering. ---select :: Unbox a+selectP :: (Unbox a, Monad m) => (Int -> Bool) -- ^ If the Int matches this predicate, -> (Int -> a) -- ^ ... then pass it to this fn to produce a value -> Int -- ^ Range between 0 and this maximum.- -> Array U DIM1 a -- ^ Array containing produced values.+ -> m (Array U DIM1 a) -- ^ Array containing produced values. -{-# INLINE [2] select #-}-select match produce len- = unsafePerformIO+selectP match produce len+ = return+ $ unsafePerformIO $ do (sh, vec) <- selectIO return $ sh `seq` vec `seq` fromUnboxed sh vec@@ -41,3 +41,4 @@ let result = V.concat vecs' return (Z :. V.length result, result)+{-# INLINE [1] selectP #-}
Data/Array/Repa/Operators/Traversal.hs view
@@ -20,15 +20,15 @@ -- It is passed a lookup function to get elements of the source. -> Array D sh' b -{-# INLINE [4] traverse #-} traverse arr transExtent newElem = arr `deepSeqArray` fromFunction (transExtent (extent arr)) (newElem (index arr))+{-# INLINE [3] traverse #-} -{-# INLINE [4] unsafeTraverse #-} unsafeTraverse arr transExtent newElem = arr `deepSeqArray` fromFunction (transExtent (extent arr)) (newElem (unsafeIndex arr))+{-# INLINE [3] unsafeTraverse #-} -- | Unstructured traversal over two arrays at once.@@ -45,17 +45,17 @@ -- source arrays. -> Array D sh'' c -{-# INLINE [4] traverse2 #-} traverse2 arrA arrB transExtent newElem = arrA `deepSeqArray` arrB `deepSeqArray` fromFunction (transExtent (extent arrA) (extent arrB)) (newElem (index arrA) (index arrB))+{-# INLINE [3] traverse2 #-} -{-# INLINE [4] unsafeTraverse2 #-} unsafeTraverse2 arrA arrB transExtent newElem = arrA `deepSeqArray` arrB `deepSeqArray` fromFunction (transExtent (extent arrA) (extent arrB)) (newElem (unsafeIndex arrA) (unsafeIndex arrB))+{-# INLINE [3] unsafeTraverse2 #-} -- | Unstructured traversal over three arrays at once.@@ -74,17 +74,17 @@ -> sh4 -> d ) -> Array D sh4 d -{-# INLINE [4] traverse3 #-} traverse3 arrA arrB arrC transExtent newElem = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray` fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC)) (newElem (index arrA) (index arrB) (index arrC))+{-# INLINE [3] traverse3 #-} -{-# INLINE [4] unsafeTraverse3 #-} unsafeTraverse3 arrA arrB arrC transExtent newElem = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray` fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC)) (newElem (unsafeIndex arrA) (unsafeIndex arrB) (unsafeIndex arrC))+{-# INLINE [3] unsafeTraverse3 #-} -- | Unstructured traversal over four arrays at once.@@ -104,17 +104,17 @@ -> sh5 -> e ) -> Array D sh5 e -{-# INLINE [4] traverse4 #-} traverse4 arrA arrB arrC arrD transExtent newElem = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray` arrD `deepSeqArray` fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC) (extent arrD)) (newElem (index arrA) (index arrB) (index arrC) (index arrD))+{-# INLINE [3] traverse4 #-} -{-# INLINE [4] unsafeTraverse4 #-} unsafeTraverse4 arrA arrB arrC arrD transExtent newElem = arrA `deepSeqArray` arrB `deepSeqArray` arrC `deepSeqArray` arrD `deepSeqArray` fromFunction (transExtent (extent arrA) (extent arrB) (extent arrC) (extent arrD)) (newElem (unsafeIndex arrA) (unsafeIndex arrB) (unsafeIndex arrC) (unsafeIndex arrD))+{-# INLINE [3] unsafeTraverse4 #-}
Data/Array/Repa/Repr/ByteString.hs view
@@ -24,21 +24,21 @@ -- Repr ----------------------------------------------------------------------- -- | Read elements from a `ByteString`. instance Repr B Word8 where- {-# INLINE linearIndex #-} linearIndex (AByteString _ bs) ix = bs `B.index` ix+ {-# INLINE linearIndex #-} - {-# INLINE unsafeLinearIndex #-} unsafeLinearIndex (AByteString _ bs) ix = bs `BU.unsafeIndex` ix+ {-# INLINE unsafeLinearIndex #-} - {-# INLINE extent #-} extent (AByteString sh _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (AByteString sh bs) x = sh `deepSeq` bs `seq` x+ {-# INLINE deepSeqArray #-} -- Conversions ----------------------------------------------------------------@@ -46,12 +46,12 @@ fromByteString :: Shape sh => sh -> ByteString -> Array B sh Word8-{-# INLINE fromByteString #-} fromByteString sh bs = AByteString sh bs+{-# INLINE fromByteString #-} -- | O(1). Unpack a `ByteString` from an array. toByteString :: Array B sh Word8 -> ByteString-{-# INLINE toByteString #-} toByteString (AByteString _ bs) = bs+{-# INLINE toByteString #-}
Data/Array/Repa/Repr/Cursored.hs view
@@ -12,6 +12,7 @@ import Data.Array.Repa.Eval.Elt import Data.Array.Repa.Eval.Cursored import GHC.Exts+import Debug.Trace -- | Cursored Arrays. -- These are produced by Repa's stencil functions, and help the fusion@@ -39,63 +40,72 @@ -- Repr ----------------------------------------------------------------------- -- | Compute elements of a cursored array. instance Repr C a where- {-# INLINE index #-} index (ACursored _ makec _ loadc) = loadc . makec+ {-# INLINE index #-} - {-# INLINE unsafeIndex #-} unsafeIndex = index+ {-# INLINE unsafeIndex #-} - {-# INLINE linearIndex #-} linearIndex (ACursored sh makec _ loadc) = loadc . makec . fromIndex sh+ {-# INLINE linearIndex #-} - {-# INLINE extent #-} extent (ACursored sh _ _ _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (ACursored sh makec shiftc loadc) y = sh `deepSeq` makec `seq` shiftc `seq` loadc `seq` y+ {-# INLINE deepSeqArray #-} -- Fill ----------------------------------------------------------------------- -- | Compute all elements in an rank-2 array. instance (Fillable r2 e, Elt e) => Fill C r2 DIM2 e where- {-# INLINE fillP #-}- fillP (ACursored (Z :. h :. w) makec shiftc loadc) marr- = fillCursoredBlock2P + fillP (ACursored (Z :. (I# h) :. (I# w)) makec shiftc loadc) marr+ = do traceEventIO "Repa.fillP[Cursored]: start"+ fillCursoredBlock2P (unsafeWriteMArr marr) makec shiftc loadc- w 0 0 (w - 1) (h - 1) -- {-# INLINE fillS #-}+ w 0# 0# (w -# 1#) (h -# 1#) + traceEventIO "Repa.fillP[Cursored]: end"+ {-# INLINE fillP #-}+ fillS (ACursored (Z :. (I# h) :. (I# w)) makec shiftc loadc) marr- = fillCursoredBlock2S + = do traceEventIO "Repa.fillS[Cursored]: start"+ fillCursoredBlock2S (unsafeWriteMArr marr) makec shiftc loadc w 0# 0# (w -# 1#) (h -# 1#) -+ traceEventIO "Repa.fillS[Cursored]: end"+ {-# INLINE fillS #-}+ -- | Compute a range of elements in a rank-2 array. instance (Fillable r2 e, Elt e) => FillRange C r2 DIM2 e where- {-# INLINE fillRangeP #-}- fillRangeP (ACursored (Z :. _h :. w) makec shiftc loadc) marr- (Z :. y0 :. x0) (Z :. y1 :. x1)- = fillCursoredBlock2P + fillRangeP (ACursored (Z :. _h :. (I# w)) makec shiftc loadc) marr+ (Z :. (I# y0) :. (I# x0)) (Z :. (I# y1) :. (I# x1))+ = do traceEventIO "Repa.fillRangeP[Cursored]: start"+ fillCursoredBlock2P (unsafeWriteMArr marr) makec shiftc loadc w x0 y0 x1 y1-- {-# INLINE fillRangeS #-}+ traceEventIO "Repa.fillRangeP[Cursored]: end"+ {-# INLINE fillRangeP #-}+ fillRangeS (ACursored (Z :. _h :. (I# w)) makec shiftc loadc) marr (Z :. (I# y0) :. (I# x0)) (Z :. (I# y1) :. (I# x1))- = fillCursoredBlock2S+ = do traceEventIO "Repa.fillRangeS[Cursored]: start"+ fillCursoredBlock2S (unsafeWriteMArr marr) makec shiftc loadc w x0 y0 x1 y1- + traceEventIO "Repa.fillRangeS[Cursored]: end"+ {-# INLINE fillRangeS #-}+ + -- Conversions ---------------------------------------------------------------- -- | Define a new cursored array. makeCursored @@ -105,5 +115,6 @@ -> (cursor -> e) -- ^ Compute the element at the cursor. -> Array C sh e -{-# INLINE makeCursored #-} makeCursored = ACursored+{-# INLINE makeCursored #-}+
Data/Array/Repa/Repr/Delayed.hs view
@@ -11,9 +11,13 @@ 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 data instance Array D sh e = ADelayed @@ -24,66 +28,79 @@ -- Repr ----------------------------------------------------------------------- -- | Compute elements of a delayed array. instance Repr D a where- {-# INLINE index #-} index (ADelayed _ f) ix = f ix+ {-# INLINE index #-} - {-# INLINE linearIndex #-} linearIndex (ADelayed sh f) ix = f (fromIndex sh ix)+ {-# INLINE linearIndex #-} - {-# INLINE extent #-} extent (ADelayed sh _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (ADelayed sh f) y = sh `deepSeq` f `seq` y+ {-# INLINE deepSeqArray #-} -- Fill ----------------------------------------------------------------------- -- | Compute all elements in an array. instance (Fillable r2 e, Shape sh) => Fill D r2 sh e where- {-# INLINE [4] fillP #-} fillP (ADelayed sh getElem) marr- = fillChunkedP (size sh) (unsafeWriteMArr marr) (getElem . fromIndex sh) + = marr `deepSeqMArr` + do traceEventIO "Repa.fillP[Delayed]: start"+ fillChunkedP (size sh) (unsafeWriteMArr marr) (getElem . fromIndex sh) + traceEventIO "Repa.fillP[Delayed]: end"+ {-# INLINE [4] fillP #-} - {-# INLINE [4] fillS #-} fillS (ADelayed sh getElem) marr- = fillChunkedS (size sh) (unsafeWriteMArr marr) (getElem . fromIndex sh)+ = marr `deepSeqMArr` + do traceEventIO "Repa.fillS[Delayed]: start"+ fillChunkedS (size sh) (unsafeWriteMArr marr) (getElem . fromIndex sh)+ traceEventIO "Repa.fillS[Delayed]: end"+ {-# INLINE [4] fillS #-} -- | Compute a range of elements in a rank-2 array. instance (Fillable r2 e, Elt e) => FillRange D r2 DIM2 e where+ fillRangeP (ADelayed (Z :. _h :. (I# w)) getElem) marr+ (Z :. (I# y0) :. (I# x0)) (Z :. (I# y1) :. (I# x1))+ = marr `deepSeqMArr` + do traceEventIO "Repa.fillRangeP[Delayed]: start"+ fillBlock2P (unsafeWriteMArr marr) + getElem+ w x0 y0 x1 y1+ traceEventIO "Repa.fillRangeP[Delayed]: end" {-# INLINE [1] fillRangeP #-}- fillRangeP (ADelayed (Z :. _h :. w) getElem) marr- (Z :. y0 :. x0) (Z :. y1 :. x1)- = fillBlock2P (unsafeWriteMArr marr) - getElem- w x0 y0 x1 y1 - {-# INLINE [1] fillRangeS #-} fillRangeS (ADelayed (Z :. _h :. (I# w)) getElem) marr (Z :. (I# y0) :. (I# x0)) (Z :. (I# y1) :. (I# x1))- = fillBlock2S (unsafeWriteMArr marr) + = marr `deepSeqMArr`+ do traceEventIO "Repa.fillRangeS[Delayed]: start"+ fillBlock2S (unsafeWriteMArr marr) getElem w x0 y0 x1 y1+ traceEventIO "Repa.fillRangeS[Delayed]: end"+ {-# INLINE [1] fillRangeS #-} -- Conversions ---------------------------------------------------------------- -- | O(1). Wrap a function as a delayed array. fromFunction :: sh -> (sh -> a) -> Array D sh a-{-# INLINE fromFunction #-} fromFunction sh f = ADelayed sh f +{-# INLINE fromFunction #-} --- | O(1). Produce the extent of an array and a function to retrieve an arbitrary element.+-- | O(1). Produce the extent of an array, and a function to retrieve an+-- arbitrary element. toFunction :: (Shape sh, Repr r1 a) => Array r1 sh a -> (sh, sh -> a)-{-# INLINE toFunction #-} toFunction arr = case delay arr of ADelayed sh f -> (sh, f)+{-# INLINE toFunction #-} -- | O(1). Delay an array.@@ -93,7 +110,7 @@ -- delay :: (Shape sh, Repr r e) => Array r sh e -> Array D sh e+delay arr = ADelayed (extent arr) (unsafeIndex arr) {-# INLINE delay #-}-delay arr = ADelayed (extent arr) (index arr)
Data/Array/Repa/Repr/ForeignPtr.hs view
@@ -12,6 +12,7 @@ import Foreign.ForeignPtr import Foreign.Marshal.Alloc import System.IO.Unsafe+import qualified Foreign.ForeignPtr.Unsafe as Unsafe -- | Arrays represented as foreign buffers in the C heap. data F@@ -21,7 +22,6 @@ -- Repr ----------------------------------------------------------------------- -- | Read elements from a foreign buffer. instance Storable a => Repr F a where- {-# INLINE linearIndex #-} linearIndex (AForeignPtr _ len fptr) ix | ix < len = unsafePerformIO @@ -30,21 +30,22 @@ | otherwise = error "Repa: foreign array index out of bounds"-- {-# INLINE unsafeLinearIndex #-}+ {-# INLINE linearIndex #-}+ unsafeLinearIndex (AForeignPtr _ _ fptr) ix = unsafePerformIO $ withForeignPtr fptr $ \ptr -> peekElemOff ptr ix+ {-# INLINE unsafeLinearIndex #-} - {-# INLINE extent #-} extent (AForeignPtr sh _ _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (AForeignPtr sh len fptr) x = sh `deepSeq` len `seq` fptr `seq` x-+ {-# INLINE deepSeqArray #-}+ -- Fill ----------------------------------------------------------------------- -- | Filling of foreign buffers.@@ -52,7 +53,6 @@ data MArr F e = FPArr !Int !(ForeignPtr e) - {-# INLINE newMArr #-} newMArr n = do let (proxy :: e) = undefined ptr <- mallocBytes (sizeOf proxy * n)@@ -60,32 +60,36 @@ fptr <- newForeignPtr finalizerFree ptr return $ FPArr n fptr+ {-# INLINE newMArr #-} - {-# INLINE unsafeWriteMArr #-} unsafeWriteMArr (FPArr _ fptr) !ix !x- = withForeignPtr fptr- $ \ptr -> pokeElemOff ptr ix x+ = pokeElemOff (Unsafe.unsafeForeignPtrToPtr fptr) ix x+ {-# INLINE unsafeWriteMArr #-} - {-# INLINE unsafeFreezeMArr #-} unsafeFreezeMArr !sh (FPArr len fptr) = return $ AForeignPtr sh len fptr+ {-# INLINE unsafeFreezeMArr #-} + deepSeqMArr !(FPArr _ ptr) x+ = Unsafe.unsafeForeignPtrToPtr ptr `seq` x+ {-# INLINE deepSeqMArr #-} + -- Conversions ---------------------------------------------------------------- -- | O(1). Wrap a `ForeignPtr` as an array. fromForeignPtr :: Shape sh => sh -> ForeignPtr e -> Array F sh e-{-# INLINE fromForeignPtr #-} fromForeignPtr !sh !fptr = AForeignPtr sh (size sh) fptr+{-# INLINE fromForeignPtr #-} -- | O(1). Unpack a `ForeignPtr` from an array. toForeignPtr :: Array F sh e -> ForeignPtr e-{-# INLINE toForeignPtr #-} toForeignPtr (AForeignPtr _ _ fptr) = fptr+{-# INLINE toForeignPtr #-} -- | Compute an array sequentially and write the elements into a foreign@@ -94,9 +98,9 @@ computeIntoS :: Fill r1 F sh e => ForeignPtr e -> Array r1 sh e -> IO ()-{-# INLINE computeIntoS #-} computeIntoS !fptr !arr = fillS arr (FPArr 0 fptr)+{-# INLINE computeIntoS #-} -- | Compute an array in parallel and write the elements into a foreign@@ -105,7 +109,7 @@ computeIntoP :: Fill r1 F sh e => ForeignPtr e -> Array r1 sh e -> IO ()-{-# INLINE computeIntoP #-} computeIntoP !fptr !arr = fillP arr (FPArr 0 fptr)+{-# INLINE computeIntoP #-}
Data/Array/Repa/Repr/Partitioned.hs view
@@ -34,49 +34,49 @@ (sh -> Bool) -- predicate to check whether were in range -- | Check whether an index is within the given range.-{-# INLINE inRange #-} inRange :: Range sh -> sh -> Bool inRange (Range _ _ p) ix = p ix+{-# INLINE inRange #-} -- Repr ----------------------------------------------------------------------- -- | Read elements from a partitioned array. instance (Repr r1 e, Repr r2 e) => Repr (P r1 r2) e where- {-# INLINE index #-} index (APart _ range arr1 arr2) ix | inRange range ix = index arr1 ix | otherwise = index arr2 ix+ {-# INLINE index #-} - {-# INLINE linearIndex #-} linearIndex arr@(APart sh _ _ _) ix = index arr $ fromIndex sh ix+ {-# INLINE linearIndex #-} - {-# INLINE extent #-} extent (APart sh _ _ _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (APart sh range arr1 arr2) y = sh `deepSeq` range `deepSeqRange` arr1 `deepSeqArray` arr2 `deepSeqArray` y+ {-# INLINE deepSeqArray #-} -{-# INLINE deepSeqRange #-} deepSeqRange :: Shape sh => Range sh -> b -> b deepSeqRange (Range low high f) y = low `deepSeq` high `deepSeq` f `seq` y+{-# INLINE deepSeqRange #-} -- Fill ----------------------------------------------------------------------- instance ( FillRange r1 r3 sh e, Fill r2 r3 sh e , Fillable r3 e) => Fill (P r1 r2) r3 sh e where- {-# INLINE fillP #-} fillP (APart _ (Range ix10 ix11 _) arr1 arr2) marr = do fillRangeP arr1 marr ix10 ix11 fillP arr2 marr+ {-# INLINE fillP #-} - {-# INLINE fillS #-} fillS (APart _ (Range ix10 ix11 _) arr1 arr2) marr = do fillRangeS arr1 marr ix10 ix11 fillS arr2 marr+ {-# INLINE fillS #-}
Data/Array/Repa/Repr/Unboxed.hs view
@@ -19,10 +19,11 @@ -- | Unboxed arrays are represented as unboxed vectors. ----- The implementation of `Data.Vector.Unboxed` is based on type families and--- picks an efficient, specialised representation for every element type. In--- particular, unboxed vectors of pairs are represented as pairs of unboxed--- vectors. This is the most efficient representation for numerical data.+-- The implementation uses @Data.Vector.Unboxed@ which is based on type+-- families and picks an efficient, specialised representation for every+-- element type. In particular, unboxed vectors of pairs are represented+-- as pairs of unboxed vectors.+-- This is the most efficient representation for numerical data. -- data U data instance U.Unbox e => Array U sh e@@ -34,21 +35,21 @@ -- Repr ----------------------------------------------------------------------- -- | Read elements from an unboxed vector array. instance U.Unbox a => Repr U a where- {-# INLINE linearIndex #-} linearIndex (AUnboxed _ vec) ix = vec U.! ix+ {-# INLINE linearIndex #-} - {-# INLINE unsafeLinearIndex #-} unsafeLinearIndex (AUnboxed _ vec) ix = vec `U.unsafeIndex` ix+ {-# INLINE unsafeLinearIndex #-} - {-# INLINE extent #-} extent (AUnboxed sh _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (AUnboxed sh vec) x = sh `deepSeq` vec `seq` x+ {-# INLINE deepSeqArray #-} -- Fill -----------------------------------------------------------------------@@ -57,20 +58,24 @@ data MArr U e = UMArr (UM.IOVector e) - {-# INLINE newMArr #-} newMArr n = liftM UMArr (UM.new n)+ {-# INLINE newMArr #-} - {-# INLINE unsafeWriteMArr #-} unsafeWriteMArr (UMArr v) ix = UM.unsafeWrite v ix+ {-# INLINE unsafeWriteMArr #-} - {-# INLINE unsafeFreezeMArr #-} unsafeFreezeMArr sh (UMArr mvec) = do vec <- U.unsafeFreeze mvec return $ AUnboxed sh vec+ {-# INLINE unsafeFreezeMArr #-} + deepSeqMArr (UMArr vec) x+ = vec `seq` x+ {-# INLINE deepSeqMArr #-} + -- Conversions ---------------------------------------------------------------- -- | Sequential computation of array elements.. --@@ -79,8 +84,8 @@ computeUnboxedS :: Fill r1 U sh e => Array r1 sh e -> Array U sh e-{-# INLINE computeUnboxedS #-} computeUnboxedS = computeS+{-# INLINE computeUnboxedS #-} -- | Parallel computation of array elements.@@ -88,10 +93,10 @@ -- * This is an alias for `computeP` with a more specific type. -- computeUnboxedP- :: Fill r1 U sh e- => Array r1 sh e -> Array U sh e-{-# INLINE computeUnboxedP #-}+ :: (Fill r1 U sh e, Monad m, U.Unbox e)+ => Array r1 sh e -> m (Array U sh e) computeUnboxedP = computeP+{-# INLINE computeUnboxedP #-} -- | O(n). Convert a list to an unboxed vector array.@@ -101,37 +106,38 @@ fromListUnboxed :: (Shape sh, U.Unbox a) => sh -> [a] -> Array U sh a-{-# INLINE fromListUnboxed #-} fromListUnboxed = R.fromList+{-# INLINE fromListUnboxed #-} -- | O(1). Wrap an unboxed vector as an array. fromUnboxed :: (Shape sh, U.Unbox e) => sh -> U.Vector e -> Array U sh e-{-# INLINE fromUnboxed #-} fromUnboxed sh vec = AUnboxed sh vec+{-# INLINE fromUnboxed #-} -- | O(1). Unpack an unboxed vector from an array. toUnboxed :: U.Unbox e => Array U sh e -> U.Vector e-{-# INLINE toUnboxed #-} toUnboxed (AUnboxed _ vec) = vec+{-# INLINE toUnboxed #-} + -- Zip ------------------------------------------------------------------------ -- | O(1). Zip some unboxed arrays. -- The shapes must be identical else `error`. zip :: (Shape sh, U.Unbox a, U.Unbox b) => Array U sh a -> Array U sh b -> Array U sh (a, b)-{-# INLINE zip #-} zip (AUnboxed sh1 vec1) (AUnboxed sh2 vec2) | sh1 /= sh2 = error "Repa: zip array shapes not identical" | otherwise = AUnboxed sh1 (U.zip vec1 vec2)+{-# INLINE zip #-} -- | O(1). Zip some unboxed arrays.@@ -139,11 +145,11 @@ zip3 :: (Shape sh, U.Unbox a, U.Unbox b, U.Unbox c) => Array U sh a -> Array U sh b -> Array U sh c -> Array U sh (a, b, c)-{-# INLINE zip3 #-} zip3 (AUnboxed sh1 vec1) (AUnboxed sh2 vec2) (AUnboxed sh3 vec3) | sh1 /= sh2 || sh1 /= sh3 = error "Repa: zip array shapes not identical" | otherwise = AUnboxed sh1 (U.zip3 vec1 vec2 vec3)+{-# INLINE zip3 #-} -- | O(1). Zip some unboxed arrays.@@ -151,11 +157,11 @@ zip4 :: (Shape sh, U.Unbox a, U.Unbox b, U.Unbox c, U.Unbox d) => Array U sh a -> Array U sh b -> Array U sh c -> Array U sh d -> Array U sh (a, b, c, d)-{-# INLINE zip4 #-} zip4 (AUnboxed sh1 vec1) (AUnboxed sh2 vec2) (AUnboxed sh3 vec3) (AUnboxed sh4 vec4) | sh1 /= sh2 || sh1 /= sh3 || sh1 /= sh4 = error "Repa: zip array shapes not identical" | otherwise = AUnboxed sh1 (U.zip4 vec1 vec2 vec3 vec4)+{-# INLINE zip4 #-} -- | O(1). Zip some unboxed arrays.@@ -163,11 +169,11 @@ zip5 :: (Shape sh, U.Unbox a, U.Unbox b, U.Unbox c, U.Unbox d, U.Unbox e) => Array U sh a -> Array U sh b -> Array U sh c -> Array U sh d -> Array U sh e -> Array U sh (a, b, c, d, e)-{-# INLINE zip5 #-} zip5 (AUnboxed sh1 vec1) (AUnboxed sh2 vec2) (AUnboxed sh3 vec3) (AUnboxed sh4 vec4) (AUnboxed sh5 vec5) | sh1 /= sh2 || sh1 /= sh3 || sh1 /= sh4 || sh1 /= sh5 = error "Repa: zip array shapes not identical" | otherwise = AUnboxed sh1 (U.zip5 vec1 vec2 vec3 vec4 vec5)+{-# INLINE zip5 #-} -- | O(1). Zip some unboxed arrays.@@ -175,11 +181,11 @@ zip6 :: (Shape sh, U.Unbox a, U.Unbox b, U.Unbox c, U.Unbox d, U.Unbox e, U.Unbox f) => Array U sh a -> Array U sh b -> Array U sh c -> Array U sh d -> Array U sh e -> Array U sh f -> Array U sh (a, b, c, d, e, f)-{-# INLINE zip6 #-} zip6 (AUnboxed sh1 vec1) (AUnboxed sh2 vec2) (AUnboxed sh3 vec3) (AUnboxed sh4 vec4) (AUnboxed sh5 vec5) (AUnboxed sh6 vec6) | sh1 /= sh2 || sh1 /= sh3 || sh1 /= sh4 || sh1 /= sh5 || sh1 /= sh6 = error "Repa: zip array shapes not identical" | otherwise = AUnboxed sh1 (U.zip6 vec1 vec2 vec3 vec4 vec5 vec6)+{-# INLINE zip6 #-} -- Unzip ----------------------------------------------------------------------@@ -187,47 +193,47 @@ unzip :: (U.Unbox a, U.Unbox b) => Array U sh (a, b) -> (Array U sh a, Array U sh b)-{-# INLINE unzip #-} unzip (AUnboxed sh vec) = let (as, bs) = U.unzip vec in (AUnboxed sh as, AUnboxed sh bs)+{-# INLINE unzip #-} -- | O(1). Unzip an unboxed array. unzip3 :: (U.Unbox a, U.Unbox b, U.Unbox c) => Array U sh (a, b, c) -> (Array U sh a, Array U sh b, Array U sh c)-{-# INLINE unzip3 #-} unzip3 (AUnboxed sh vec) = let (as, bs, cs) = U.unzip3 vec in (AUnboxed sh as, AUnboxed sh bs, AUnboxed sh cs)+{-# INLINE unzip3 #-} -- | O(1). Unzip an unboxed array. unzip4 :: (U.Unbox a, U.Unbox b, U.Unbox c, U.Unbox d) => Array U sh (a, b, c, d) -> (Array U sh a, Array U sh b, Array U sh c, Array U sh d)-{-# INLINE unzip4 #-} unzip4 (AUnboxed sh vec) = let (as, bs, cs, ds) = U.unzip4 vec in (AUnboxed sh as, AUnboxed sh bs, AUnboxed sh cs, AUnboxed sh ds)+{-# INLINE unzip4 #-} -- | O(1). Unzip an unboxed array. unzip5 :: (U.Unbox a, U.Unbox b, U.Unbox c, U.Unbox d, U.Unbox e) => Array U sh (a, b, c, d, e) -> (Array U sh a, Array U sh b, Array U sh c, Array U sh d, Array U sh e)-{-# INLINE unzip5 #-} unzip5 (AUnboxed sh vec) = let (as, bs, cs, ds, es) = U.unzip5 vec in (AUnboxed sh as, AUnboxed sh bs, AUnboxed sh cs, AUnboxed sh ds, AUnboxed sh es)+{-# INLINE unzip5 #-} -- | O(1). Unzip an unboxed array. unzip6 :: (U.Unbox a, U.Unbox b, U.Unbox c, U.Unbox d, U.Unbox e, U.Unbox f) => Array U sh (a, b, c, d, e, f) -> (Array U sh a, Array U sh b, Array U sh c, Array U sh d, Array U sh e, Array U sh f)-{-# INLINE unzip6 #-} unzip6 (AUnboxed sh vec) = let (as, bs, cs, ds, es, fs) = U.unzip6 vec in (AUnboxed sh as, AUnboxed sh bs, AUnboxed sh cs, AUnboxed sh ds, AUnboxed sh es, AUnboxed sh fs)+{-# INLINE unzip6 #-}
Data/Array/Repa/Repr/Undefined.hs view
@@ -19,19 +19,19 @@ -- | Undefined array elements. Inspecting them yields `error`. -- instance Repr X e where- {-# INLINE deepSeqArray #-} deepSeqArray _ x = x+ {-# INLINE deepSeqArray #-} - {-# INLINE extent #-} extent (AUndefined sh) = sh+ {-# INLINE extent #-} - {-# INLINE index #-} index (AUndefined _) _ = error "Repa: array element is undefined."+ {-# INLINE index #-} - {-# INLINE linearIndex #-} linearIndex (AUndefined _) _ = error "Repa: array element is undefined."+ {-# INLINE linearIndex #-} instance (Shape sh, Fillable r2 e, Num e) => Fill X r2 sh e where
Data/Array/Repa/Repr/Vector.hs view
@@ -28,21 +28,21 @@ -- Repr ----------------------------------------------------------------------- -- | Read elements from a boxed vector array. instance Repr V a where- {-# INLINE linearIndex #-} linearIndex (AVector _ vec) ix = vec V.! ix+ {-# INLINE linearIndex #-} - {-# INLINE unsafeLinearIndex #-} unsafeLinearIndex (AVector _ vec) ix = vec `V.unsafeIndex` ix+ {-# INLINE unsafeLinearIndex #-} - {-# INLINE extent #-} extent (AVector sh _) = sh+ {-# INLINE extent #-} - {-# INLINE deepSeqArray #-} deepSeqArray (AVector sh vec) x = sh `deepSeq` vec `seq` x+ {-# INLINE deepSeqArray #-} -- Fill -----------------------------------------------------------------------@@ -51,19 +51,22 @@ data MArr V e = MVec (VM.IOVector e) - {-# INLINE newMArr #-} newMArr n = liftM MVec (VM.new n)+ {-# INLINE newMArr #-} - {-# INLINE unsafeWriteMArr #-} unsafeWriteMArr (MVec v) ix = VM.unsafeWrite v ix+ {-# INLINE unsafeWriteMArr #-} - {-# INLINE unsafeFreezeMArr #-} unsafeFreezeMArr sh (MVec mvec) = do vec <- V.unsafeFreeze mvec return $ AVector sh vec+ {-# INLINE unsafeFreezeMArr #-} + deepSeqMArr !_vec x+ = x+ {-# INLINE deepSeqMArr #-} -- Conversions ---------------------------------------------------------------- -- | Sequential computation of array elements.@@ -73,16 +76,16 @@ computeVectorS :: Fill r1 V sh e => Array r1 sh e -> Array V sh e-{-# INLINE computeVectorS #-} computeVectorS = computeS+{-# INLINE computeVectorS #-} -- | Parallel computation of array elements. computeVectorP- :: Fill r1 V sh e- => Array r1 sh e -> Array V sh e-{-# INLINE computeVectorP #-}+ :: (Fill r1 V sh e, Monad m)+ => Array r1 sh e -> m (Array V sh e) computeVectorP = computeP+{-# INLINE computeVectorP #-} -- | O(n). Convert a list to a boxed vector array.@@ -90,23 +93,23 @@ -- * This is an alias for `fromList` with a more specific type. -- fromListVector :: Shape sh => sh -> [a] -> Array V sh a-{-# INLINE fromListVector #-} fromListVector = fromList+{-# INLINE fromListVector #-} -- | O(1). Wrap a boxed vector as an array. fromVector :: Shape sh => sh -> V.Vector e -> Array V sh e-{-# INLINE fromVector #-} fromVector sh vec = AVector sh vec+{-# INLINE fromVector #-} -- | O(1). Unpack a boxed vector from an array. toVector :: Array V sh e -> V.Vector e-{-# INLINE toVector #-} toVector (AVector _ vec) = vec+{-# INLINE toVector #-}
Data/Array/Repa/Specialised/Dim2.hs view
@@ -8,6 +8,7 @@ , makeBordered2) where import Data.Array.Repa.Index+import Data.Array.Repa.Base import Data.Array.Repa.Repr.Partitioned import Data.Array.Repa.Repr.Undefined @@ -70,10 +71,9 @@ -- The two arrays must have the same extent. -- The border must be the same width on all sides. ----- TODO: Check arrays have same extent.--- makeBordered2- :: DIM2 -- ^ Extent of array.+ :: (Repr r1 a, Repr r2 a)+ => DIM2 -- ^ Extent of array. -> Int -- ^ Width of border. -> Array r1 DIM2 a -- ^ Array for internal elements. -> Array r2 DIM2 a -- ^ Array for border elements.@@ -81,21 +81,21 @@ {-# INLINE makeBordered2 #-} makeBordered2 sh@(_ :. aHeight :. aWidth) borderWidth arrInternal arrBorder- = let+ = checkDims `seq` + let -- minimum and maximum indicies of values in the inner part of the image. !xMin = borderWidth !yMin = borderWidth !xMax = aWidth - borderWidth - 1 !yMax = aHeight - borderWidth - 1 -- {-# INLINE inInternal #-} inInternal (Z :. y :. x) = x >= xMin && x <= xMax && y >= yMin && y <= yMax+ {-# INLINE inInternal #-} - {-# INLINE inBorder #-} inBorder = not . inInternal+ {-# INLINE inBorder #-} in -- internal region@@ -107,3 +107,11 @@ $ APart sh (Range (Z :. yMin :. 0) (Z :. yMax :. xMin - 1) inBorder) arrBorder $ APart sh (Range (Z :. yMin :. xMax + 1) (Z :. yMax :. aWidth - 1) inBorder) arrBorder $ AUndefined sh++ where+ checkDims+ = if (extent arrInternal) == (extent arrBorder)+ then ()+ else error "makeBordered2: internal and border arrays have different extents"+ {-# NOINLINE checkDims #-}+ -- NOINLINE because we don't want the branch in the core code.
Data/Array/Repa/Stencil/Dim2.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE MagicHash #-} -- This is specialised for stencils up to 7x7. -- Due to limitations in the GHC optimiser, using larger stencils doesn't -- work, and will yield `error` at runtime. We can probably increase the@@ -23,6 +24,7 @@ import Data.Array.Repa.Repr.Undefined import Data.Array.Repa.Stencil.Base import Data.Array.Repa.Stencil.Template+import GHC.Exts -- | A index into the flat array. -- Should be abstract outside the stencil modules.@@ -167,34 +169,34 @@ (StencilStatic sExtent zero loads) arr cur - | _ :. sHeight :. sWidth <- sExtent- , _ :. aHeight :. aWidth <- extent arr+ | _ :. sHeight :. sWidth <- sExtent+ , _ :. (I# aHeight) :. (I# aWidth) <- extent arr , sHeight <= 7, sWidth <= 7 = let -- Get data from the manifest array. {-# INLINE getData #-} getData :: DIM2 -> a- getData (Z :. y :. x)+ getData (Z :. (I# y) :. (I# x)) = wrapLoadX x y - -- TODO: Inlining this into above makes SpecConstr choke- wrapLoadX :: Int -> Int -> a+ {-# NOINLINE wrapLoadX #-}+ wrapLoadX :: Int# -> Int# -> a wrapLoadX !x !y- | x < 0 = wrapLoadY 0 y- | x >= aWidth = wrapLoadY (aWidth - 1) y+ | x <# 0# = wrapLoadY 0# y+ | x >=# aWidth = wrapLoadY (aWidth -# 1#) y | otherwise = wrapLoadY x y - {-# INLINE wrapLoadY #-}- wrapLoadY :: Int -> Int -> a+ {-# NOINLINE wrapLoadY #-}+ wrapLoadY :: Int# -> Int# -> a wrapLoadY !x !y- | y < 0 = loadXY x 0- | y >= aHeight = loadXY x (aHeight - 1)- | otherwise = loadXY x y+ | y <# 0# = loadXY x 0#+ | y >=# aHeight = loadXY x (aHeight -# 1#)+ | otherwise = loadXY x y {-# INLINE loadXY #-}- loadXY :: Int -> Int -> a+ loadXY :: Int# -> Int# -> a loadXY !x !y- = arr `unsafeIndex` (Z :. y :. x)+ = arr `unsafeIndex` (Z :. (I# y) :. (I# x)) -- Build a function to pass data from the array to our stencil. {-# INLINE oload #-}
+ Data/Array/Repa/Unsafe.hs view
@@ -0,0 +1,14 @@++-- | Functions without sanity or bounds checks.+module Data.Array.Repa.Unsafe+ ( unsafeBackpermute+ , unsafeBackpermuteDft+ , unsafeSlice+ , unsafeExtend+ , unsafeTraverse+ , unsafeTraverse2+ , unsafeTraverse3+ , unsafeTraverse4)+where+import Data.Array.Repa.Operators.IndexSpace+import Data.Array.Repa.Operators.Traversal
repa.cabal view
@@ -1,5 +1,5 @@ Name: repa-Version: 3.0.0.1+Version: 3.1.0.1 License: BSD3 License-file: LICENSE Author: The DPH Team@@ -72,6 +72,7 @@ Data.Array.Repa.Shape Data.Array.Repa.Slice Data.Array.Repa.Stencil+ Data.Array.Repa.Unsafe Data.Array.Repa Other-modules: