{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Massiv.Array.Stencil (
Stencil,
makeStencil,
getStencilSize,
getStencilCenter,
Padding (..),
noPadding,
samePadding,
mapStencil,
applyStencil,
idStencil,
sumStencil,
productStencil,
avgStencil,
maxStencil,
minStencil,
foldlStencil,
foldrStencil,
foldStencil,
dimapStencil,
lmapStencil,
rmapStencil,
module Data.Massiv.Array.Stencil.Convolution,
) where
import Data.Coerce
import Data.Massiv.Array.Delayed.Windowed
import Data.Massiv.Array.Manifest
import Data.Massiv.Array.Stencil.Convolution
import Data.Massiv.Array.Stencil.Internal
import Data.Massiv.Array.Stencil.Unsafe
import Data.Massiv.Core.Common
import Data.Semigroup
import GHC.Exts (inline)
getStencilSize :: Stencil ix e a -> Sz ix
getStencilSize :: forall ix e a. Stencil ix e a -> Sz ix
getStencilSize = Stencil ix e a -> Sz ix
forall ix e a. Stencil ix e a -> Sz ix
stencilSize
getStencilCenter :: Stencil ix e a -> ix
getStencilCenter :: forall ix e a. Stencil ix e a -> ix
getStencilCenter = Stencil ix e a -> ix
forall ix e a. Stencil ix e a -> ix
stencilCenter
mapStencil
:: (Index ix, Manifest r e)
=> Border e
-> Stencil ix e a
-> Array r ix e
-> Array DW ix a
mapStencil :: forall ix r e a.
(Index ix, Manifest r e) =>
Border e -> Stencil ix e a -> Array r ix e -> Array DW ix a
mapStencil Border e
b Stencil ix e a
stencil = Padding ix e -> Stencil ix e a -> Array r ix e -> Array DW ix a
forall ix r e a.
(Index ix, Manifest r e) =>
Padding ix e -> Stencil ix e a -> Array r ix e -> Array DW ix a
applyStencil (Stencil ix e a -> Border e -> Padding ix e
forall ix e a.
Index ix =>
Stencil ix e a -> Border e -> Padding ix e
samePadding Stencil ix e a
stencil Border e
b) Stencil ix e a
stencil
{-# INLINE mapStencil #-}
data Padding ix e = Padding
{ forall ix e. Padding ix e -> Sz ix
paddingFromOrigin :: !(Sz ix)
, forall ix e. Padding ix e -> Sz ix
paddingFromBottom :: !(Sz ix)
, forall ix e. Padding ix e -> Border e
paddingWithElement :: !(Border e)
}
deriving (Padding ix e -> Padding ix e -> Bool
(Padding ix e -> Padding ix e -> Bool)
-> (Padding ix e -> Padding ix e -> Bool) -> Eq (Padding ix e)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall ix e. (Eq ix, Eq e) => Padding ix e -> Padding ix e -> Bool
$c== :: forall ix e. (Eq ix, Eq e) => Padding ix e -> Padding ix e -> Bool
== :: Padding ix e -> Padding ix e -> Bool
$c/= :: forall ix e. (Eq ix, Eq e) => Padding ix e -> Padding ix e -> Bool
/= :: Padding ix e -> Padding ix e -> Bool
Eq, Int -> Padding ix e -> ShowS
[Padding ix e] -> ShowS
Padding ix e -> String
(Int -> Padding ix e -> ShowS)
-> (Padding ix e -> String)
-> ([Padding ix e] -> ShowS)
-> Show (Padding ix e)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall ix e. (Index ix, Show e) => Int -> Padding ix e -> ShowS
forall ix e. (Index ix, Show e) => [Padding ix e] -> ShowS
forall ix e. (Index ix, Show e) => Padding ix e -> String
$cshowsPrec :: forall ix e. (Index ix, Show e) => Int -> Padding ix e -> ShowS
showsPrec :: Int -> Padding ix e -> ShowS
$cshow :: forall ix e. (Index ix, Show e) => Padding ix e -> String
show :: Padding ix e -> String
$cshowList :: forall ix e. (Index ix, Show e) => [Padding ix e] -> ShowS
showList :: [Padding ix e] -> ShowS
Show)
noPadding :: Index ix => Padding ix e
noPadding :: forall ix e. Index ix => Padding ix e
noPadding = Sz ix -> Sz ix -> Border e -> Padding ix e
forall ix e. Sz ix -> Sz ix -> Border e -> Padding ix e
Padding Sz ix
forall ix. Index ix => Sz ix
zeroSz Sz ix
forall ix. Index ix => Sz ix
zeroSz Border e
forall e. Border e
Edge
samePadding :: Index ix => Stencil ix e a -> Border e -> Padding ix e
samePadding :: forall ix e a.
Index ix =>
Stencil ix e a -> Border e -> Padding ix e
samePadding (Stencil (Sz ix
sSz) ix
sCenter (ix -> e) -> (ix -> e) -> ix -> a
_) Border e
border =
Padding
{ paddingFromOrigin :: Sz ix
paddingFromOrigin = ix -> Sz ix
forall ix. Index ix => ix -> Sz ix
Sz ix
sCenter
, paddingFromBottom :: Sz ix
paddingFromBottom = ix -> Sz ix
forall ix. Index ix => ix -> Sz ix
Sz ((Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 (-) ix
sSz ((Int -> Int) -> ix -> ix
forall ix. Index ix => (Int -> Int) -> ix -> ix
liftIndex (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) ix
sCenter))
, paddingWithElement :: Border e
paddingWithElement = Border e
border
}
applyStencil
:: (Index ix, Manifest r e)
=> Padding ix e
-> Stencil ix e a
-> Array r ix e
-> Array DW ix a
applyStencil :: forall ix r e a.
(Index ix, Manifest r e) =>
Padding ix e -> Stencil ix e a -> Array r ix e -> Array DW ix a
applyStencil (Padding (Sz ix
po) (Sz ix
pb) Border e
border) (Stencil Sz ix
sSz ix
sCenter (ix -> e) -> (ix -> e) -> ix -> a
stencilF) !Array r ix e
arr =
Array D ix a -> Window ix a -> Array DW ix a
forall ix e.
Index ix =>
Array D ix e -> Window ix e -> Array DW ix e
insertWindow Array D ix a
warr Window ix a
window
where
!offset :: ix
offset = (Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 (-) ix
sCenter ix
po
!warr :: Array D ix a
warr =
Comp -> Sz ix -> PrefIndex ix a -> Array D ix a
forall ix e. Comp -> Sz ix -> PrefIndex ix e -> Array D ix e
DArray
(Array r ix e -> Comp
forall r ix e. Strategy r => Array r ix e -> Comp
forall ix e. Array r ix e -> Comp
getComp Array r ix e
arr)
Sz ix
sz
((ix -> a) -> PrefIndex ix a
forall ix e. (ix -> e) -> PrefIndex ix e
PrefIndex ((ix -> e) -> (ix -> e) -> ix -> a
stencilF (Border e -> Array r ix e -> ix -> e
forall ix r e.
(Index ix, Manifest r e) =>
Border e -> Array r ix e -> ix -> e
borderIndex Border e
border Array r ix e
arr) (Border e -> Array r ix e -> ix -> e
forall ix r e.
(Index ix, Manifest r e) =>
Border e -> Array r ix e -> ix -> e
borderIndex Border e
border Array r ix e
arr) (ix -> a) -> (ix -> ix) -> ix -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ix
offset))
!shrinkSz :: Sz ix
shrinkSz = ix -> Sz ix
forall ix. Index ix => ix -> Sz ix
Sz ((Int -> Int) -> ix -> ix
forall ix. Index ix => (Int -> Int) -> ix -> ix
liftIndex (Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
1) (Sz ix -> ix
forall ix. Sz ix -> ix
unSz Sz ix
sSz))
!sz :: Sz ix
sz = (Int -> Int -> Int) -> Sz ix -> Sz ix -> Sz ix
forall ix.
Index ix =>
(Int -> Int -> Int) -> Sz ix -> Sz ix -> Sz ix
liftSz2 (-) (ix -> Sz ix
forall ix. ix -> Sz ix
SafeSz ((Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ix
po ((Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ix
pb (Sz ix -> ix
forall ix. Sz ix -> ix
unSz (Array r ix e -> Sz ix
forall r ix e. Size r => Array r ix e -> Sz ix
forall ix e. Array r ix e -> Sz ix
size Array r ix e
arr))))) Sz ix
shrinkSz
!wsz :: Sz ix
wsz = (Int -> Int -> Int) -> Sz ix -> Sz ix -> Sz ix
forall ix.
Index ix =>
(Int -> Int -> Int) -> Sz ix -> Sz ix -> Sz ix
liftSz2 (-) (Array r ix e -> Sz ix
forall r ix e. Size r => Array r ix e -> Sz ix
forall ix e. Array r ix e -> Sz ix
size Array r ix e
arr) Sz ix
shrinkSz
!window :: Window ix a
window =
Window
{ windowStart :: ix
windowStart = ix
po
, windowSize :: Sz ix
windowSize = Sz ix
wsz
, windowIndex :: ix -> a
windowIndex = (ix -> e) -> (ix -> e) -> ix -> a
stencilF (Array r ix e -> ix -> e
forall ix. Index ix => Array r ix e -> ix -> e
forall r e ix. (Source r e, Index ix) => Array r ix e -> ix -> e
unsafeIndex Array r ix e
arr) (Array r ix e -> ix -> e
forall ix r e.
(HasCallStack, Index ix, Manifest r e) =>
Array r ix e -> ix -> e
index' Array r ix e
arr) (ix -> a) -> (ix -> ix) -> ix -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ix
offset
, windowUnrollIx2 :: Maybe Int
windowUnrollIx2 = Sz Int -> Int
forall ix. Sz ix -> ix
unSz (Sz Int -> Int)
-> ((Sz Int, Sz (Lower ix)) -> Sz Int)
-> (Sz Int, Sz (Lower ix))
-> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Sz Int, Sz (Lower ix)) -> Sz Int
forall a b. (a, b) -> a
fst ((Sz Int, Sz (Lower ix)) -> Int)
-> Maybe (Sz Int, Sz (Lower ix)) -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sz ix -> Dim -> Maybe (Sz Int, Sz (Lower ix))
forall (m :: * -> *) ix.
(MonadThrow m, Index ix) =>
Sz ix -> Dim -> m (Sz Int, Sz (Lower ix))
pullOutSzM Sz ix
sSz Dim
2
}
{-# INLINE applyStencil #-}
makeStencil
:: Index ix
=> Sz ix
-> ix
-> ((ix -> e) -> a)
-> Stencil ix e a
makeStencil :: forall ix e a.
Index ix =>
Sz ix -> ix -> ((ix -> e) -> a) -> Stencil ix e a
makeStencil !Sz ix
sSz !ix
sCenter (ix -> e) -> a
relStencil = Sz ix
-> ix -> ((ix -> e) -> (ix -> e) -> ix -> a) -> Stencil ix e a
forall ix e a.
Sz ix
-> ix -> ((ix -> e) -> (ix -> e) -> ix -> a) -> Stencil ix e a
Stencil Sz ix
sSz ix
sCenter (ix -> e) -> (ix -> e) -> ix -> a
stencil
where
stencil :: (ix -> e) -> (ix -> e) -> ix -> a
stencil ix -> e
_ ix -> e
getVal !ix
ix = a -> a
forall a. a -> a
inline ((ix -> e) -> a
relStencil (ix -> e
getVal (ix -> e) -> (ix -> ix) -> ix -> e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 Int -> Int -> Int
forall a. Num a => a -> a -> a
(+) ix
ix))
{-# INLINE stencil #-}
{-# INLINE makeStencil #-}
idStencil :: Index ix => Stencil ix e e
idStencil :: forall ix e. Index ix => Stencil ix e e
idStencil = Sz ix -> ix -> (ix -> (ix -> e) -> e) -> Stencil ix e e
forall ix e a.
Index ix =>
Sz ix -> ix -> (ix -> (ix -> e) -> a) -> Stencil ix e a
makeUnsafeStencil Sz ix
forall ix. Index ix => Sz ix
oneSz ix
forall ix. Index ix => ix
zeroIndex ((ix -> (ix -> e) -> e) -> Stencil ix e e)
-> (ix -> (ix -> e) -> e) -> Stencil ix e e
forall a b. (a -> b) -> a -> b
$ \ix
_ ix -> e
get -> ix -> e
get ix
forall ix. Index ix => ix
zeroIndex
{-# INLINE idStencil #-}
foldlStencil :: Index ix => (a -> e -> a) -> a -> Sz ix -> Stencil ix e a
foldlStencil :: forall ix a e.
Index ix =>
(a -> e -> a) -> a -> Sz ix -> Stencil ix e a
foldlStencil a -> e -> a
f a
acc0 Sz ix
sz =
Sz ix -> ix -> (ix -> (ix -> e) -> a) -> Stencil ix e a
forall ix e a.
Index ix =>
Sz ix -> ix -> (ix -> (ix -> e) -> a) -> Stencil ix e a
makeUnsafeStencil Sz ix
sz ix
forall ix. Index ix => ix
zeroIndex ((ix -> (ix -> e) -> a) -> Stencil ix e a)
-> (ix -> (ix -> e) -> a) -> Stencil ix e a
forall a b. (a -> b) -> a -> b
$ \ix
_ ix -> e
get ->
ix -> ix -> ix -> (Int -> Int -> Bool) -> a -> (ix -> a -> a) -> a
forall ix a.
Index ix =>
ix -> ix -> ix -> (Int -> Int -> Bool) -> a -> (ix -> a -> a) -> a
iter ix
forall ix. Index ix => ix
zeroIndex (Sz ix -> ix
forall ix. Sz ix -> ix
unSz Sz ix
sz) ix
forall ix. Index ix => ix
oneIndex Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(<) a
acc0 ((ix -> a -> a) -> a) -> (ix -> a -> a) -> a
forall a b. (a -> b) -> a -> b
$ \ix
ix -> (a -> e -> a
`f` ix -> e
get ix
ix)
{-# INLINE foldlStencil #-}
foldrStencil :: Index ix => (e -> a -> a) -> a -> Sz ix -> Stencil ix e a
foldrStencil :: forall ix e a.
Index ix =>
(e -> a -> a) -> a -> Sz ix -> Stencil ix e a
foldrStencil e -> a -> a
f a
acc0 Sz ix
sz =
let ixStart :: ix
ixStart = (Int -> Int -> Int) -> ix -> ix -> ix
forall ix. Index ix => (Int -> Int -> Int) -> ix -> ix -> ix
liftIndex2 (-) (Sz ix -> ix
forall ix. Sz ix -> ix
unSz Sz ix
sz) ix
forall ix. Index ix => ix
oneIndex
in Sz ix -> ix -> (ix -> (ix -> e) -> a) -> Stencil ix e a
forall ix e a.
Index ix =>
Sz ix -> ix -> (ix -> (ix -> e) -> a) -> Stencil ix e a
makeUnsafeStencil Sz ix
sz ix
forall ix. Index ix => ix
zeroIndex ((ix -> (ix -> e) -> a) -> Stencil ix e a)
-> (ix -> (ix -> e) -> a) -> Stencil ix e a
forall a b. (a -> b) -> a -> b
$ \ix
_ ix -> e
get ->
ix -> ix -> ix -> (Int -> Int -> Bool) -> a -> (ix -> a -> a) -> a
forall ix a.
Index ix =>
ix -> ix -> ix -> (Int -> Int -> Bool) -> a -> (ix -> a -> a) -> a
iter ix
ixStart ix
forall ix. Index ix => ix
zeroIndex (Int -> ix
forall ix. Index ix => Int -> ix
pureIndex (-Int
1)) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
(>=) a
acc0 ((ix -> a -> a) -> a) -> (ix -> a -> a) -> a
forall a b. (a -> b) -> a -> b
$ \ix
ix -> e -> a -> a
f (ix -> e
get ix
ix)
{-# INLINE foldrStencil #-}
foldStencil :: (Monoid e, Index ix) => Sz ix -> Stencil ix e e
foldStencil :: forall e ix. (Monoid e, Index ix) => Sz ix -> Stencil ix e e
foldStencil = (e -> e -> e) -> e -> Sz ix -> Stencil ix e e
forall ix a e.
Index ix =>
(a -> e -> a) -> a -> Sz ix -> Stencil ix e a
foldlStencil e -> e -> e
forall a. Monoid a => a -> a -> a
mappend e
forall a. Monoid a => a
mempty
{-# INLINE foldStencil #-}
maxStencil :: (Bounded e, Ord e, Index ix) => Sz ix -> Stencil ix e e
maxStencil :: forall e ix.
(Bounded e, Ord e, Index ix) =>
Sz ix -> Stencil ix e e
maxStencil = (e -> Max e)
-> (Max e -> e) -> Stencil ix (Max e) (Max e) -> Stencil ix e e
forall c d a b ix.
(c -> d) -> (a -> b) -> Stencil ix d a -> Stencil ix c b
dimapStencil e -> Max e
forall a b. Coercible a b => a -> b
coerce Max e -> e
forall a. Max a -> a
getMax (Stencil ix (Max e) (Max e) -> Stencil ix e e)
-> (Sz ix -> Stencil ix (Max e) (Max e)) -> Sz ix -> Stencil ix e e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Stencil ix (Max e) (Max e)
forall e ix. (Monoid e, Index ix) => Sz ix -> Stencil ix e e
foldStencil
{-# INLINE maxStencil #-}
minStencil :: (Bounded e, Ord e, Index ix) => Sz ix -> Stencil ix e e
minStencil :: forall e ix.
(Bounded e, Ord e, Index ix) =>
Sz ix -> Stencil ix e e
minStencil = (e -> Min e)
-> (Min e -> e) -> Stencil ix (Min e) (Min e) -> Stencil ix e e
forall c d a b ix.
(c -> d) -> (a -> b) -> Stencil ix d a -> Stencil ix c b
dimapStencil e -> Min e
forall a b. Coercible a b => a -> b
coerce Min e -> e
forall a. Min a -> a
getMin (Stencil ix (Min e) (Min e) -> Stencil ix e e)
-> (Sz ix -> Stencil ix (Min e) (Min e)) -> Sz ix -> Stencil ix e e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Stencil ix (Min e) (Min e)
forall e ix. (Monoid e, Index ix) => Sz ix -> Stencil ix e e
foldStencil
{-# INLINE minStencil #-}
sumStencil :: (Num e, Index ix) => Sz ix -> Stencil ix e e
sumStencil :: forall e ix. (Num e, Index ix) => Sz ix -> Stencil ix e e
sumStencil = (e -> Sum e)
-> (Sum e -> e) -> Stencil ix (Sum e) (Sum e) -> Stencil ix e e
forall c d a b ix.
(c -> d) -> (a -> b) -> Stencil ix d a -> Stencil ix c b
dimapStencil e -> Sum e
forall a b. Coercible a b => a -> b
coerce Sum e -> e
forall a. Sum a -> a
getSum (Stencil ix (Sum e) (Sum e) -> Stencil ix e e)
-> (Sz ix -> Stencil ix (Sum e) (Sum e)) -> Sz ix -> Stencil ix e e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Stencil ix (Sum e) (Sum e)
forall e ix. (Monoid e, Index ix) => Sz ix -> Stencil ix e e
foldStencil
{-# INLINE sumStencil #-}
productStencil :: (Num e, Index ix) => Sz ix -> Stencil ix e e
productStencil :: forall e ix. (Num e, Index ix) => Sz ix -> Stencil ix e e
productStencil = (e -> Product e)
-> (Product e -> e)
-> Stencil ix (Product e) (Product e)
-> Stencil ix e e
forall c d a b ix.
(c -> d) -> (a -> b) -> Stencil ix d a -> Stencil ix c b
dimapStencil e -> Product e
forall a b. Coercible a b => a -> b
coerce Product e -> e
forall a. Product a -> a
getProduct (Stencil ix (Product e) (Product e) -> Stencil ix e e)
-> (Sz ix -> Stencil ix (Product e) (Product e))
-> Sz ix
-> Stencil ix e e
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sz ix -> Stencil ix (Product e) (Product e)
forall e ix. (Monoid e, Index ix) => Sz ix -> Stencil ix e e
foldStencil
{-# INLINE productStencil #-}
avgStencil :: (Fractional e, Index ix) => Sz ix -> Stencil ix e e
avgStencil :: forall e ix. (Fractional e, Index ix) => Sz ix -> Stencil ix e e
avgStencil Sz ix
sz = Sz ix -> Stencil ix e e
forall e ix. (Num e, Index ix) => Sz ix -> Stencil ix e e
sumStencil Sz ix
sz Stencil ix e e -> Stencil ix e e -> Stencil ix e e
forall a. Fractional a => a -> a -> a
/ Int -> Stencil ix e e
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Sz ix -> Int
forall ix. Index ix => Sz ix -> Int
totalElem Sz ix
sz)
{-# INLINE avgStencil #-}