    {-# 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
    --   limit if required -- just ask.
    --
    --   The focus of the stencil is in the center of the 7x7 tile, which has
    --   coordinates (0, 0). All coefficients in the stencil must fit in the tile,
    --   so they can be given X,Y coordinates up to +/- 3 positions.
    --   The stencil can be any shape, and need not be symmetric -- provided it
    --   fits in the 7x7 tile.
    --
    module Data.Array.Repa.Stencil.Dim2
            ( -- * Stencil creation
              makeStencil2, stencil2

              -- * Stencil operators
            , 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

    -- | A index into the flat array.
    --   Should be abstract outside the stencil modules.
    data Cursor
            = Cursor Int

    type PC5 = P C (P (S D) (P (S D) (P (S D) (P (S D) X))))

    -- Wrappers -------------------------------------------------------------------
    -- | Like `mapStencil2` but with the parameters flipped.
    forStencil2
            :: Source r a
            => Boundary a
            -> Array  r DIM2 a
            -> Stencil  DIM2 a
            -> Array PC5 DIM2 a

    {-# INLINE forStencil2 #-}
    forStencil2 :: Boundary a -> Array r DIM2 a -> Stencil DIM2 a -> Array PC5 DIM2 a
    forStencil2 boundary :: Boundary a
    boundary arr :: Array r DIM2 a
    arr stencil :: Stencil DIM2 a
    stencil
            = Boundary a -> Stencil DIM2 a -> Array r DIM2 a -> Array PC5 DIM2 a
    forall r a.
    Source r a =>
    Boundary a -> Stencil DIM2 a -> Array r DIM2 a -> Array PC5 DIM2 a
    mapStencil2 Boundary a
    boundary Stencil DIM2 a
    stencil Array r DIM2 a
    arr

    -------------------------------------------------------------------------------
    -- | Apply a stencil to every element of a 2D array.
    mapStencil2
            :: Source r a
            => Boundary a           -- ^ How to handle the boundary of the array.
            -> Stencil DIM2 a       -- ^ Stencil to apply.
            -> Array r DIM2 a               -- ^ Array to apply stencil to.
            -> Array PC5 DIM2 a

    {-# INLINE mapStencil2 #-}
    mapStencil2 :: Boundary a -> Stencil DIM2 a -> Array r DIM2 a -> Array PC5 DIM2 a
    mapStencil2 boundary :: Boundary a
    boundary stencil :: Stencil DIM2 a
    stencil@(StencilStatic sExtent :: DIM2
    sExtent _zero :: a
    _zero _load :: DIM2 -> a -> a -> a
    _load) arr :: Array r DIM2 a
    arr
     = let  sh :: DIM2
    sh                       = Array r DIM2 a -> DIM2
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
    extent Array r DIM2 a
    arr
            (_ :. aHeight :: Int
    aHeight :. aWidth :: Int
    aWidth) = DIM2
    sh
            (_ :. sHeight :: Int
    sHeight :. sWidth :: Int
    sWidth) = DIM2
    sExtent

            sHeight2 :: Int
    sHeight2        = Int
    sHeight Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` 2
            sWidth2 :: Int
    sWidth2         = Int
    sWidth  Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` 2

            -- Partition the array into the internal and border regions.
            ![ Region    inX :: Int
    inX    inY :: Int
    inY    inW :: Int
    inW    inH :: Int
    inH
             , Region  westX :: Int
    westX  westY :: Int
    westY  westW :: Int
    westW  westH :: Int
    westH
             , Region  eastX :: Int
    eastX  eastY :: Int
    eastY  eastW :: Int
    eastW  eastH :: Int
    eastH
             , Region northX :: Int
    northX northY :: Int
    northY northW :: Int
    northW northH :: Int
    northH
             , Region southX :: Int
    southX southY :: Int
    southY southW :: Int
    southW southH :: Int
    southH ]
               = Size -> Size -> Offset -> [Region]
    partitionForStencil
                    (Int -> Int -> Size
    Size   Int
    aWidth   Int
    aHeight)
                    (Int -> Int -> Size
    Size   Int
    sWidth   Int
    sHeight)
                    (Int -> Int -> Offset
    Offset Int
    sWidth2  Int
    sHeight2)

            {-# INLINE inInternal #-}
            inInternal :: DIM2 -> Bool
    inInternal (Z :. y :: Int
    y :. x :: Int
    x)
                    =  Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    inX Bool -> Bool -> Bool
    && Int
    x Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < (Int
    inX Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    inW)
                    Bool -> Bool -> Bool
    && Int
    y Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    inY Bool -> Bool -> Bool
    && Int
    y Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < (Int
    inY Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    inH)

            {-# INLINE inBorder #-}
            inBorder :: DIM2 -> Bool
    inBorder       = Bool -> Bool
    not (Bool -> Bool) -> (DIM2 -> Bool) -> DIM2 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DIM2 -> Bool
    inInternal

            -- Cursor functions ----------------
            {-# INLINE makec #-}
            makec :: DIM2 -> Cursor
    makec (Z :. y :: Int
    y :. x :: Int
    x)
             = Int -> Cursor
    Cursor (Int
    x Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    y Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    aWidth)

            {-# INLINE shiftc #-}
            shiftc :: DIM2 -> Cursor -> Cursor
    shiftc ix :: DIM2
    ix (Cursor off :: Int
    off)
             = Int -> Cursor
    Cursor
             (Int -> Cursor) -> Int -> Cursor
    forall a b. (a -> b) -> a -> b
    $ case DIM2
    ix of
                    Z :. y :: Int
    y :. x :: Int
    x     -> Int
    off Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    y Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    aWidth Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    x

            {-# INLINE arrInternal #-}
            arrInternal :: Array C DIM2 a
    arrInternal     = DIM2
    -> (DIM2 -> Cursor)
    -> (DIM2 -> Cursor -> Cursor)
    -> (Cursor -> a)
    -> Array C DIM2 a
    forall sh cursor e.
    sh
    -> (sh -> cursor)
    -> (sh -> cursor -> cursor)
    -> (cursor -> e)
    -> Array C sh e
    makeCursored (Array r DIM2 a -> DIM2
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
    extent Array r DIM2 a
    arr) DIM2 -> Cursor
    makec DIM2 -> Cursor -> Cursor
    shiftc Cursor -> a
    getInner'

            {-# INLINE getInner' #-}
            getInner' :: Cursor -> a
    getInner' cur :: Cursor
    cur   = (DIM2 -> Cursor -> Cursor)
    -> Stencil DIM2 a -> Array r DIM2 a -> Cursor -> a
    forall r a.
    Source r a =>
    (DIM2 -> Cursor -> Cursor)
    -> Stencil DIM2 a -> Array r DIM2 a -> Cursor -> a
    unsafeAppStencilCursor2 DIM2 -> Cursor -> Cursor
    shiftc Stencil DIM2 a
    stencil Array r DIM2 a
    arr Cursor
    cur

            {-# INLINE arrBorder #-}
            arrBorder :: Array (S D) DIM2 a
    arrBorder       = Array D DIM2 a -> Array (S D) DIM2 a
    forall r1 sh a. Array r1 sh a -> Array (S r1) sh a
    ASmall (DIM2 -> (DIM2 -> a) -> Array D DIM2 a
    forall sh a. sh -> (sh -> a) -> Array D sh a
    fromFunction (Array r DIM2 a -> DIM2
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
    extent Array r DIM2 a
    arr) DIM2 -> a
    getBorder')

            {-# INLINE getBorder' #-}
            getBorder' :: DIM2 -> a
    getBorder' ix :: DIM2
    ix
             = case Boundary a
    boundary of
                    BoundFixed c :: a
    c    -> a
    c
                    BoundConst c :: a
    c    -> (DIM2 -> DIM2 -> DIM2)
    -> Stencil DIM2 a -> a -> Array r DIM2 a -> DIM2 -> a
    forall r a.
    Source r a =>
    (DIM2 -> DIM2 -> DIM2)
    -> Stencil DIM2 a -> a -> Array r DIM2 a -> DIM2 -> a
    unsafeAppStencilCursor2_const DIM2 -> DIM2 -> DIM2
    forall sh. Shape sh => sh -> sh -> sh
    addDim Stencil DIM2 a
    stencil a
    c Array r DIM2 a
    arr DIM2
    ix
                    BoundClamp      -> (DIM2 -> DIM2 -> DIM2)
    -> Stencil DIM2 a -> Array r DIM2 a -> DIM2 -> a
    forall r a.
    Source r a =>
    (DIM2 -> DIM2 -> DIM2)
    -> Stencil DIM2 a -> Array r DIM2 a -> DIM2 -> a
    unsafeAppStencilCursor2_clamp DIM2 -> DIM2 -> DIM2
    forall sh. Shape sh => sh -> sh -> sh
    addDim Stencil DIM2 a
    stencil Array r DIM2 a
    arr DIM2
    ix
       in
        --  internal region
            DIM2
    -> Range DIM2
    -> Array C DIM2 a
    -> Array (P (S D) (P (S D) (P (S D) (P (S D) X)))) DIM2 a
    -> Array PC5 DIM2 a
    forall r1 r2 sh e.
    sh
    -> Range sh
    -> Array r1 sh e
    -> Array r2 sh e
    -> Array (P r1 r2) sh e
    APart DIM2
    sh (DIM2 -> DIM2 -> (DIM2 -> Bool) -> Range DIM2
    forall sh. sh -> sh -> (sh -> Bool) -> Range sh
    Range (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :.    Int
    inY (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.    Int
    inX) (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :.    Int
    inH (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.    Int
    inW) DIM2 -> Bool
    inInternal) Array C DIM2 a
    arrInternal

        --  border regions
        (Array (P (S D) (P (S D) (P (S D) (P (S D) X)))) DIM2 a
     -> Array PC5 DIM2 a)
    -> Array (P (S D) (P (S D) (P (S D) (P (S D) X)))) DIM2 a
    -> Array PC5 DIM2 a
    forall a b. (a -> b) -> a -> b
    $   DIM2
    -> Range DIM2
    -> Array (S D) DIM2 a
    -> Array (P (S D) (P (S D) (P (S D) X))) DIM2 a
    -> Array (P (S D) (P (S D) (P (S D) (P (S D) X)))) DIM2 a
    forall r1 r2 sh e.
    sh
    -> Range sh
    -> Array r1 sh e
    -> Array r2 sh e
    -> Array (P r1 r2) sh e
    APart DIM2
    sh (DIM2 -> DIM2 -> (DIM2 -> Bool) -> Range DIM2
    forall sh. sh -> sh -> (sh -> Bool) -> Range sh
    Range (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :.  Int
    westY (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.  Int
    westX) (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :.  Int
    westH (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.  Int
    westW) DIM2 -> Bool
    inBorder)   Array (S D) DIM2 a
    arrBorder
        (Array (P (S D) (P (S D) (P (S D) X))) DIM2 a
     -> Array (P (S D) (P (S D) (P (S D) (P (S D) X)))) DIM2 a)
    -> Array (P (S D) (P (S D) (P (S D) X))) DIM2 a
    -> Array (P (S D) (P (S D) (P (S D) (P (S D) X)))) DIM2 a
    forall a b. (a -> b) -> a -> b
    $   DIM2
    -> Range DIM2
    -> Array (S D) DIM2 a
    -> Array (P (S D) (P (S D) X)) DIM2 a
    -> Array (P (S D) (P (S D) (P (S D) X))) DIM2 a
    forall r1 r2 sh e.
    sh
    -> Range sh
    -> Array r1 sh e
    -> Array r2 sh e
    -> Array (P r1 r2) sh e
    APart DIM2
    sh (DIM2 -> DIM2 -> (DIM2 -> Bool) -> Range DIM2
    forall sh. sh -> sh -> (sh -> Bool) -> Range sh
    Range (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :.  Int
    eastY (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.  Int
    eastX) (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :.  Int
    eastH (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.  Int
    eastW) DIM2 -> Bool
    inBorder)   Array (S D) DIM2 a
    arrBorder
        (Array (P (S D) (P (S D) X)) DIM2 a
     -> Array (P (S D) (P (S D) (P (S D) X))) DIM2 a)
    -> Array (P (S D) (P (S D) X)) DIM2 a
    -> Array (P (S D) (P (S D) (P (S D) X))) DIM2 a
    forall a b. (a -> b) -> a -> b
    $   DIM2
    -> Range DIM2
    -> Array (S D) DIM2 a
    -> Array (P (S D) X) DIM2 a
    -> Array (P (S D) (P (S D) X)) DIM2 a
    forall r1 r2 sh e.
    sh
    -> Range sh
    -> Array r1 sh e
    -> Array r2 sh e
    -> Array (P r1 r2) sh e
    APart DIM2
    sh (DIM2 -> DIM2 -> (DIM2 -> Bool) -> Range DIM2
    forall sh. sh -> sh -> (sh -> Bool) -> Range sh
    Range (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    northY (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    northX) (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    northH (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    northW) DIM2 -> Bool
    inBorder)   Array (S D) DIM2 a
    arrBorder
        (Array (P (S D) X) DIM2 a -> Array (P (S D) (P (S D) X)) DIM2 a)
    -> Array (P (S D) X) DIM2 a -> Array (P (S D) (P (S D) X)) DIM2 a
    forall a b. (a -> b) -> a -> b
    $   DIM2
    -> Range DIM2
    -> Array (S D) DIM2 a
    -> Array X DIM2 a
    -> Array (P (S D) X) DIM2 a
    forall r1 r2 sh e.
    sh
    -> Range sh
    -> Array r1 sh e
    -> Array r2 sh e
    -> Array (P r1 r2) sh e
    APart DIM2
    sh (DIM2 -> DIM2 -> (DIM2 -> Bool) -> Range DIM2
    forall sh. sh -> sh -> (sh -> Bool) -> Range sh
    Range (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    southY (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    southX) (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    southH (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    southW) DIM2 -> Bool
    inBorder)   Array (S D) DIM2 a
    arrBorder
        (Array X DIM2 a -> Array (P (S D) X) DIM2 a)
    -> Array X DIM2 a -> Array (P (S D) X) DIM2 a
    forall a b. (a -> b) -> a -> b
    $   DIM2 -> Array X DIM2 a
    forall sh e. sh -> Array X sh e
    AUndefined DIM2
    sh

    unsafeAppStencilCursor2
            :: Source r a
            => (DIM2 -> Cursor -> Cursor)
            -> Stencil DIM2 a
            -> Array r DIM2 a
            -> Cursor
            -> a

    {-# INLINE unsafeAppStencilCursor2 #-}
    unsafeAppStencilCursor2 :: (DIM2 -> Cursor -> Cursor)
    -> Stencil DIM2 a -> Array r DIM2 a -> Cursor -> a
    unsafeAppStencilCursor2 shift :: DIM2 -> Cursor -> Cursor
    shift
            (StencilStatic sExtent :: DIM2
    sExtent zero :: a
    zero loads :: DIM2 -> a -> a -> a
    loads)
            arr :: Array r DIM2 a
    arr cur0 :: Cursor
    cur0

            | _ :. sHeight :: Int
    sHeight :. sWidth :: Int
    sWidth        <- DIM2
    sExtent
            , Int
    sHeight Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 7, Int
    sWidth Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 7
            = let
                    -- Get data from the manifest array.
                    {-# INLINE getData #-}
                    getData :: Cursor -> a
    getData (Cursor cur :: Int
    cur) = Array r DIM2 a
    arr Array r DIM2 a -> Int -> a
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> Int -> e
    `unsafeLinearIndex` Int
    cur

                    -- Build a function to pass data from the array to our stencil.
                    {-# INLINE oload #-}
                    oload :: Int -> Int -> a -> a
    oload oy :: Int
    oy ox :: Int
    ox
                     = let  !cur' :: Cursor
    cur' = DIM2 -> Cursor -> Cursor
    shift (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    oy (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    ox) Cursor
    cur0
                       in   DIM2 -> a -> a -> a
    loads (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    oy (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    ox) (Cursor -> a
    getData Cursor
    cur')

               in   (Int -> Int -> a -> a) -> a -> a
    forall a. (Int -> Int -> a -> a) -> a -> a
    template7x7 Int -> Int -> a -> a
    oload a
    zero

            | Bool
    otherwise
            = [Char] -> a
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> a) -> [Char] -> a
    forall a b. (a -> b) -> a -> b
    $ [[Char]] -> [Char]
    unlines
                    [ "mapStencil2: Your stencil is too big for this method."
                    , " It must fit within a 7x7 tile to be compiled statically." ]

    -- | Like above, but treat elements outside the array has having a constant value.
    unsafeAppStencilCursor2_const
            :: forall r a
            .  Source r a
            => (DIM2 -> DIM2 -> DIM2)
            -> Stencil DIM2 a
            -> a
            -> Array r DIM2 a
            -> DIM2
            -> a

    {-# INLINE unsafeAppStencilCursor2_const #-}
    unsafeAppStencilCursor2_const :: (DIM2 -> DIM2 -> DIM2)
    -> Stencil DIM2 a -> a -> Array r DIM2 a -> DIM2 -> a
    unsafeAppStencilCursor2_const shift :: DIM2 -> DIM2 -> DIM2
    shift
               (StencilStatic sExtent :: DIM2
    sExtent zero :: a
    zero loads :: DIM2 -> a -> a -> a
    loads)
               fixed :: a
    fixed arr :: Array r DIM2 a
    arr cur :: DIM2
    cur

            | _ :. sHeight :: Int
    sHeight      :. sWidth :: Int
    sWidth       <- DIM2
    sExtent
            , _ :. (I# aHeight :: Int#
    aHeight) :. (I# aWidth :: Int#
    aWidth)  <- Array r DIM2 a -> DIM2
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
    extent Array r DIM2 a
    arr
            , Int
    sHeight Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 7, Int
    sWidth Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 7
            = let
                    -- Get data from the manifest array.
                    {-# INLINE getData #-}
                    getData :: DIM2 -> a
                    getData :: DIM2 -> a
    getData (Z :. (I# y :: Int#
    y) :. (I# x :: Int#
    x))
                     = Int# -> Int# -> a
    getData' Int#
    x Int#
    y

                    {-# NOINLINE getData' #-}
                    getData' :: Int# -> Int# -> a
                    getData' :: Int# -> Int# -> a
    getData' !Int#
    x !Int#
    y
                     | Int#
    1# <-   (Int#
    x Int# -> Int# -> Int#
    <# 0#) Int# -> Int# -> Int#
    `orI#` (Int#
    x Int# -> Int# -> Int#
    >=# Int#
    aWidth)
                        Int# -> Int# -> Int#
    `orI#` (Int#
    y Int# -> Int# -> Int#
    <# 0#) Int# -> Int# -> Int#
    `orI#` (Int#
    y Int# -> Int# -> Int#
    >=# Int#
    aHeight)
                     = a
    fixed

                     | Bool
    otherwise
                     = Array r DIM2 a
    arr Array r DIM2 a -> DIM2 -> a
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh -> e
    `unsafeIndex` (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. (Int# -> Int
    I# Int#
    y) (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.  (Int# -> Int
    I# Int#
    x))

                    -- Build a function to pass data from the array to our stencil.
                    {-# INLINE oload #-}
                    oload :: Int -> Int -> a -> a
    oload oy :: Int
    oy ox :: Int
    ox
                     = let  !cur' :: DIM2
    cur' = DIM2 -> DIM2 -> DIM2
    shift (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    oy (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    ox) DIM2
    cur
                       in   DIM2 -> a -> a -> a
    loads (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    oy (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    ox) (DIM2 -> a
    getData DIM2
    cur')

               in   (Int -> Int -> a -> a) -> a -> a
    forall a. (Int -> Int -> a -> a) -> a -> a
    template7x7 Int -> Int -> a -> a
    oload a
    zero

            | Bool
    otherwise
            = [Char] -> a
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> a) -> [Char] -> a
    forall a b. (a -> b) -> a -> b
    $ [[Char]] -> [Char]
    unlines
                    [ "mapStencil2: Your stencil is too big for this method."
                    , " It must fit within a 7x7 tile to be compiled statically." ]

    -- | Like above, but clamp out of bounds array values to the closest real value.
    unsafeAppStencilCursor2_clamp
            :: forall r a
            .  Source r a
            => (DIM2 -> DIM2 -> DIM2)
            -> Stencil DIM2 a
            -> Array r DIM2 a
            -> DIM2
            -> a

    {-# INLINE unsafeAppStencilCursor2_clamp #-}
    unsafeAppStencilCursor2_clamp :: (DIM2 -> DIM2 -> DIM2)
    -> Stencil DIM2 a -> Array r DIM2 a -> DIM2 -> a
    unsafeAppStencilCursor2_clamp shift :: DIM2 -> DIM2 -> DIM2
    shift
               (StencilStatic sExtent :: DIM2
    sExtent zero :: a
    zero loads :: DIM2 -> a -> a -> a
    loads)
               arr :: Array r DIM2 a
    arr cur :: DIM2
    cur

            | _ :. sHeight :: Int
    sHeight      :. sWidth :: Int
    sWidth       <- DIM2
    sExtent
            , _ :. (I# aHeight :: Int#
    aHeight) :. (I# aWidth :: Int#
    aWidth)  <- Array r DIM2 a -> DIM2
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh
    extent Array r DIM2 a
    arr
            , Int
    sHeight Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 7, Int
    sWidth Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 7
            = let
                    -- Get data from the manifest array.
                    {-# INLINE getData #-}
                    getData :: DIM2 -> a
                    getData :: DIM2 -> a
    getData (Z :. (I# y :: Int#
    y) :. (I# x :: Int#
    x))
                     = Int# -> Int# -> a
    wrapLoadX Int#
    x Int#
    y

                    {-# NOINLINE wrapLoadX #-}
                    wrapLoadX :: Int# -> Int# -> a
                    wrapLoadX :: Int# -> Int# -> a
    wrapLoadX !Int#
    x !Int#
    y
                     | Int#
    1# <- Int#
    x Int# -> Int# -> Int#
    <# 0#        = Int# -> Int# -> a
    wrapLoadY 0#             Int#
    y
                     | Int#
    1# <- Int#
    x Int# -> Int# -> Int#
    >=# Int#
    aWidth   = Int# -> Int# -> a
    wrapLoadY (Int#
    aWidth Int# -> Int# -> Int#
    -# 1#) Int#
    y
                     | Bool
    otherwise    = Int# -> Int# -> a
    wrapLoadY Int#
    x Int#
    y

                    {-# NOINLINE wrapLoadY #-}
                    wrapLoadY :: Int# -> Int# -> a
                    wrapLoadY :: Int# -> Int# -> a
    wrapLoadY !Int#
    x !Int#
    y
                     | Int#
    1# <- Int#
    y Int# -> Int# -> Int#
    <#  0#       = Int# -> Int# -> a
    loadXY Int#
    x 0#
                     | Int#
    1# <- Int#
    y Int# -> Int# -> Int#
    >=# Int#
    aHeight  = Int# -> Int# -> a
    loadXY Int#
    x (Int#
    aHeight Int# -> Int# -> Int#
    -# 1#)
                     | Bool
    otherwise     = Int# -> Int# -> a
    loadXY Int#
    x Int#
    y

                    {-# INLINE loadXY #-}
                    loadXY :: Int# -> Int# -> a
                    loadXY :: Int# -> Int# -> a
    loadXY !Int#
    x !Int#
    y
                     = Array r DIM2 a
    arr Array r DIM2 a -> DIM2 -> a
    forall r e sh. (Source r e, Shape sh) => Array r sh e -> sh -> e
    `unsafeIndex` (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. (Int# -> Int
    I# Int#
    y) (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :.  (Int# -> Int
    I# Int#
    x))

                    -- Build a function to pass data from the array to our stencil.
                    {-# INLINE oload #-}
                    oload :: Int -> Int -> a -> a
    oload oy :: Int
    oy ox :: Int
    ox
                     = let  !cur' :: DIM2
    cur' = DIM2 -> DIM2 -> DIM2
    shift (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    oy (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    ox) DIM2
    cur
                       in   DIM2 -> a -> a -> a
    loads (Z
    Z Z -> Int -> Z :. Int
    forall tail head. tail -> head -> tail :. head
    :. Int
    oy (Z :. Int) -> Int -> DIM2
    forall tail head. tail -> head -> tail :. head
    :. Int
    ox) (DIM2 -> a
    getData DIM2
    cur')

               in   (Int -> Int -> a -> a) -> a -> a
    forall a. (Int -> Int -> a -> a) -> a -> a
    template7x7 Int -> Int -> a -> a
    oload a
    zero

            | Bool
    otherwise
            = [Char] -> a
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> a) -> [Char] -> a
    forall a b. (a -> b) -> a -> b
    $ [[Char]] -> [Char]
    unlines
                    [ "mapStencil2: Your stencil is too big for this method."
                    , " It must fit within a 7x7 tile to be compiled statically." ]

    -- | Data template for stencils up to 7x7.
    template7x7
            :: (Int -> Int -> a -> a)
            -> a -> a

    {-# INLINE template7x7 #-}
    template7x7 :: (Int -> Int -> a -> a) -> a -> a
    template7x7 f :: Int -> Int -> a -> a
    f zero :: a
    zero
            = Int -> Int -> a -> a
    f (-3) (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-3) (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-3) (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-3)   0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-3)   1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-3)   2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f (-3) 3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f (-2) (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-2) (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-2) (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-2)   0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-2)   1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-2)   2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f (-2) 3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f (-1) (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-1) (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-1) (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-1)   0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-1)   1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f (-1)   2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f (-1) 3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   0  (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   0  (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   0  (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   0    0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   0    1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   0    2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   0  3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   1  (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   1  (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   1  (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   1    0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   1    1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   1    2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   1  3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   2  (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   2  (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   2  (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   2    0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   2    1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   2    2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   2  3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   3  (-3)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   3  (-2)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   3  (-1)  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   3    0  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   3    1  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $  Int -> Int -> a -> a
    f   3    2  (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> a -> a
    f   3  3
            (a -> a) -> a -> a
    forall a b. (a -> b) -> a -> b
    $ a
    zero