// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2012, 2013 Chen-Pang He <jdh8@ms63.hinet.net>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef EIGEN_MATRIX_POWER
#define EIGEN_MATRIX_POWER

namespace Eigen {

template<typename MatrixType> class MatrixPower;

/**
 * \ingroup MatrixFunctions_Module
 *
 * \brief Proxy for the matrix power of some matrix.
 *
 * \tparam MatrixType  type of the base, a matrix.
 *
 * This class holds the arguments to the matrix power until it is
 * assigned or evaluated for some other reason (so the argument
 * should not be changed in the meantime). It is the return type of
 * MatrixPower::operator() and related functions and most of the
 * time this is the only way it is used.
 */
/* TODO This class is only used by MatrixPower, so it should be nested
 * into MatrixPower, like MatrixPower::ReturnValue. However, my
 * compiler complained about unused template parameter in the
 * following declaration in namespace internal.
 *
 * template<typename MatrixType>
 * struct traits<MatrixPower<MatrixType>::ReturnValue>;
 */
template<typename MatrixType>
class MatrixPowerParenthesesReturnValue : public ReturnByValue< MatrixPowerParenthesesReturnValue<MatrixType> >
{
  public:
    typedef typename MatrixType::RealScalar RealScalar;

    /**
     * \brief Constructor.
     *
     * \param[in] pow  %MatrixPower storing the base.
     * \param[in] p    scalar, the exponent of the matrix power.
     */
    MatrixPowerParenthesesReturnValue(MatrixPower<MatrixType>& pow, RealScalar p) : m_pow(pow), m_p(p)
    { }

    /**
     * \brief Compute the matrix power.
     *
     * \param[out] result
     */
    template<typename ResultType>
    inline void evalTo(ResultType& result) const
    { m_pow.compute(result, m_p); }

    Index rows() const { return m_pow.rows(); }
    Index cols() const { return m_pow.cols(); }

  private:
    MatrixPower<MatrixType>& m_pow;
    const RealScalar m_p;
};

/**
 * \ingroup MatrixFunctions_Module
 *
 * \brief Class for computing matrix powers.
 *
 * \tparam MatrixType  type of the base, expected to be an instantiation
 * of the Matrix class template.
 *
 * This class is capable of computing triangular real/complex matrices
 * raised to a power in the interval \f$ (-1, 1) \f$.
 *
 * \note Currently this class is only used by MatrixPower. One may
 * insist that this be nested into MatrixPower. This class is here to
 * facilitate future development of triangular matrix functions.
 */
template<typename MatrixType>
class MatrixPowerAtomic : internal::noncopyable
{
  private:
    enum {
      RowsAtCompileTime = MatrixType::RowsAtCompileTime,
      MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
    };
    typedef typename MatrixType::Scalar Scalar;
    typedef typename MatrixType::RealScalar RealScalar;
    typedef std::complex<RealScalar> ComplexScalar;
    typedef Block<MatrixType,Dynamic,Dynamic> ResultType;

    const MatrixType& m_A;
    RealScalar m_p;

    void computePade(int degree, const MatrixType& IminusT, ResultType& res) const;
    void compute2x2(ResultType& res, RealScalar p) const;
    void computeBig(ResultType& res) const;
    static int getPadeDegree(float normIminusT);
    static int getPadeDegree(double normIminusT);
    static int getPadeDegree(long double normIminusT);
    static ComplexScalar computeSuperDiag(const ComplexScalar&, const ComplexScalar&, RealScalar p);
    static RealScalar computeSuperDiag(RealScalar, RealScalar, RealScalar p);

  public:
    /**
     * \brief Constructor.
     *
     * \param[in] T  the base of the matrix power.
     * \param[in] p  the exponent of the matrix power, should be in
     * \f$ (-1, 1) \f$.
     *
     * The class stores a reference to T, so it should not be changed
     * (or destroyed) before evaluation. Only the upper triangular
     * part of T is read.
     */
    MatrixPowerAtomic(const MatrixType& T, RealScalar p);
    
