    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 w :: Int
    w h :: Int
    h)
            = Int -> Int -> Int -> Int -> Region
    Region 0 0 Int
    w Int
    h
    {-# INLINE regionOfSize #-}

    -- | Offset a region.
    offsetRegion :: Offset -> Region -> Region
    offsetRegion :: Offset -> Region -> Region
    offsetRegion (Offset x :: Int
    x y :: Int
    y) (Region x0 :: Int
    x0 y0 :: Int
    y0 w :: Int
    w h :: 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   arrW :: Int
    arrW arrH :: Int
    arrH)
              (Size   krnW :: Int
    krnW krnH :: Int
    krnH)
              (Offset focX :: Int
    focX focY :: 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
    - 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
    - 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  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  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 #-}