// 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/.
// SPDX-License-Identifier: MPL-2.0

#ifndef EIGEN_MATRIX_POWER
#define EIGEN_MATRIX_POWER

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

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 {
 private:
  enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime };
  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::RealScalar RealScalar;
  typedef internal::make_complex_t<Scalar> 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:
  MatrixPowerAtomic(const MatrixPowerAtomic&) = delete;
  MatrixPowerAtomic& operator=(const MatrixPowerAtomic&) = delete;

  /**
   * \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);
    Scalar a = m_A.coeff(i - 1, i - 1);
    Scalar b = m_A.coeff(i, i);
    Scalar diff = b - a;
    // Use the derivative formula when eigenvalues are nearly equal to avoid
    // catastrophic cancellation in the difference quotient.
    if (abs(diff) <= RealScalar(2) * (std::numeric_limits<RealScalar>::epsilon)() * (std::max)(abs(a), abs(b)))
      res.coeffRef(i - 1, i) = p * pow(b, p - 1);
    else if (2 * abs(a) < abs(b) || 2 * abs(b) < abs(a))
      res.coeffRef(i - 1, i) = (res.coeff(i, i) - res.coeff(i - 1, i - 1)) / diff;
    else
      res.coeffRef(i - 1, i) = computeSuperDiag(b, a, 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 <= static_cast<long double>(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 {
 private:
  typedef typename MatrixType::Scalar Scalar;
  typedef typename MatrixType::RealScalar RealScalar;

 public:
  MatrixPower(const MatrixPower&) = delete;
  MatrixPower& operator=(const MatrixPower&) = delete;

  /**
   * \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 internal::make_complex_t<Scalar> 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 internal::make_complex_t<typename Derived::Scalar> 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;
};

}  // namespace internal

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 internal::make_complex_t<Scalar>& p) const {
  return MatrixComplexPowerReturnValue<Derived>(derived(), p);
}

}  // namespace Eigen

#endif  // EIGEN_MATRIX_POWER