    /**
     * \brief Compute the matrix power.
     *
     * \param[out] res  \f$ A^p \f$ where A and p are specified in the
     * constructor.
     */
    void compute(ResultType& res) const;
};

template<typename MatrixType>
MatrixPowerAtomic<MatrixType>::MatrixPowerAtomic(const MatrixType& T, RealScalar p) :
  m_A(T), m_p(p)
{
  eigen_assert(T.rows() == T.cols());
  eigen_assert(p > -1 && p < 1);
}

template<typename MatrixType>
void MatrixPowerAtomic<MatrixType>::compute(ResultType& res) const
{
  using std::pow;
  switch (m_A.rows()) {
    case 0:
      break;
    case 1:
      res(0,0) = pow(m_A(0,0), m_p);
      break;
    case 2:
      compute2x2(res, m_p);
      break;
    default:
      computeBig(res);
  }
}

template<typename MatrixType>
void MatrixPowerAtomic<MatrixType>::computePade(int degree, const MatrixType& IminusT, ResultType& res) const
{
  int i = 2*degree;
  res = (m_p-RealScalar(degree)) / RealScalar(2*i-2) * IminusT;

  for (--i; i; --i) {
    res = (MatrixType::Identity(IminusT.rows(), IminusT.cols()) + res).template triangularView<Upper>()
	.solve((i==1 ? -m_p : i&1 ? (-m_p-RealScalar(i/2))/RealScalar(2*i) : (m_p-RealScalar(i/2))/RealScalar(2*i-2)) * IminusT).eval();
  }
  res += MatrixType::Identity(IminusT.rows(), IminusT.cols());
}

// This function assumes that res has the correct size (see bug 614)
template<typename MatrixType>
void MatrixPowerAtomic<MatrixType>::compute2x2(ResultType& res, RealScalar p) const
{
  using std::abs;
  using std::pow;
  res.coeffRef(0,0) = pow(m_A.coeff(0,0), p);

  for (Index i=1; i < m_A.cols(); ++i) {
    res.coeffRef(i,i) = pow(m_A.coeff(i,i), p);
    if (m_A.coeff(i-1,i-1) == m_A.coeff(i,i))
      res.coeffRef(i-1,i) = p * pow(m_A.coeff(i,i), p-1);
    else if (2*abs(m_A.coeff(i-1,i-1)) < abs(m_A.coeff(i,i)) || 2*abs(m_A.coeff(i,i)) < abs(m_A.coeff(i-1,i-1)))
      res.coeffRef(i-1,i) = (res.coeff(i,i)-res.coeff(i-1,i-1)) / (m_A.coeff(i,i)-m_A.coeff(i-1,i-1));
    else
      res.coeffRef(i-1,i) = computeSuperDiag(m_A.coeff(i,i), m_A.coeff(i-1,i-1), p);
    res.coeffRef(i-1,i) *= m_A.coeff(i-1,i);
  }
}

template<typename MatrixType>
void MatrixPowerAtomic<MatrixType>::computeBig(ResultType& res) const
{
  using std::ldexp;
  const int digits = std::numeric_limits<RealScalar>::digits;
  const RealScalar maxNormForPade = RealScalar(
                                    digits <=  24? 4.3386528e-1L                            // single precision
                                  : digits <=  53? 2.789358995219730e-1L                    // double precision
                                  : digits <=  64? 2.4471944416607995472e-1L                // extended precision
                                  : digits <= 106? 1.1016843812851143391275867258512e-1L    // double-double
                                  :                9.134603732914548552537150753385375e-2L); // quadruple precision
  MatrixType IminusT, sqrtT, T = m_A.template triangularView<Upper>();
  RealScalar normIminusT;
  int degree, degree2, numberOfSquareRoots = 0;
  bool hasExtraSquareRoot = false;

  for (Index i=0; i < m_A.cols(); ++i)
    eigen_assert(m_A(i,i) != RealScalar(0));

  while (true) {
    IminusT = MatrixType::Identity(m_A.rows(), m_A.cols()) - T;
    normIminusT = IminusT.cwiseAbs().colwise().sum().maxCoeff();
    if (normIminusT < maxNormForPade) {
      degree = getPadeDegree(normIminusT);
      degree2 = getPadeDegree(normIminusT/2);
      if (degree - degree2 <= 1 || hasExtraSquareRoot)
	break;
      hasExtraSquareRoot = true;
    }
    matrix_sqrt_triangular(T, sqrtT);
    T = sqrtT.template triangularView<Upper>();
    ++numberOfSquareRoots;
  }
  computePade(degree, IminusT, res);

  for (; numberOfSquareRoots; --numberOfSquareRoots) {
    compute2x2(res, ldexp(m_p, -numberOfSquareRoots));
    res = res.template triangularView<Upper>() * res;
  }
  compute2x2(res, m_p);
}
  
template<typename MatrixType>
inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(float normIminusT)
{
  const float maxNormForPade[] = { 2.8064004e-1f /* degree = 3 */ , 4.3386528e-1f };
  int degree = 3;
  for (; degree <= 4; ++degree)
    if (normIminusT <= maxNormForPade[degree - 3])
      break;
  return degree;
}

template<typename MatrixType>
inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(double normIminusT)
{
  const double maxNormForPade[] = { 1.884160592658218e-2 /* degree = 3 */ , 6.038881904059573e-2, 1.239917516308172e-1,
      1.999045567181744e-1, 2.789358995219730e-1 };
  int degree = 3;
  for (; degree <= 7; ++degree)
    if (normIminusT <= maxNormForPade[degree - 3])
      break;
  return degree;
}

template<typename MatrixType>
inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(long double normIminusT)
{
#if   LDBL_MANT_DIG == 53
  const int maxPadeDegree = 7;
  const double maxNormForPade[] = { 1.884160592658218e-2L /* degree = 3 */ , 6.038881904059573e-2L, 1.239917516308172e-1L,
      1.999045567181744e-1L, 2.789358995219730e-1L };
#elif LDBL_MANT_DIG <= 64
  const int maxPadeDegree = 8;
  const long double maxNormForPade[] = { 6.3854693117491799460e-3L /* degree = 3 */ , 2.6394893435456973676e-2L,
      6.4216043030404063729e-2L, 1.1701165502926694307e-1L, 1.7904284231268670284e-1L, 2.4471944416607995472e-1L };
#elif LDBL_MANT_DIG <= 106
  const int maxPadeDegree = 10;
  const double maxNormForPade[] = { 1.0007161601787493236741409687186e-4L /* degree = 3 */ ,
      1.0007161601787493236741409687186e-3L, 4.7069769360887572939882574746264e-3L, 1.3220386624169159689406653101695e-2L,
      2.8063482381631737920612944054906e-2L, 4.9625993951953473052385361085058e-2L, 7.7367040706027886224557538328171e-2L,
      1.1016843812851143391275867258512e-1L };
#else
  const int maxPadeDegree = 10;
  const double maxNormForPade[] = { 5.524506147036624377378713555116378e-5L /* degree = 3 */ ,
      6.640600568157479679823602193345995e-4L, 3.227716520106894279249709728084626e-3L,
      9.619593944683432960546978734646284e-3L, 2.134595382433742403911124458161147e-2L,
      3.908166513900489428442993794761185e-2L, 6.266780814639442865832535460550138e-2L,
      9.134603732914548552537150753385375e-2L };
#endif
  int degree = 3;
  for (; degree <= maxPadeDegree; ++degree)
    if (normIminusT <= maxNormForPade[degree - 3])
      break;
  return degree;
}

template<typename MatrixType>
inline typename MatrixPowerAtomic<MatrixType>::ComplexScalar
MatrixPowerAtomic<MatrixType>::computeSuperDiag(const ComplexScalar& curr, const ComplexScalar& prev, RealScalar p)
{
  using std::ceil;
  using std::exp;
  using std::log;
  using std::sinh;

  ComplexScalar logCurr = log(curr);
  ComplexScalar logPrev = log(prev);
  RealScalar unwindingNumber = ceil((numext::imag(logCurr - logPrev) - RealScalar(EIGEN_PI)) / RealScalar(2*EIGEN_PI));
  ComplexScalar w = numext::log1p((curr-prev)/prev)/RealScalar(2) + ComplexScalar(0, RealScalar(EIGEN_PI)*unwindingNumber);
  return RealScalar(2) * exp(RealScalar(0.5) * p * (logCurr + logPrev)) * sinh(p * w) / (curr - prev);
}

template<typename MatrixType>
inline typename MatrixPowerAtomic<MatrixType>::RealScalar
MatrixPowerAtomic<MatrixType>::computeSuperDiag(RealScalar curr, RealScalar prev, RealScalar p)
{
  using std::exp;
  using std::log;
  using std::sinh;

  RealScalar w = numext::log1p((curr-prev)/prev)/RealScalar(2);
  return 2 * exp(p * (log(curr) + log(prev)) / 2) * sinh(p * w) / (curr - prev);
}

/**
 * \ingroup MatrixFunctions_Module
 *
 * \brief Class for computing matrix powers.
 *
 * \tparam MatrixType  type of the base, expected to be an instantiation
 * of the Matrix class template.
 *
 * This class is capable of computing real/complex matrices raised to
 * an arbitrary real power. Meanwhile, it saves the result of Schur
 * decomposition if an non-integral power has even been calculated.
 * Therefore, if you want to compute multiple (>= 2) matrix powers
 * for the same matrix, using the class directly is more efficient than
 * calling MatrixBase::pow().
 *
 * Example:
 * \include MatrixPower_optimal.cpp
 * Output: \verbinclude MatrixPower_optimal.out
 */
template<typename MatrixType>
class MatrixPower : internal::noncopyable
{
  private:
    typedef typename MatrixType::Scalar Scalar;
    typedef typename MatrixType::RealScalar RealScalar;

