void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output) { arma::mat maxInput = arma::repmat(arma::max(input), input.n_rows, 1); output = (maxInput - input); // Approximation of the hyperbolic tangent. The acuracy however is // about 0.00001 lower as using tanh. Credits go to Leon Bottou. output.transform( [](double x) { //! Fast approximation of exp(-x) for x positive. static constexpr double A0 = 1.0; static constexpr double A1 = 0.125; static constexpr double A2 = 0.0078125; static constexpr double A3 = 0.00032552083; static constexpr double A4 = 1.0172526e-5; if (x < 13.0) { double y = A0 + x * (A1 + x * (A2 + x * (A3 + x * A4))); y *= y; y *= y; y *= y; y = 1 / y; return y; } return 0.0; } ); output = input - (maxInput + std::log(arma::accu(output))); }
void Fn(const arma::Mat<eT>& x, arma::Mat<eT>& y) { y = x; y.transform( [&](eT val) { return std::min( std::max( val, minValue ), maxValue ); } ); }