#ifndef LAYER_CONVOLUTION_HPP
#define LAYER_CONVOLUTION_HPP

#include <random>
#include "layer.hpp"

namespace Layer{
  /*****************************************
   * Implementation of a convolutionnal Layer

   */
  class Convolution:public Layer{
  public:
    size_t nf,ni,nj;
    size_t mf,mi,mj;
    size_t p,q;
    Vector K;
    Vector b;
    Vector nabla_K;
    Vector nabla_b;
  public:
    Convolution(size_t nf,size_t ni,size_t nj,size_t p,size_t q,size_t mf);
    ~Convolution();
    void init(Real m,Real d);
    Vector feed_forward(Vector x);
    void init_nabla();
    Vector back_propagation(Vector d);
    void update(Real eta);
  };

  inline Convolution::Convolution(size_t nf_,size_t ni_,size_t nj_,size_t p_,size_t q_,size_t mf_):Layer(nf_*ni_*nj_,mf_*(ni_-p_+1)*(nj_-q_+1)){
    nf=nf_;
    ni=ni_;
    nj=nj_;
    p=p_;
    q=q_;
    mf=mf_;
    mi=ni-p+1;
    mj=nj-q+1;
    K=init_vector(mf*nf*p*q);
    b=init_vector(mf*nf);
    nabla_K=init_vector(mf*nf*p*q);
    nabla_b=init_vector(mf*nf);
  }

  inline
  Convolution::~Convolution(){
    delete_vector(K);
    delete_vector(b);
    delete_vector(nabla_K);
    delete_vector(nabla_b);
  }
}
#endif
