module Data.Array.Repa.Stencil.Partition
        ( Offset (..)
        , Size   (..)
        , Region (..)
        , partitionForStencil)
where

-- | An offset in the 2d plane.
data Offset
        = Offset !Int !Int

-- | Size of a region in the 2d plane.
data Size
        = Size   !Int !Int

-- | A region in the 2d plane.
data Region 
        = Region
        { Region -> Int
regionX       :: !Int
        , Region -> Int
regionY       :: !Int
        , Region -> Int
regionWidth   :: !Int
        , Region -> Int
regionHeight  :: !Int }
        deriving Int -> Region -> ShowS
[Region] -> ShowS
Region -> String
(Int -> Region -> ShowS)
-> (Region -> String) -> ([Region] -> ShowS) -> Show Region
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Region] -> ShowS
$cshowList :: [Region] -> ShowS
show :: Region -> String
$cshow :: Region -> String
showsPrec :: Int -> Region -> ShowS
$cshowsPrec :: Int -> Region -> ShowS
Show


-- | Create a new region of the given size.
regionOfSize :: Size -> Region
regionOfSize :: Size -> Region
regionOfSize (Size Int
w Int
h)
        = Int -> Int -> Int -> Int -> Region
Region Int
0 Int
0 Int
w Int
h
{-# INLINE regionOfSize #-}

-- | Offset a region.
offsetRegion :: Offset -> Region -> Region
offsetRegion :: Offset -> Region -> Region
offsetRegion (Offset Int
x Int
y) (Region Int
x0 Int
y0 Int
w Int
h)
        = Int -> Int -> Int -> Int -> Region
Region (Int
x0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
x) (Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
y) Int
w Int
h
{-# INLINE offsetRegion #-}

-- | Partition a region into inner and border regions for the given stencil.
partitionForStencil
        :: Size         -- ^ Size of array
        -> Size         -- ^ Size of stencil
        -> Offset       -- ^ Focus of stencil
        -> [Region]

partitionForStencil :: Size -> Size -> Offset -> [Region]
partitionForStencil
          (Size   Int
arrW Int
arrH)
          (Size   Int
krnW Int
krnH)
          (Offset Int
focX Int
focY)
 = let  
        gapNorth :: Int
gapNorth        = Int
focY
        gapSouth :: Int
gapSouth        = Int
krnH Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
focY Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
        gapWest :: Int
gapWest         = Int
focX
        gapEast :: Int
gapEast         = Int
krnW Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
focX Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1

        innerW :: Int
innerW          = Int
arrW Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
gapWest  Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
gapEast
        innerH :: Int
innerH          = Int
arrH Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
gapNorth Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
gapSouth

        regionInner :: Region
regionInner     = Offset -> Region -> Region
offsetRegion (Int -> Int -> Offset
Offset  Int
gapWest           Int
gapNorth)
                        (Region -> Region) -> Region -> Region
forall a b. (a -> b) -> a -> b
$ Size -> Region
regionOfSize (Int -> Int -> Size
Size    Int
innerW            Int
innerH)

        regionNorth :: Region
regionNorth     = Size -> Region
regionOfSize (Int -> Int -> Size
Size    Int
arrW              Int
gapNorth)

        regionSouth :: Region
regionSouth     = Offset -> Region -> Region
offsetRegion (Int -> Int -> Offset
Offset  Int
0                 (Int
gapNorth Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
innerH))
                        (Region -> Region) -> Region -> Region
forall a b. (a -> b) -> a -> b
$ Size -> Region
regionOfSize (Int -> Int -> Size
Size    Int
arrW              Int
gapSouth)

        regionWest :: Region
regionWest      = Offset -> Region -> Region
offsetRegion (Int -> Int -> Offset
Offset  Int
0                 Int
gapNorth)
                        (Region -> Region) -> Region -> Region
forall a b. (a -> b) -> a -> b
$ Size -> Region
regionOfSize (Int -> Int -> Size
Size    Int
gapWest           Int
innerH)

        regionEast :: Region
regionEast      = Offset -> Region -> Region
offsetRegion (Int -> Int -> Offset
Offset (Int
gapWest Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
innerW) Int
gapNorth)
                        (Region -> Region) -> Region -> Region
forall a b. (a -> b) -> a -> b
$ Size -> Region
regionOfSize (Int -> Int -> Size
Size    Int
gapEast           Int
innerH)

  in    [Region
regionInner, Region
regionNorth, Region
regionSouth, Region
regionWest, Region
regionEast]
{-# INLINE partitionForStencil #-}