  public:
    /**
     * \brief Constructor.
     *
     * \param[in] A  the base of the matrix power.
     *
     * The class stores a reference to A, so it should not be changed
     * (or destroyed) before evaluation.
     */
    explicit MatrixPower(const MatrixType& A) :
      m_A(A),
      m_conditionNumber(0),
      m_rank(A.cols()),
      m_nulls(0)
    { eigen_assert(A.rows() == A.cols()); }

    /**
     * \brief Returns the matrix power.
     *
     * \param[in] p  exponent, a real scalar.
     * \return The expression \f$ A^p \f$, where A is specified in the
     * constructor.
     */
    const MatrixPowerParenthesesReturnValue<MatrixType> operator()(RealScalar p)
    { return MatrixPowerParenthesesReturnValue<MatrixType>(*this, p); }

    /**
     * \brief Compute the matrix power.
     *
     * \param[in]  p    exponent, a real scalar.
     * \param[out] res  \f$ A^p \f$ where A is specified in the
     * constructor.
     */
    template<typename ResultType>
    void compute(ResultType& res, RealScalar p);
    
    Index rows() const { return m_A.rows(); }
    Index cols() const { return m_A.cols(); }

  private:
    typedef std::complex<RealScalar> ComplexScalar;
    typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0,
              MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> ComplexMatrix;

