module Data.Array.Repa.Stencil.Dim2
(
makeStencil2, stencil2
, PC5, mapStencil2, forStencil2)
where
import Data.Array.Repa.Base
import Data.Array.Repa.Index
import Data.Array.Repa.Shape
import Data.Array.Repa.Repr.Delayed
import Data.Array.Repa.Repr.Cursored
import Data.Array.Repa.Repr.Partitioned
import Data.Array.Repa.Repr.HintSmall
import Data.Array.Repa.Repr.Undefined
import Data.Array.Repa.Stencil.Base
import Data.Array.Repa.Stencil.Template
import Data.Array.Repa.Stencil.Partition
import GHC.Exts
data Cursor
= Cursor Int
type PC5 = P C (P (S D) (P (S D) (P (S D) (P (S D) X))))
forStencil2
:: Source r a
=> Boundary a
-> Array r DIM2 a
-> Stencil DIM2 a
-> Array PC5 DIM2 a
forStencil2 boundary arr stencil
= mapStencil2 boundary stencil arr
mapStencil2
:: Source r a
=> Boundary a
-> Stencil DIM2 a
-> Array r DIM2 a
-> Array PC5 DIM2 a
mapStencil2 boundary stencil@(StencilStatic sExtent _zero _load) arr
= let sh = extent arr
(_ :. aHeight :. aWidth) = sh
(_ :. sHeight :. sWidth) = sExtent
sHeight2 = sHeight `div` 2
sWidth2 = sWidth `div` 2
![ Region inX inY inW inH
, Region westX westY westW westH
, Region eastX eastY eastW eastH
, Region northX northY northW northH
, Region southX southY southW southH ]
= partitionForStencil
(Size aWidth aHeight)
(Size sWidth sHeight)
(Offset sWidth2 sHeight2)
inInternal (Z :. y :. x)
= x >= inX && x < (inX + inW)
&& y >= inY && y < (inY + inH)
inBorder = not . inInternal
makec (Z :. y :. x)
= Cursor (x + y * aWidth)
shiftc ix (Cursor off)
= Cursor
$ case ix of
Z :. y :. x -> off + y * aWidth + x
arrInternal = makeCursored (extent arr) makec shiftc getInner'
getInner' cur = unsafeAppStencilCursor2 shiftc stencil arr cur
arrBorder = ASmall (fromFunction (extent arr) getBorder')
getBorder' ix
= case boundary of
BoundFixed c -> c
BoundConst c -> unsafeAppStencilCursor2_const addDim stencil c arr ix
BoundClamp -> unsafeAppStencilCursor2_clamp addDim stencil arr ix
in
APart sh (Range (Z :. inY :. inX) (Z :. inH :. inW) inInternal) arrInternal
$ APart sh (Range (Z :. westY :. westX) (Z :. westH :. westW) inBorder) arrBorder
$ APart sh (Range (Z :. eastY :. eastX) (Z :. eastH :. eastW) inBorder) arrBorder
$ APart sh (Range (Z :. northY :. northX) (Z :. northH :. northW) inBorder) arrBorder
$ APart sh (Range (Z :. southY :. southX) (Z :. southH :. southW) inBorder) arrBorder
$ AUndefined sh
unsafeAppStencilCursor2
:: Source r a
=> (DIM2 -> Cursor -> Cursor)
-> Stencil DIM2 a
-> Array r DIM2 a
-> Cursor
-> a
unsafeAppStencilCursor2 shift
(StencilStatic sExtent zero loads)
arr cur0
| _ :. sHeight :. sWidth <- sExtent
, sHeight <= 7, sWidth <= 7
= let
getData (Cursor cur) = arr `unsafeLinearIndex` cur
oload oy ox
= let !cur' = shift (Z :. oy :. ox) cur0
in loads (Z :. oy :. ox) (getData cur')
in template7x7 oload zero
| otherwise
= error $ unlines
[ "mapStencil2: Your stencil is too big for this method."
, " It must fit within a 7x7 tile to be compiled statically." ]
unsafeAppStencilCursor2_const
:: forall r a
. Source r a
=> (DIM2 -> DIM2 -> DIM2)
-> Stencil DIM2 a
-> a
-> Array r DIM2 a
-> DIM2
-> a
unsafeAppStencilCursor2_const shift
(StencilStatic sExtent zero loads)
fixed arr cur
| _ :. sHeight :. sWidth <- sExtent
, _ :. (I# aHeight) :. (I# aWidth) <- extent arr
, sHeight <= 7, sWidth <= 7
= let
getData :: DIM2 -> a
getData (Z :. (I# y) :. (I# x))
= getData' x y
getData' :: Int# -> Int# -> a
getData' !x !y
| 1# <- (x <# 0#) `orI#` (x >=# aWidth)
`orI#` (y <# 0#) `orI#` (y >=# aHeight)
= fixed
| otherwise
= arr `unsafeIndex` (Z :. (I# y) :. (I# x))
oload oy ox
= let !cur' = shift (Z :. oy :. ox) cur
in loads (Z :. oy :. ox) (getData cur')
in template7x7 oload zero
| otherwise
= error $ unlines
[ "mapStencil2: Your stencil is too big for this method."
, " It must fit within a 7x7 tile to be compiled statically." ]
unsafeAppStencilCursor2_clamp
:: forall r a
. Source r a
=> (DIM2 -> DIM2 -> DIM2)
-> Stencil DIM2 a
-> Array r DIM2 a
-> DIM2
-> a
unsafeAppStencilCursor2_clamp shift
(StencilStatic sExtent zero loads)
arr cur
| _ :. sHeight :. sWidth <- sExtent
, _ :. (I# aHeight) :. (I# aWidth) <- extent arr
, sHeight <= 7, sWidth <= 7
= let
getData :: DIM2 -> a
getData (Z :. (I# y) :. (I# x))
= wrapLoadX x y
wrapLoadX :: Int# -> Int# -> a
wrapLoadX !x !y
| 1# <- x <# 0# = wrapLoadY 0# y
| 1# <- x >=# aWidth = wrapLoadY (aWidth -# 1#) y
| otherwise = wrapLoadY x y
wrapLoadY :: Int# -> Int# -> a
wrapLoadY !x !y
| 1# <- y <# 0# = loadXY x 0#
| 1# <- y >=# aHeight = loadXY x (aHeight -# 1#)
| otherwise = loadXY x y
loadXY :: Int# -> Int# -> a
loadXY !x !y
= arr `unsafeIndex` (Z :. (I# y) :. (I# x))
oload oy ox
= let !cur' = shift (Z :. oy :. ox) cur
in loads (Z :. oy :. ox) (getData cur')
in template7x7 oload zero
| otherwise
= error $ unlines
[ "mapStencil2: Your stencil is too big for this method."
, " It must fit within a 7x7 tile to be compiled statically." ]
template7x7
:: (Int -> Int -> a -> a)
-> a -> a
template7x7 f zero
= f (3) (3) $ f (3) (2) $ f (3) (1) $ f (3) 0 $ f (3) 1 $ f (3) 2 $ f (3) 3
$ f (2) (3) $ f (2) (2) $ f (2) (1) $ f (2) 0 $ f (2) 1 $ f (2) 2 $ f (2) 3
$ f (1) (3) $ f (1) (2) $ f (1) (1) $ f (1) 0 $ f (1) 1 $ f (1) 2 $ f (1) 3
$ f 0 (3) $ f 0 (2) $ f 0 (1) $ f 0 0 $ f 0 1 $ f 0 2 $ f 0 3
$ f 1 (3) $ f 1 (2) $ f 1 (1) $ f 1 0 $ f 1 1 $ f 1 2 $ f 1 3
$ f 2 (3) $ f 2 (2) $ f 2 (1) $ f 2 0 $ f 2 1 $ f 2 2 $ f 2 3
$ f 3 (3) $ f 3 (2) $ f 3 (1) $ f 3 0 $ f 3 1 $ f 3 2 $ f 3 3
$ zero