#ifndef STAN_MATH_PRIM_MAT_FUN_MATRIX_EXP_PADE_HPP
#define STAN_MATH_PRIM_MAT_FUN_MATRIX_EXP_PADE_HPP

#include <stan/math/prim/mat/fun/MatrixExponential.h>

namespace stan {
  namespace math {

    /**
     * Computes the matrix exponential, using a Pade
     * approximation, coupled with scaling and
     * squaring.
     *
     * @tparam MatrixType scalar type of the elements
     * in the input matrix.
     * @param[in] arg matrix to exponentiate.
     * @return Matrix exponential of input matrix.
     */
    template <typename MatrixType>
    MatrixType
    matrix_exp_pade(const MatrixType& arg) {
      MatrixType U, V;
      int squarings;
      Eigen::matrix_exp_computeUV<MatrixType>::run(arg, U, V, squarings,
                                                   arg(0, 0));
      // Pade approximant is
      // (U+V) / (-U+V)
      MatrixType numer = U + V;
      MatrixType denom = -U + V;
      MatrixType pade_approximation = denom.partialPivLu().solve(numer);
      for (int i = 0; i < squarings; ++i)
        pade_approximation *= pade_approximation;  // undo scaling by
                                                   // repeated squaring
      return pade_approximation;
    }
  }
}
#endif
