{-# OPTIONS_GHC -fplugin=GHC.TypeLits.KnownNat.Solver -fplugin=GHC.TypeLits.Normalise -fconstraint-solver-iterations=10 #-}
{-# LANGUAGE ConstraintKinds,TypeApplications,UndecidableInstances #-}

-- | Manifolds of 'Convolutional' operators. This is hardly used, but could in
-- theory power conv nets. One day.
module Goal.Geometry.Map.Linear.Convolutional
    ( -- * Convolutional Manifolds
      Convolutional
    , KnownConvolutional
    ) where


--- Imports ---


-- Goal --

import Goal.Core
import Goal.Geometry.Manifold
import Goal.Geometry.Map
import Goal.Geometry.Vector
import Goal.Geometry.Map.Linear
import Goal.Geometry.Differential

import qualified Goal.Core.Vector.Generic as G
import qualified Goal.Core.Vector.Storable as S


-- Convolutional Layers --

-- | A 'Manifold' of correlational/convolutional transformations, defined by the
-- number of kernels, their radius, the depth of the input, and its number of
-- rows and columns.
data Convolutional (rd :: Nat) (r :: Nat) (c :: Nat) :: Type -> Type -> Type

-- | A convenience type for ensuring that all the type-level Nats of a
-- 'Convolutional' 'Manifold's are 'KnownNat's.
type KnownConvolutional rd r c z x
  = ( KnownNat rd, KnownNat r, KnownNat c, 1 <= r*c
    , Dimension x ~ (Div (Dimension x) (r*c) * r*c)
    , Dimension z ~ (Div (Dimension z) (r*c) * r*c)
    , Manifold (Convolutional rd r c z x)
    , Manifold x, Manifold z
    , KnownNat (Div (Dimension x) (r*c))
    , KnownNat (Div (Dimension z) (r*c))
    )

inputToImage
    :: (KnownConvolutional rd r c z x)
    => a # Convolutional rd r c z x
    -> a #* x
    -> S.Matrix (Div (Dimension x) (r*c)) (r*c) Double
{-# INLINE inputToImage #-}
inputToImage :: (a # Convolutional rd r c z x)
-> (a #* x) -> Matrix (Div (Dimension x) (r * c)) (r * c) Double
inputToImage a # Convolutional rd r c z x
_ (Point Vector (Dimension x) Double
img) = Vector Vector (Div (Dimension x) (r * c) * (r * c)) Double
-> Matrix (Div (Dimension x) (r * c)) (r * c) Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Vector v (m * n) a -> Matrix v m n a
G.Matrix Vector Vector (Div (Dimension x) (r * c) * (r * c)) Double
Vector (Dimension x) Double
img

outputToImage
    :: (KnownConvolutional rd r c z x)
    => a # Convolutional rd r c z x
    -> a #* z
    -> S.Matrix (Div (Dimension z) (r*c)) (r*c) Double
{-# INLINE outputToImage #-}
outputToImage :: (a # Convolutional rd r c z x)
-> (a #* z) -> Matrix (Div (Dimension z) (r * c)) (r * c) Double
outputToImage a # Convolutional rd r c z x
_ (Point Vector (Dimension z) Double
img) = Vector Vector (Div (Dimension z) (r * c) * (r * c)) Double
-> Matrix (Div (Dimension z) (r * c)) (r * c) Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Vector v (m * n) a -> Matrix v m n a
G.Matrix Vector Vector (Div (Dimension z) (r * c) * (r * c)) Double
Vector (Dimension z) Double
img

layerToKernels
    :: ( KnownConvolutional rd r c z x)
    => a # Convolutional rd r c z x
    -> S.Matrix (Div (Dimension z) (r*c)) (Div (Dimension x) (r*c) * (2*rd+1)*(2*rd+1)) Double
{-# INLINE layerToKernels #-}
layerToKernels :: (a # Convolutional rd r c z x)
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
layerToKernels (Point Vector (Dimension (Convolutional rd r c z x)) Double
krns) = Vector
  Vector
  (Div (Dimension z) (r * c)
   * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
  Double
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Vector v (m * n) a -> Matrix v m n a
G.Matrix Vector
  Vector
  (Div (Dimension z) (r * c)
   * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
  Double
Vector (Dimension (Convolutional rd r c z x)) Double
krns

convolveApply
    :: forall a rd r c z x
    . KnownConvolutional rd r c z x
    => a # Convolutional rd r c z x
    -> a #* x
    -> a # z
{-# INLINE convolveApply #-}
convolveApply :: (a # Convolutional rd r c z x) -> (a #* x) -> a # z
convolveApply a # Convolutional rd r c z x
cnv a #* x
imp =
    let img :: S.Matrix (Div (Dimension x) (r*c)) (r*c) Double
        img :: Matrix (Div (Dimension x) (r * c)) (r * c) Double
img = (a # Convolutional rd r c z x)
-> (a #* x) -> Matrix (Div (Dimension x) (r * c)) (r * c) Double
forall (rd :: Nat) (r :: Nat) (c :: Nat) z x a.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x)
-> (a #* x) -> Matrix (Div (Dimension x) (r * c)) (r * c) Double
inputToImage a # Convolutional rd r c z x
cnv a #* x
imp
        krns :: S.Matrix (Div (Dimension z) (r*c)) (Div (Dimension x) (r*c) * (2*rd+1)*(2*rd+1)) Double
        krns :: Matrix
  (Div (Dimension z) (r * c))
  ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
krns = (a # Convolutional rd r c z x)
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
forall (rd :: Nat) (r :: Nat) (c :: Nat) z x a.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x)
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
layerToKernels a # Convolutional rd r c z x
cnv
     in Vector Vector ((Div (Dimension z) (r * c) * r) * c) Double -> a # z
forall c x. Vector (Dimension x) Double -> Point c x
Point (Vector Vector ((Div (Dimension z) (r * c) * r) * c) Double
 -> a # z)
-> (Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
    -> Vector Vector ((Div (Dimension z) (r * c) * r) * c) Double)
-> Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
-> a # z
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
-> Vector Vector ((Div (Dimension z) (r * c) * r) * c) Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Matrix v m n a -> Vector v (m * n) a
G.toVector
         (Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double -> a # z)
-> Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
-> a # z
forall a b. (a -> b) -> a -> b
$ Proxy rd
-> Proxy rd
-> Proxy r
-> Proxy c
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
-> Matrix (Div (Dimension x) (r * c)) (r * c) Double
-> Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
forall (nk :: Nat) (rdkr :: Nat) (rdkc :: Nat) (mr :: Nat)
       (mc :: Nat) (md :: Nat) x.
(KnownNat rdkr, KnownNat rdkc, KnownNat md, KnownNat mr,
 KnownNat mc, KnownNat nk, Numeric x, Storable x) =>
Proxy rdkr
-> Proxy rdkc
-> Proxy mr
-> Proxy mc
-> Matrix nk ((md * ((2 * rdkr) + 1)) * ((2 * rdkc) + 1)) x
-> Matrix md (mr * mc) x
-> Matrix nk (mr * mc) x
S.crossCorrelate2d (Proxy rd
forall k (t :: k). Proxy t
Proxy @ rd) (Proxy rd
forall k (t :: k). Proxy t
Proxy @ rd) (Proxy r
forall k (t :: k). Proxy t
Proxy @ r) (Proxy c
forall k (t :: k). Proxy t
Proxy @ c) Matrix
  (Div (Dimension z) (r * c))
  ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
krns Matrix (Div (Dimension x) (r * c)) (r * c) Double
img

convolveTranspose
    :: forall a rd r c z x
    . KnownConvolutional rd r c z x
    => a # Convolutional rd r c z x
    -> a # Convolutional rd r c x z
{-# INLINE convolveTranspose #-}
convolveTranspose :: (a # Convolutional rd r c z x) -> a # Convolutional rd r c x z
convolveTranspose a # Convolutional rd r c z x
cnv =
    let krns :: Matrix
  (Div (Dimension z) (r * c))
  ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
krns = (a # Convolutional rd r c z x)
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
forall (rd :: Nat) (r :: Nat) (c :: Nat) z x a.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x)
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
layerToKernels a # Convolutional rd r c z x
cnv
        pnk :: Proxy (Div (Dimension z) (r * c))
pnk = Proxy (Div (Dimension z) (r * c))
forall k (t :: k). Proxy t
Proxy :: Proxy (Div (Dimension z) (r*c))
        pmd :: Proxy (Div (Dimension x) (r * c))
pmd = Proxy (Div (Dimension x) (r * c))
forall k (t :: k). Proxy t
Proxy :: Proxy (Div (Dimension x) (r*c))
        krn' :: S.Matrix (Div (Dimension x) (r*c)) (Div (Dimension z) (r*c)*(2*rd+1)*(2*rd+1)) Double
        krn' :: Matrix
  (Div (Dimension x) (r * c))
  ((Div (Dimension z) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
krn' = Proxy (Div (Dimension z) (r * c))
-> Proxy (Div (Dimension x) (r * c))
-> Proxy rd
-> Proxy rd
-> Matrix
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
-> Matrix
     (Div (Dimension x) (r * c))
     ((Div (Dimension z) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
forall (nk :: Nat) (md :: Nat) (rdkr :: Nat) (rdkc :: Nat) x.
(KnownNat nk, KnownNat md, KnownNat rdkr, KnownNat rdkc, Numeric x,
 Storable x) =>
Proxy nk
-> Proxy md
-> Proxy rdkr
-> Proxy rdkc
-> Matrix nk ((md * ((2 * rdkr) + 1)) * ((2 * rdkc) + 1)) x
-> Matrix md ((nk * ((2 * rdkr) + 1)) * ((2 * rdkc) + 1)) x
S.kernelTranspose Proxy (Div (Dimension z) (r * c))
pnk Proxy (Div (Dimension x) (r * c))
pmd (Proxy rd
forall k (t :: k). Proxy t
Proxy @ rd) (Proxy rd
forall k (t :: k). Proxy t
Proxy @ rd) Matrix
  (Div (Dimension z) (r * c))
  ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
krns
     in Vector (Dimension (Convolutional rd r c x z)) Double
-> a # Convolutional rd r c x z
forall c x. Vector (Dimension x) Double -> Point c x
Point (Vector (Dimension (Convolutional rd r c x z)) Double
 -> a # Convolutional rd r c x z)
-> Vector (Dimension (Convolutional rd r c x z)) Double
-> a # Convolutional rd r c x z
forall a b. (a -> b) -> a -> b
$ Matrix
  (Div (Dimension x) (r * c))
  ((Div (Dimension z) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
-> Vector
     Vector
     (Div (Dimension x) (r * c)
      * ((Div (Dimension z) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
     Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Matrix v m n a -> Vector v (m * n) a
G.toVector Matrix
  (Div (Dimension x) (r * c))
  ((Div (Dimension z) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
krn'

--convolveTransposeApply
--    :: forall a rd r c z x . KnownConvolutional rd r c z x
--    => Dual a # z
--    -> a #> Convolutional rd r c z x
--    -> a # x
--{-# INLINE convolveTransposeApply #-}
--convolveTransposeApply imp cnv =
--    let img = outputToImage cnv imp
--        krns = layerToKernels cnv
--     in Point . G.toVector
--         $ S.convolve2d (Proxy @ rd) (Proxy @ rd) (Proxy @ r) (Proxy @ c) krns img

convolutionalOuterProduct
    :: forall a rd r c z x
    . KnownConvolutional rd r c z x
      => a # z
      -> a # x
      -> a # Convolutional rd r c z x
{-# INLINE convolutionalOuterProduct #-}
convolutionalOuterProduct :: (a # z) -> (a # x) -> a # Convolutional rd r c z x
convolutionalOuterProduct (Point Vector (Dimension z) Double
oimg) (Point Vector (Dimension x) Double
iimg) =
    let omtx :: Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
omtx = Vector Vector (Div (Dimension z) (r * c) * (r * c)) Double
-> Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Vector v (m * n) a -> Matrix v m n a
G.Matrix Vector Vector (Div (Dimension z) (r * c) * (r * c)) Double
Vector (Dimension z) Double
oimg
        imtx :: Matrix Vector (Div (Dimension x) (r * c)) (r * c) Double
imtx = Vector Vector (Div (Dimension x) (r * c) * (r * c)) Double
-> Matrix Vector (Div (Dimension x) (r * c)) (r * c) Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Vector v (m * n) a -> Matrix v m n a
G.Matrix Vector Vector (Div (Dimension x) (r * c) * (r * c)) Double
Vector (Dimension x) Double
iimg
     in Vector
  Vector
  (Div (Dimension z) (r * c)
   * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
  Double
-> a # Convolutional rd r c z x
forall c x. Vector (Dimension x) Double -> Point c x
Point (Vector
   Vector
   (Div (Dimension z) (r * c)
    * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
   Double
 -> a # Convolutional rd r c z x)
-> (Matrix
      Vector
      (Div (Dimension z) (r * c))
      ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
      Double
    -> Vector
         Vector
         (Div (Dimension z) (r * c)
          * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
         Double)
-> Matrix
     Vector
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
-> a # Convolutional rd r c z x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix
  Vector
  (Div (Dimension z) (r * c))
  ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
-> Vector
     Vector
     (Div (Dimension z) (r * c)
      * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
     Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Matrix v m n a -> Vector v (m * n) a
G.toVector (Matrix
   Vector
   (Div (Dimension z) (r * c))
   ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
   Double
 -> a # Convolutional rd r c z x)
-> Matrix
     Vector
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
-> a # Convolutional rd r c z x
forall a b. (a -> b) -> a -> b
$ Proxy rd
-> Proxy rd
-> Proxy r
-> Proxy c
-> Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
-> Matrix Vector (Div (Dimension x) (r * c)) (r * c) Double
-> Matrix
     Vector
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
forall (nk :: Nat) (rdkr :: Nat) (rdkc :: Nat) (md :: Nat)
       (mr :: Nat) (mc :: Nat) x.
(KnownNat rdkr, KnownNat rdkc, KnownNat mr, KnownNat mc,
 KnownNat md, KnownNat nk, Numeric x, Storable x) =>
Proxy rdkr
-> Proxy rdkc
-> Proxy mr
-> Proxy mc
-> Matrix nk (mr * mc) x
-> Matrix md (mr * mc) x
-> Matrix nk ((md * ((2 * rdkr) + 1)) * ((2 * rdkc) + 1)) x
S.kernelOuterProduct (Proxy rd
forall k (t :: k). Proxy t
Proxy @ rd) (Proxy rd
forall k (t :: k). Proxy t
Proxy @ rd) (Proxy r
forall k (t :: k). Proxy t
Proxy @ r) (Proxy c
forall k (t :: k). Proxy t
Proxy @ c) Matrix Vector (Div (Dimension z) (r * c)) (r * c) Double
omtx Matrix Vector (Div (Dimension x) (r * c)) (r * c) Double
imtx

convolvePropagate
    :: forall a rd r c z x . KnownConvolutional rd r c z x
      => [a #* z]
      -> [a #* x]
      -> a # Convolutional rd r c z x
      -> (a #* Convolutional rd r c z x, [a # z])
{-# INLINE convolvePropagate #-}
convolvePropagate :: [a #* z]
-> [a #* x]
-> (a # Convolutional rd r c z x)
-> (a #* Convolutional rd r c z x, [a # z])
convolvePropagate [a #* z]
omps [a #* x]
imps a # Convolutional rd r c z x
cnv =
    let prdkr :: Proxy rd
prdkr = Proxy rd
forall k (t :: k). Proxy t
Proxy :: Proxy rd
        prdkc :: Proxy rd
prdkc = Proxy rd
forall k (t :: k). Proxy t
Proxy :: Proxy rd
        pmr :: Proxy r
pmr = Proxy r
forall k (t :: k). Proxy t
Proxy :: Proxy r
        pmc :: Proxy c
pmc = Proxy c
forall k (t :: k). Proxy t
Proxy :: Proxy c
        foldfun :: (a #* z, a #* x)
-> (Double, a #* Convolutional rd r c z x)
-> (Double, a #* Convolutional rd r c z x)
foldfun (a #* z
omp,a #* x
imp) (Double
k,a #* Convolutional rd r c z x
dkrns) =
            let img :: Matrix (Div (Dimension x) (r * c)) (r * c) Double
img = (a # Convolutional rd r c z x)
-> (a #* x) -> Matrix (Div (Dimension x) (r * c)) (r * c) Double
forall (rd :: Nat) (r :: Nat) (c :: Nat) z x a.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x)
-> (a #* x) -> Matrix (Div (Dimension x) (r * c)) (r * c) Double
inputToImage a # Convolutional rd r c z x
cnv a #* x
imp
                dimg :: Matrix (Div (Dimension z) (r * c)) (r * c) Double
dimg = (a # Convolutional rd r c z x)
-> (a #* z) -> Matrix (Div (Dimension z) (r * c)) (r * c) Double
forall (rd :: Nat) (r :: Nat) (c :: Nat) z x a.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x)
-> (a #* z) -> Matrix (Div (Dimension z) (r * c)) (r * c) Double
outputToImage a # Convolutional rd r c z x
cnv a #* z
omp
                dkrns' :: a #* Convolutional rd r c z x
dkrns' = Vector
  Vector
  (Div (Dimension z) (r * c)
   * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
  Double
-> a #* Convolutional rd r c z x
forall c x. Vector (Dimension x) Double -> Point c x
Point (Vector
   Vector
   (Div (Dimension z) (r * c)
    * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
   Double
 -> a #* Convolutional rd r c z x)
-> (Matrix
      Vector
      (Div (Dimension z) (r * c))
      ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
      Double
    -> Vector
         Vector
         (Div (Dimension z) (r * c)
          * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
         Double)
-> Matrix
     Vector
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
-> a #* Convolutional rd r c z x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix
  Vector
  (Div (Dimension z) (r * c))
  ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
  Double
-> Vector
     Vector
     (Div (Dimension z) (r * c)
      * ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1)))
     Double
forall (v :: Type -> Type) (m :: Nat) (n :: Nat) a.
Matrix v m n a -> Vector v (m * n) a
G.toVector (Matrix
   Vector
   (Div (Dimension z) (r * c))
   ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
   Double
 -> a #* Convolutional rd r c z x)
-> Matrix
     Vector
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
-> a #* Convolutional rd r c z x
forall a b. (a -> b) -> a -> b
$ Proxy rd
-> Proxy rd
-> Proxy r
-> Proxy c
-> Matrix (Div (Dimension z) (r * c)) (r * c) Double
-> Matrix (Div (Dimension x) (r * c)) (r * c) Double
-> Matrix
     Vector
     (Div (Dimension z) (r * c))
     ((Div (Dimension x) (r * c) * ((2 * rd) + 1)) * ((2 * rd) + 1))
     Double
forall (nk :: Nat) (rdkr :: Nat) (rdkc :: Nat) (md :: Nat)
       (mr :: Nat) (mc :: Nat) x.
(KnownNat rdkr, KnownNat rdkc, KnownNat mr, KnownNat mc,
 KnownNat md, KnownNat nk, Numeric x, Storable x) =>
Proxy rdkr
-> Proxy rdkc
-> Proxy mr
-> Proxy mc
-> Matrix nk (mr * mc) x
-> Matrix md (mr * mc) x
-> Matrix nk ((md * ((2 * rdkr) + 1)) * ((2 * rdkc) + 1)) x
S.kernelOuterProduct Proxy rd
prdkr Proxy rd
prdkc Proxy r
pmr Proxy c
pmc Matrix (Div (Dimension z) (r * c)) (r * c) Double
dimg Matrix (Div (Dimension x) (r * c)) (r * c) Double
img
             in (Double
kDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
1,a #* Convolutional rd r c z x
dkrns' (a #* Convolutional rd r c z x)
-> (a #* Convolutional rd r c z x) -> a #* Convolutional rd r c z x
forall a. Num a => a -> a -> a
+ a #* Convolutional rd r c z x
dkrns)
     in ((Double
 -> (a #* Convolutional rd r c z x)
 -> a #* Convolutional rd r c z x)
-> (Double, a #* Convolutional rd r c z x)
-> a #* Convolutional rd r c z x
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Double
-> (a #* Convolutional rd r c z x) -> a #* Convolutional rd r c z x
forall c x. Double -> (c # x) -> c # x
(/>) ((Double, a #* Convolutional rd r c z x)
 -> a #* Convolutional rd r c z x)
-> ([(a #* z, a #* x)] -> (Double, a #* Convolutional rd r c z x))
-> [(a #* z, a #* x)]
-> a #* Convolutional rd r c z x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a #* z, a #* x)
 -> (Double, a #* Convolutional rd r c z x)
 -> (Double, a #* Convolutional rd r c z x))
-> (Double, a #* Convolutional rd r c z x)
-> [(a #* z, a #* x)]
-> (Double, a #* Convolutional rd r c z x)
forall (t :: Type -> Type) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (a #* z, a #* x)
-> (Double, a #* Convolutional rd r c z x)
-> (Double, a #* Convolutional rd r c z x)
foldfun (Double
0,a #* Convolutional rd r c z x
0) ([(a #* z, a #* x)] -> a #* Convolutional rd r c z x)
-> [(a #* z, a #* x)] -> a #* Convolutional rd r c z x
forall a b. (a -> b) -> a -> b
$ [a #* z] -> [a #* x] -> [(a #* z, a #* x)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a #* z]
omps [a #* x]
imps, a # Convolutional rd r c z x
cnv (a # Convolutional rd r c z x) -> [a #* x] -> [a # z]
forall c (f :: Type -> Type -> Type) y x.
Map c f y x =>
(c # f y x) -> [c #* x] -> [c # y]
>$> [a #* x]
imps)


--- Instances ---


-- Convolutional Manifolds --

instance ( 1 <= r*c, Manifold x, Manifold y, KnownNat r, KnownNat c, KnownNat rd
         , KnownNat (Div (Dimension x) (r*c)) , KnownNat (Div (Dimension y) (r*c)) )
  => Manifold (Convolutional rd r c y x) where
      type Dimension (Convolutional rd r c y x)
        = (Div (Dimension y) (r * c) * ((Div (Dimension x) (r * c) * (2 * rd + 1)) * (2 * rd + 1)))


instance KnownConvolutional rd r c z x => Map a (Convolutional rd r c) z x where
      {-# INLINE (>.>) #-}
      >.> :: (a # Convolutional rd r c z x) -> (a #* x) -> a # z
(>.>) = (a # Convolutional rd r c z x) -> (a #* x) -> a # z
forall a (rd :: Nat) (r :: Nat) (c :: Nat) z x.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x) -> (a #* x) -> a # z
convolveApply
      {-# INLINE (>$>) #-}
      >$> :: (a # Convolutional rd r c z x) -> [a #* x] -> [a # z]
(>$>) a # Convolutional rd r c z x
cnv = ((a #* x) -> a # z) -> [a #* x] -> [a # z]
forall a b. (a -> b) -> [a] -> [b]
map ((a # Convolutional rd r c z x) -> (a #* x) -> a # z
forall a (rd :: Nat) (r :: Nat) (c :: Nat) z x.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x) -> (a #* x) -> a # z
convolveApply a # Convolutional rd r c z x
cnv)

instance KnownConvolutional rd r c z x => Bilinear (Convolutional rd r c) z x where
    {-# INLINE (>.<) #-}
    >.< :: (c # z) -> (c # x) -> c # Convolutional rd r c z x
(>.<) = (c # z) -> (c # x) -> c # Convolutional rd r c z x
forall a (rd :: Nat) (r :: Nat) (c :: Nat) z x.
KnownConvolutional rd r c z x =>
(a # z) -> (a # x) -> a # Convolutional rd r c z x
convolutionalOuterProduct
    {-# INLINE (>$<) #-}
    >$< :: [c # z] -> [c # x] -> c # Convolutional rd r c z x
(>$<) [c # z]
ps [c # x]
qs = [c # Convolutional rd r c z x] -> c # Convolutional rd r c z x
forall (t :: Type -> Type) a. (Foldable t, Num a) => t a -> a
sum ([c # Convolutional rd r c z x] -> c # Convolutional rd r c z x)
-> [c # Convolutional rd r c z x] -> c # Convolutional rd r c z x
forall a b. (a -> b) -> a -> b
$ ((c # z) -> (c # x) -> c # Convolutional rd r c z x)
-> [c # z] -> [c # x] -> [c # Convolutional rd r c z x]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (c # z) -> (c # x) -> c # Convolutional rd r c z x
forall a (rd :: Nat) (r :: Nat) (c :: Nat) z x.
KnownConvolutional rd r c z x =>
(a # z) -> (a # x) -> a # Convolutional rd r c z x
convolutionalOuterProduct [c # z]
ps [c # x]
qs
    {-# INLINE transpose #-}
    transpose :: (c # Convolutional rd r c z x) -> c # Convolutional rd r c x z
transpose = (c # Convolutional rd r c z x) -> c # Convolutional rd r c x z
forall a (rd :: Nat) (r :: Nat) (c :: Nat) z x.
KnownConvolutional rd r c z x =>
(a # Convolutional rd r c z x) -> a # Convolutional rd r c x z
convolveTranspose

instance KnownConvolutional rd r c z x => Propagate a (Convolutional rd r c) z x where
    {-# INLINE propagate #-}
    propagate :: [a #* z]
-> [a #* x]
-> (a # Convolutional rd r c z x)
-> (a #* Convolutional rd r c z x, [a # z])
propagate = [a #* z]
-> [a #* x]
-> (a # Convolutional rd r c z x)
-> (a #* Convolutional rd r c z x, [a # z])
forall a (rd :: Nat) (r :: Nat) (c :: Nat) z x.
KnownConvolutional rd r c z x =>
[a #* z]
-> [a #* x]
-> (a # Convolutional rd r c z x)
-> (a #* Convolutional rd r c z x, [a # z])
convolvePropagate