    /** \brief Reference to the base of matrix power. */
    typename MatrixType::Nested m_A;

    /** \brief Temporary storage. */
    MatrixType m_tmp;

    /** \brief Store the result of Schur decomposition. */
    ComplexMatrix m_T, m_U;
    
    /** \brief Store fractional power of m_T. */
    ComplexMatrix m_fT;

    /**
     * \brief Condition number of m_A.
     *
     * It is initialized as 0 to avoid performing unnecessary Schur
     * decomposition, which is the bottleneck.
     */
    RealScalar m_conditionNumber;

    /** \brief Rank of m_A. */
    Index m_rank;
    
    /** \brief Rank deficiency of m_A. */
    Index m_nulls;

    /**
     * \brief Split p into integral part and fractional part.
     *
     * \param[in]  p        The exponent.
     * \param[out] p        The fractional part ranging in \f$ (-1, 1) \f$.
     * \param[out] intpart  The integral part.
     *
     * Only if the fractional part is nonzero, it calls initialize().
     */
    void split(RealScalar& p, RealScalar& intpart);

    /** \brief Perform Schur decomposition for fractional power. */
    void initialize();

    template<typename ResultType>
    void computeIntPower(ResultType& res, RealScalar p);

    template<typename ResultType>
    void computeFracPower(ResultType& res, RealScalar p);

    template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    static void revertSchur(
        Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
        const ComplexMatrix& T,
        const ComplexMatrix& U);

