#ifndef LAYER_ACTIVATION_HPP
#define LAYER_ACTIVATION_HPP

#include "layer.hpp"
#include "math.hpp"

namespace Layer{
  enum ActivationMap{Sigmoid};

  template<ActivationMap A> Real activation_map(Real);
  template<ActivationMap A> Real activation_diff_map(Real);

  template<> Real activation_map<Sigmoid>(Real);
  template<> Real activation_diff_map<Sigmoid>(Real);

  template<ActivationMap A> class Activation:public Layer{
  private:
    using Layer::x_out;
  public:
    Activation(size_t n);
    Vector feed_forward(Vector x);
    void init_nabla(){};
    Vector back_propagation(Vector d);
    void update(Real){};
  };

  template<ActivationMap A>
  inline
  Activation<A>::Activation(size_t n):Layer(n,n){
  }

  template<ActivationMap A>
  inline Vector
  Activation<A>::feed_forward(Vector x){
    x_in=x;
    for(size_t i=0;i<n_in;++i){
      x_out[i]=activation_map<A>(x[i]);
    }
    return x_out;
  }

  template<ActivationMap A>
  inline Vector
  Activation<A>::back_propagation(Vector d){
    for(size_t i=0;i<n_in;++i){
      delta[i]=activation_diff_map<A>(x_in[i])*d[i];
    }
    return delta;
  }

  template<>
  Real
  activation_map<Sigmoid>(Real x){
    return 1.0/(1.0+exp(-x));
  }

  template<>
  Real
  activation_diff_map<Sigmoid>(Real x){
    Real t=activation_map<Sigmoid>(x);
    return t*(1.0-t);
  }
}
#endif