    template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    static void revertSchur(
        Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
        const ComplexMatrix& T,
        const ComplexMatrix& U);
};

template<typename MatrixType>
template<typename ResultType>
void MatrixPower<MatrixType>::compute(ResultType& res, RealScalar p)
{
  using std::pow;
  switch (cols()) {
    case 0:
      break;
    case 1:
      res(0,0) = pow(m_A.coeff(0,0), p);
      break;
    default:
      RealScalar intpart;
      split(p, intpart);

      res = MatrixType::Identity(rows(), cols());
      computeIntPower(res, intpart);
      if (p) computeFracPower(res, p);
  }
}

template<typename MatrixType>
void MatrixPower<MatrixType>::split(RealScalar& p, RealScalar& intpart)
{
  using std::floor;
  using std::pow;

  intpart = floor(p);
  p -= intpart;

  // Perform Schur decomposition if it is not yet performed and the power is
  // not an integer.
  if (!m_conditionNumber && p)
    initialize();

  // Choose the more stable of intpart = floor(p) and intpart = ceil(p).
  if (p > RealScalar(0.5) && p > (1-p) * pow(m_conditionNumber, p)) {
    --p;
    ++intpart;
  }
}

template<typename MatrixType>
void MatrixPower<MatrixType>::initialize()
{
  const ComplexSchur<MatrixType> schurOfA(m_A);
  JacobiRotation<ComplexScalar> rot;
  ComplexScalar eigenvalue;

  m_fT.resizeLike(m_A);
  m_T = schurOfA.matrixT();
  m_U = schurOfA.matrixU();
  m_conditionNumber = m_T.diagonal().array().abs().maxCoeff() / m_T.diagonal().array().abs().minCoeff();

  // Move zero eigenvalues to the bottom right corner.
  for (Index i = cols()-1; i>=0; --i) {
    if (m_rank <= 2)
      return;
    if (m_T.coeff(i,i) == RealScalar(0)) {
      for (Index j=i+1; j < m_rank; ++j) {
        eigenvalue = m_T.coeff(j,j);
        rot.makeGivens(m_T.coeff(j-1,j), eigenvalue);
        m_T.applyOnTheRight(j-1, j, rot);
        m_T.applyOnTheLeft(j-1, j, rot.adjoint());
        m_T.coeffRef(j-1,j-1) = eigenvalue;
        m_T.coeffRef(j,j) = RealScalar(0);
        m_U.applyOnTheRight(j-1, j, rot);
      }
      --m_rank;
    }
  }

  m_nulls = rows() - m_rank;
  if (m_nulls) {
    eigen_assert(m_T.bottomRightCorner(m_nulls, m_nulls).isZero()
        && "Base of matrix power should be invertible or with a semisimple zero eigenvalue.");
    m_fT.bottomRows(m_nulls).fill(RealScalar(0));
  }
}

template<typename MatrixType>
template<typename ResultType>
void MatrixPower<MatrixType>::computeIntPower(ResultType& res, RealScalar p)
{
  using std::abs;
  using std::fmod;
  RealScalar pp = abs(p);

  if (p<0) 
    m_tmp = m_A.inverse();
  else     
    m_tmp = m_A;

  while (true) {
    if (fmod(pp, 2) >= 1)
      res = m_tmp * res;
    pp /= 2;
    if (pp < 1)
      break;
    m_tmp *= m_tmp;
  }
}

template<typename MatrixType>
template<typename ResultType>
void MatrixPower<MatrixType>::computeFracPower(ResultType& res, RealScalar p)
{
  Block<ComplexMatrix,Dynamic,Dynamic> blockTp(m_fT, 0, 0, m_rank, m_rank);
  eigen_assert(m_conditionNumber);
  eigen_assert(m_rank + m_nulls == rows());

  MatrixPowerAtomic<ComplexMatrix>(m_T.topLeftCorner(m_rank, m_rank), p).compute(blockTp);
  if (m_nulls) {
    m_fT.topRightCorner(m_rank, m_nulls) = m_T.topLeftCorner(m_rank, m_rank).template triangularView<Upper>()
        .solve(blockTp * m_T.topRightCorner(m_rank, m_nulls));
  }
  revertSchur(m_tmp, m_fT, m_U);
  res = m_tmp * res;
}

template<typename MatrixType>
template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
inline void MatrixPower<MatrixType>::revertSchur(
    Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
    const ComplexMatrix& T,
    const ComplexMatrix& U)
{ res.noalias() = U * (T.template triangularView<Upper>() * U.adjoint()); }

template<typename MatrixType>
template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
inline void MatrixPower<MatrixType>::revertSchur(
    Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
    const ComplexMatrix& T,
    const ComplexMatrix& U)
{ res.noalias() = (U * (T.template triangularView<Upper>() * U.adjoint())).real(); }

/**
 * \ingroup MatrixFunctions_Module
 *
 * \brief Proxy for the matrix power of some matrix (expression).
 *
 * \tparam Derived  type of the base, a matrix (expression).
 *
 * This class holds the arguments to the matrix power until it is
 * assigned or evaluated for some other reason (so the argument
 * should not be changed in the meantime). It is the return type of
 * MatrixBase::pow() and related functions and most of the
 * time this is the only way it is used.
 */
template<typename Derived>
class MatrixPowerReturnValue : public ReturnByValue< MatrixPowerReturnValue<Derived> >
{
  public:
    typedef typename Derived::PlainObject PlainObject;
    typedef typename Derived::RealScalar RealScalar;

    /**
     * \brief Constructor.
     *
     * \param[in] A  %Matrix (expression), the base of the matrix power.
     * \param[in] p  real scalar, the exponent of the matrix power.
     */
    MatrixPowerReturnValue(const Derived& A, RealScalar p) : m_A(A), m_p(p)
    { }

    /**
     * \brief Compute the matrix power.
     *
     * \param[out] result  \f$ A^p \f$ where \p A and \p p are as in the
     * constructor.
     */
    template<typename ResultType>
    inline void evalTo(ResultType& result) const
    { MatrixPower<PlainObject>(m_A.eval()).compute(result, m_p); }

    Index rows() const { return m_A.rows(); }
    Index cols() const { return m_A.cols(); }

  private:
    const Derived& m_A;
    const RealScalar m_p;
};

/**
 * \ingroup MatrixFunctions_Module
 *
 * \brief Proxy for the matrix power of some matrix (expression).
 *
 * \tparam Derived  type of the base, a matrix (expression).
 *
 * This class holds the arguments to the matrix power until it is
 * assigned or evaluated for some other reason (so the argument
 * should not be changed in the meantime). It is the return type of
 * MatrixBase::pow() and related functions and most of the
 * time this is the only way it is used.
 */
template<typename Derived>
class MatrixComplexPowerReturnValue : public ReturnByValue< MatrixComplexPowerReturnValue<Derived> >
{
  public:
    typedef typename Derived::PlainObject PlainObject;
    typedef typename std::complex<typename Derived::RealScalar> ComplexScalar;

    /**
     * \brief Constructor.
     *
     * \param[in] A  %Matrix (expression), the base of the matrix power.
     * \param[in] p  complex scalar, the exponent of the matrix power.
     */
    MatrixComplexPowerReturnValue(const Derived& A, const ComplexScalar& p) : m_A(A), m_p(p)
    { }

    /**
     * \brief Compute the matrix power.
     *
     * Because \p p is complex, \f$ A^p \f$ is simply evaluated as \f$
     * \exp(p \log(A)) \f$.
     *
     * \param[out] result  \f$ A^p \f$ where \p A and \p p are as in the
     * constructor.
     */
    template<typename ResultType>
    inline void evalTo(ResultType& result) const
    { result = (m_p * m_A.log()).exp(); }

    Index rows() const { return m_A.rows(); }
    Index cols() const { return m_A.cols(); }

  private:
    const Derived& m_A;
    const ComplexScalar m_p;
};

namespace internal {

template<typename MatrixPowerType>
struct traits< MatrixPowerParenthesesReturnValue<MatrixPowerType> >
{ typedef typename MatrixPowerType::PlainObject ReturnType; };

template<typename Derived>
struct traits< MatrixPowerReturnValue<Derived> >
{ typedef typename Derived::PlainObject ReturnType; };

template<typename Derived>
struct traits< MatrixComplexPowerReturnValue<Derived> >
{ typedef typename Derived::PlainObject ReturnType; };

}

template<typename Derived>
const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(const RealScalar& p) const
{ return MatrixPowerReturnValue<Derived>(derived(), p); }

template<typename Derived>
const MatrixComplexPowerReturnValue<Derived> MatrixBase<Derived>::pow(const std::complex<RealScalar>& p) const
{ return MatrixComplexPowerReturnValue<Derived>(derived(), p); }

} // namespace Eigen

#endif // EIGEN_MATRIX_POWER
