Home | History | Annotate | Download | only in MatrixFunctions
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2012, 2013 Chen-Pang He <jdh8 (at) ms63.hinet.net>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #ifndef EIGEN_MATRIX_POWER
     11 #define EIGEN_MATRIX_POWER
     12 
     13 namespace Eigen {
     14 
     15 template<typename MatrixType> class MatrixPower;
     16 
     17 /**
     18  * \ingroup MatrixFunctions_Module
     19  *
     20  * \brief Proxy for the matrix power of some matrix.
     21  *
     22  * \tparam MatrixType  type of the base, a matrix.
     23  *
     24  * This class holds the arguments to the matrix power until it is
     25  * assigned or evaluated for some other reason (so the argument
     26  * should not be changed in the meantime). It is the return type of
     27  * MatrixPower::operator() and related functions and most of the
     28  * time this is the only way it is used.
     29  */
     30 /* TODO This class is only used by MatrixPower, so it should be nested
     31  * into MatrixPower, like MatrixPower::ReturnValue. However, my
     32  * compiler complained about unused template parameter in the
     33  * following declaration in namespace internal.
     34  *
     35  * template<typename MatrixType>
     36  * struct traits<MatrixPower<MatrixType>::ReturnValue>;
     37  */
     38 template<typename MatrixType>
     39 class MatrixPowerParenthesesReturnValue : public ReturnByValue< MatrixPowerParenthesesReturnValue<MatrixType> >
     40 {
     41   public:
     42     typedef typename MatrixType::RealScalar RealScalar;
     43     typedef typename MatrixType::Index Index;
     44 
     45     /**
     46      * \brief Constructor.
     47      *
     48      * \param[in] pow  %MatrixPower storing the base.
     49      * \param[in] p    scalar, the exponent of the matrix power.
     50      */
     51     MatrixPowerParenthesesReturnValue(MatrixPower<MatrixType>& pow, RealScalar p) : m_pow(pow), m_p(p)
     52     { }
     53 
     54     /**
     55      * \brief Compute the matrix power.
     56      *
     57      * \param[out] result
     58      */
     59     template<typename ResultType>
     60     inline void evalTo(ResultType& res) const
     61     { m_pow.compute(res, m_p); }
     62 
     63     Index rows() const { return m_pow.rows(); }
     64     Index cols() const { return m_pow.cols(); }
     65 
     66   private:
     67     MatrixPower<MatrixType>& m_pow;
     68     const RealScalar m_p;
     69 };
     70 
     71 /**
     72  * \ingroup MatrixFunctions_Module
     73  *
     74  * \brief Class for computing matrix powers.
     75  *
     76  * \tparam MatrixType  type of the base, expected to be an instantiation
     77  * of the Matrix class template.
     78  *
     79  * This class is capable of computing triangular real/complex matrices
     80  * raised to a power in the interval \f$ (-1, 1) \f$.
     81  *
     82  * \note Currently this class is only used by MatrixPower. One may
     83  * insist that this be nested into MatrixPower. This class is here to
     84  * faciliate future development of triangular matrix functions.
     85  */
     86 template<typename MatrixType>
     87 class MatrixPowerAtomic : internal::noncopyable
     88 {
     89   private:
     90     enum {
     91       RowsAtCompileTime = MatrixType::RowsAtCompileTime,
     92       MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime
     93     };
     94     typedef typename MatrixType::Scalar Scalar;
     95     typedef typename MatrixType::RealScalar RealScalar;
     96     typedef std::complex<RealScalar> ComplexScalar;
     97     typedef typename MatrixType::Index Index;
     98     typedef Block<MatrixType,Dynamic,Dynamic> ResultType;
     99 
    100     const MatrixType& m_A;
    101     RealScalar m_p;
    102 
    103     void computePade(int degree, const MatrixType& IminusT, ResultType& res) const;
    104     void compute2x2(ResultType& res, RealScalar p) const;
    105     void computeBig(ResultType& res) const;
    106     static int getPadeDegree(float normIminusT);
    107     static int getPadeDegree(double normIminusT);
    108     static int getPadeDegree(long double normIminusT);
    109     static ComplexScalar computeSuperDiag(const ComplexScalar&, const ComplexScalar&, RealScalar p);
    110     static RealScalar computeSuperDiag(RealScalar, RealScalar, RealScalar p);
    111 
    112   public:
    113     /**
    114      * \brief Constructor.
    115      *
    116      * \param[in] T  the base of the matrix power.
    117      * \param[in] p  the exponent of the matrix power, should be in
    118      * \f$ (-1, 1) \f$.
    119      *
    120      * The class stores a reference to T, so it should not be changed
    121      * (or destroyed) before evaluation. Only the upper triangular
    122      * part of T is read.
    123      */
    124     MatrixPowerAtomic(const MatrixType& T, RealScalar p);
    125 
    126     /**
    127      * \brief Compute the matrix power.
    128      *
    129      * \param[out] res  \f$ A^p \f$ where A and p are specified in the
    130      * constructor.
    131      */
    132     void compute(ResultType& res) const;
    133 };
    134 
    135 template<typename MatrixType>
    136 MatrixPowerAtomic<MatrixType>::MatrixPowerAtomic(const MatrixType& T, RealScalar p) :
    137   m_A(T), m_p(p)
    138 {
    139   eigen_assert(T.rows() == T.cols());
    140   eigen_assert(p > -1 && p < 1);
    141 }
    142 
    143 template<typename MatrixType>
    144 void MatrixPowerAtomic<MatrixType>::compute(ResultType& res) const
    145 {
    146   using std::pow;
    147   switch (m_A.rows()) {
    148     case 0:
    149       break;
    150     case 1:
    151       res(0,0) = pow(m_A(0,0), m_p);
    152       break;
    153     case 2:
    154       compute2x2(res, m_p);
    155       break;
    156     default:
    157       computeBig(res);
    158   }
    159 }
    160 
    161 template<typename MatrixType>
    162 void MatrixPowerAtomic<MatrixType>::computePade(int degree, const MatrixType& IminusT, ResultType& res) const
    163 {
    164   int i = 2*degree;
    165   res = (m_p-degree) / (2*i-2) * IminusT;
    166 
    167   for (--i; i; --i) {
    168     res = (MatrixType::Identity(IminusT.rows(), IminusT.cols()) + res).template triangularView<Upper>()
    169 	.solve((i==1 ? -m_p : i&1 ? (-m_p-i/2)/(2*i) : (m_p-i/2)/(2*i-2)) * IminusT).eval();
    170   }
    171   res += MatrixType::Identity(IminusT.rows(), IminusT.cols());
    172 }
    173 
    174 // This function assumes that res has the correct size (see bug 614)
    175 template<typename MatrixType>
    176 void MatrixPowerAtomic<MatrixType>::compute2x2(ResultType& res, RealScalar p) const
    177 {
    178   using std::abs;
    179   using std::pow;
    180   res.coeffRef(0,0) = pow(m_A.coeff(0,0), p);
    181 
    182   for (Index i=1; i < m_A.cols(); ++i) {
    183     res.coeffRef(i,i) = pow(m_A.coeff(i,i), p);
    184     if (m_A.coeff(i-1,i-1) == m_A.coeff(i,i))
    185       res.coeffRef(i-1,i) = p * pow(m_A.coeff(i,i), p-1);
    186     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)))
    187       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));
    188     else
    189       res.coeffRef(i-1,i) = computeSuperDiag(m_A.coeff(i,i), m_A.coeff(i-1,i-1), p);
    190     res.coeffRef(i-1,i) *= m_A.coeff(i-1,i);
    191   }
    192 }
    193 
    194 template<typename MatrixType>
    195 void MatrixPowerAtomic<MatrixType>::computeBig(ResultType& res) const
    196 {
    197   using std::ldexp;
    198   const int digits = std::numeric_limits<RealScalar>::digits;
    199   const RealScalar maxNormForPade = digits <=  24? 4.3386528e-1L                            // single precision
    200                                   : digits <=  53? 2.789358995219730e-1L                    // double precision
    201                                   : digits <=  64? 2.4471944416607995472e-1L                // extended precision
    202                                   : digits <= 106? 1.1016843812851143391275867258512e-1L    // double-double
    203                                   :                9.134603732914548552537150753385375e-2L; // quadruple precision
    204   MatrixType IminusT, sqrtT, T = m_A.template triangularView<Upper>();
    205   RealScalar normIminusT;
    206   int degree, degree2, numberOfSquareRoots = 0;
    207   bool hasExtraSquareRoot = false;
    208 
    209   for (Index i=0; i < m_A.cols(); ++i)
    210     eigen_assert(m_A(i,i) != RealScalar(0));
    211 
    212   while (true) {
    213     IminusT = MatrixType::Identity(m_A.rows(), m_A.cols()) - T;
    214     normIminusT = IminusT.cwiseAbs().colwise().sum().maxCoeff();
    215     if (normIminusT < maxNormForPade) {
    216       degree = getPadeDegree(normIminusT);
    217       degree2 = getPadeDegree(normIminusT/2);
    218       if (degree - degree2 <= 1 || hasExtraSquareRoot)
    219 	break;
    220       hasExtraSquareRoot = true;
    221     }
    222     matrix_sqrt_triangular(T, sqrtT);
    223     T = sqrtT.template triangularView<Upper>();
    224     ++numberOfSquareRoots;
    225   }
    226   computePade(degree, IminusT, res);
    227 
    228   for (; numberOfSquareRoots; --numberOfSquareRoots) {
    229     compute2x2(res, ldexp(m_p, -numberOfSquareRoots));
    230     res = res.template triangularView<Upper>() * res;
    231   }
    232   compute2x2(res, m_p);
    233 }
    234 
    235 template<typename MatrixType>
    236 inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(float normIminusT)
    237 {
    238   const float maxNormForPade[] = { 2.8064004e-1f /* degree = 3 */ , 4.3386528e-1f };
    239   int degree = 3;
    240   for (; degree <= 4; ++degree)
    241     if (normIminusT <= maxNormForPade[degree - 3])
    242       break;
    243   return degree;
    244 }
    245 
    246 template<typename MatrixType>
    247 inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(double normIminusT)
    248 {
    249   const double maxNormForPade[] = { 1.884160592658218e-2 /* degree = 3 */ , 6.038881904059573e-2, 1.239917516308172e-1,
    250       1.999045567181744e-1, 2.789358995219730e-1 };
    251   int degree = 3;
    252   for (; degree <= 7; ++degree)
    253     if (normIminusT <= maxNormForPade[degree - 3])
    254       break;
    255   return degree;
    256 }
    257 
    258 template<typename MatrixType>
    259 inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(long double normIminusT)
    260 {
    261 #if   LDBL_MANT_DIG == 53
    262   const int maxPadeDegree = 7;
    263   const double maxNormForPade[] = { 1.884160592658218e-2L /* degree = 3 */ , 6.038881904059573e-2L, 1.239917516308172e-1L,
    264       1.999045567181744e-1L, 2.789358995219730e-1L };
    265 #elif LDBL_MANT_DIG <= 64
    266   const int maxPadeDegree = 8;
    267   const long double maxNormForPade[] = { 6.3854693117491799460e-3L /* degree = 3 */ , 2.6394893435456973676e-2L,
    268       6.4216043030404063729e-2L, 1.1701165502926694307e-1L, 1.7904284231268670284e-1L, 2.4471944416607995472e-1L };
    269 #elif LDBL_MANT_DIG <= 106
    270   const int maxPadeDegree = 10;
    271   const double maxNormForPade[] = { 1.0007161601787493236741409687186e-4L /* degree = 3 */ ,
    272       1.0007161601787493236741409687186e-3L, 4.7069769360887572939882574746264e-3L, 1.3220386624169159689406653101695e-2L,
    273       2.8063482381631737920612944054906e-2L, 4.9625993951953473052385361085058e-2L, 7.7367040706027886224557538328171e-2L,
    274       1.1016843812851143391275867258512e-1L };
    275 #else
    276   const int maxPadeDegree = 10;
    277   const double maxNormForPade[] = { 5.524506147036624377378713555116378e-5L /* degree = 3 */ ,
    278       6.640600568157479679823602193345995e-4L, 3.227716520106894279249709728084626e-3L,
    279       9.619593944683432960546978734646284e-3L, 2.134595382433742403911124458161147e-2L,
    280       3.908166513900489428442993794761185e-2L, 6.266780814639442865832535460550138e-2L,
    281       9.134603732914548552537150753385375e-2L };
    282 #endif
    283   int degree = 3;
    284   for (; degree <= maxPadeDegree; ++degree)
    285     if (normIminusT <= maxNormForPade[degree - 3])
    286       break;
    287   return degree;
    288 }
    289 
    290 template<typename MatrixType>
    291 inline typename MatrixPowerAtomic<MatrixType>::ComplexScalar
    292 MatrixPowerAtomic<MatrixType>::computeSuperDiag(const ComplexScalar& curr, const ComplexScalar& prev, RealScalar p)
    293 {
    294   using std::ceil;
    295   using std::exp;
    296   using std::log;
    297   using std::sinh;
    298 
    299   ComplexScalar logCurr = log(curr);
    300   ComplexScalar logPrev = log(prev);
    301   int unwindingNumber = ceil((numext::imag(logCurr - logPrev) - RealScalar(EIGEN_PI)) / RealScalar(2*EIGEN_PI));
    302   ComplexScalar w = numext::log1p((curr-prev)/prev)/RealScalar(2) + ComplexScalar(0, EIGEN_PI*unwindingNumber);
    303   return RealScalar(2) * exp(RealScalar(0.5) * p * (logCurr + logPrev)) * sinh(p * w) / (curr - prev);
    304 }
    305 
    306 template<typename MatrixType>
    307 inline typename MatrixPowerAtomic<MatrixType>::RealScalar
    308 MatrixPowerAtomic<MatrixType>::computeSuperDiag(RealScalar curr, RealScalar prev, RealScalar p)
    309 {
    310   using std::exp;
    311   using std::log;
    312   using std::sinh;
    313 
    314   RealScalar w = numext::log1p((curr-prev)/prev)/RealScalar(2);
    315   return 2 * exp(p * (log(curr) + log(prev)) / 2) * sinh(p * w) / (curr - prev);
    316 }
    317 
    318 /**
    319  * \ingroup MatrixFunctions_Module
    320  *
    321  * \brief Class for computing matrix powers.
    322  *
    323  * \tparam MatrixType  type of the base, expected to be an instantiation
    324  * of the Matrix class template.
    325  *
    326  * This class is capable of computing real/complex matrices raised to
    327  * an arbitrary real power. Meanwhile, it saves the result of Schur
    328  * decomposition if an non-integral power has even been calculated.
    329  * Therefore, if you want to compute multiple (>= 2) matrix powers
    330  * for the same matrix, using the class directly is more efficient than
    331  * calling MatrixBase::pow().
    332  *
    333  * Example:
    334  * \include MatrixPower_optimal.cpp
    335  * Output: \verbinclude MatrixPower_optimal.out
    336  */
    337 template<typename MatrixType>
    338 class MatrixPower : internal::noncopyable
    339 {
    340   private:
    341     typedef typename MatrixType::Scalar Scalar;
    342     typedef typename MatrixType::RealScalar RealScalar;
    343     typedef typename MatrixType::Index Index;
    344 
    345   public:
    346     /**
    347      * \brief Constructor.
    348      *
    349      * \param[in] A  the base of the matrix power.
    350      *
    351      * The class stores a reference to A, so it should not be changed
    352      * (or destroyed) before evaluation.
    353      */
    354     explicit MatrixPower(const MatrixType& A) :
    355       m_A(A),
    356       m_conditionNumber(0),
    357       m_rank(A.cols()),
    358       m_nulls(0)
    359     { eigen_assert(A.rows() == A.cols()); }
    360 
    361     /**
    362      * \brief Returns the matrix power.
    363      *
    364      * \param[in] p  exponent, a real scalar.
    365      * \return The expression \f$ A^p \f$, where A is specified in the
    366      * constructor.
    367      */
    368     const MatrixPowerParenthesesReturnValue<MatrixType> operator()(RealScalar p)
    369     { return MatrixPowerParenthesesReturnValue<MatrixType>(*this, p); }
    370 
    371     /**
    372      * \brief Compute the matrix power.
    373      *
    374      * \param[in]  p    exponent, a real scalar.
    375      * \param[out] res  \f$ A^p \f$ where A is specified in the
    376      * constructor.
    377      */
    378     template<typename ResultType>
    379     void compute(ResultType& res, RealScalar p);
    380 
    381     Index rows() const { return m_A.rows(); }
    382     Index cols() const { return m_A.cols(); }
    383 
    384   private:
    385     typedef std::complex<RealScalar> ComplexScalar;
    386     typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0,
    387               MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime> ComplexMatrix;
    388 
    389     /** \brief Reference to the base of matrix power. */
    390     typename MatrixType::Nested m_A;
    391 
    392     /** \brief Temporary storage. */
    393     MatrixType m_tmp;
    394 
    395     /** \brief Store the result of Schur decomposition. */
    396     ComplexMatrix m_T, m_U;
    397 
    398     /** \brief Store fractional power of m_T. */
    399     ComplexMatrix m_fT;
    400 
    401     /**
    402      * \brief Condition number of m_A.
    403      *
    404      * It is initialized as 0 to avoid performing unnecessary Schur
    405      * decomposition, which is the bottleneck.
    406      */
    407     RealScalar m_conditionNumber;
    408 
    409     /** \brief Rank of m_A. */
    410     Index m_rank;
    411 
    412     /** \brief Rank deficiency of m_A. */
    413     Index m_nulls;
    414 
    415     /**
    416      * \brief Split p into integral part and fractional part.
    417      *
    418      * \param[in]  p        The exponent.
    419      * \param[out] p        The fractional part ranging in \f$ (-1, 1) \f$.
    420      * \param[out] intpart  The integral part.
    421      *
    422      * Only if the fractional part is nonzero, it calls initialize().
    423      */
    424     void split(RealScalar& p, RealScalar& intpart);
    425 
    426     /** \brief Perform Schur decomposition for fractional power. */
    427     void initialize();
    428 
    429     template<typename ResultType>
    430     void computeIntPower(ResultType& res, RealScalar p);
    431 
    432     template<typename ResultType>
    433     void computeFracPower(ResultType& res, RealScalar p);
    434 
    435     template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    436     static void revertSchur(
    437         Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
    438         const ComplexMatrix& T,
    439         const ComplexMatrix& U);
    440 
    441     template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    442     static void revertSchur(
    443         Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
    444         const ComplexMatrix& T,
    445         const ComplexMatrix& U);
    446 };
    447 
    448 template<typename MatrixType>
    449 template<typename ResultType>
    450 void MatrixPower<MatrixType>::compute(ResultType& res, RealScalar p)
    451 {
    452   using std::pow;
    453   switch (cols()) {
    454     case 0:
    455       break;
    456     case 1:
    457       res(0,0) = pow(m_A.coeff(0,0), p);
    458       break;
    459     default:
    460       RealScalar intpart;
    461       split(p, intpart);
    462 
    463       res = MatrixType::Identity(rows(), cols());
    464       computeIntPower(res, intpart);
    465       if (p) computeFracPower(res, p);
    466   }
    467 }
    468 
    469 template<typename MatrixType>
    470 void MatrixPower<MatrixType>::split(RealScalar& p, RealScalar& intpart)
    471 {
    472   using std::floor;
    473   using std::pow;
    474 
    475   intpart = floor(p);
    476   p -= intpart;
    477 
    478   // Perform Schur decomposition if it is not yet performed and the power is
    479   // not an integer.
    480   if (!m_conditionNumber && p)
    481     initialize();
    482 
    483   // Choose the more stable of intpart = floor(p) and intpart = ceil(p).
    484   if (p > RealScalar(0.5) && p > (1-p) * pow(m_conditionNumber, p)) {
    485     --p;
    486     ++intpart;
    487   }
    488 }
    489 
    490 template<typename MatrixType>
    491 void MatrixPower<MatrixType>::initialize()
    492 {
    493   const ComplexSchur<MatrixType> schurOfA(m_A);
    494   JacobiRotation<ComplexScalar> rot;
    495   ComplexScalar eigenvalue;
    496 
    497   m_fT.resizeLike(m_A);
    498   m_T = schurOfA.matrixT();
    499   m_U = schurOfA.matrixU();
    500   m_conditionNumber = m_T.diagonal().array().abs().maxCoeff() / m_T.diagonal().array().abs().minCoeff();
    501 
    502   // Move zero eigenvalues to the bottom right corner.
    503   for (Index i = cols()-1; i>=0; --i) {
    504     if (m_rank <= 2)
    505       return;
    506     if (m_T.coeff(i,i) == RealScalar(0)) {
    507       for (Index j=i+1; j < m_rank; ++j) {
    508         eigenvalue = m_T.coeff(j,j);
    509         rot.makeGivens(m_T.coeff(j-1,j), eigenvalue);
    510         m_T.applyOnTheRight(j-1, j, rot);
    511         m_T.applyOnTheLeft(j-1, j, rot.adjoint());
    512         m_T.coeffRef(j-1,j-1) = eigenvalue;
    513         m_T.coeffRef(j,j) = RealScalar(0);
    514         m_U.applyOnTheRight(j-1, j, rot);
    515       }
    516       --m_rank;
    517     }
    518   }
    519 
    520   m_nulls = rows() - m_rank;
    521   if (m_nulls) {
    522     eigen_assert(m_T.bottomRightCorner(m_nulls, m_nulls).isZero()
    523         && "Base of matrix power should be invertible or with a semisimple zero eigenvalue.");
    524     m_fT.bottomRows(m_nulls).fill(RealScalar(0));
    525   }
    526 }
    527 
    528 template<typename MatrixType>
    529 template<typename ResultType>
    530 void MatrixPower<MatrixType>::computeIntPower(ResultType& res, RealScalar p)
    531 {
    532   using std::abs;
    533   using std::fmod;
    534   RealScalar pp = abs(p);
    535 
    536   if (p<0)
    537     m_tmp = m_A.inverse();
    538   else
    539     m_tmp = m_A;
    540 
    541   while (true) {
    542     if (fmod(pp, 2) >= 1)
    543       res = m_tmp * res;
    544     pp /= 2;
    545     if (pp < 1)
    546       break;
    547     m_tmp *= m_tmp;
    548   }
    549 }
    550 
    551 template<typename MatrixType>
    552 template<typename ResultType>
    553 void MatrixPower<MatrixType>::computeFracPower(ResultType& res, RealScalar p)
    554 {
    555   Block<ComplexMatrix,Dynamic,Dynamic> blockTp(m_fT, 0, 0, m_rank, m_rank);
    556   eigen_assert(m_conditionNumber);
    557   eigen_assert(m_rank + m_nulls == rows());
    558 
    559   MatrixPowerAtomic<ComplexMatrix>(m_T.topLeftCorner(m_rank, m_rank), p).compute(blockTp);
    560   if (m_nulls) {
    561     m_fT.topRightCorner(m_rank, m_nulls) = m_T.topLeftCorner(m_rank, m_rank).template triangularView<Upper>()
    562         .solve(blockTp * m_T.topRightCorner(m_rank, m_nulls));
    563   }
    564   revertSchur(m_tmp, m_fT, m_U);
    565   res = m_tmp * res;
    566 }
    567 
    568 template<typename MatrixType>
    569 template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    570 inline void MatrixPower<MatrixType>::revertSchur(
    571     Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
    572     const ComplexMatrix& T,
    573     const ComplexMatrix& U)
    574 { res.noalias() = U * (T.template triangularView<Upper>() * U.adjoint()); }
    575 
    576 template<typename MatrixType>
    577 template<int Rows, int Cols, int Options, int MaxRows, int MaxCols>
    578 inline void MatrixPower<MatrixType>::revertSchur(
    579     Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
    580     const ComplexMatrix& T,
    581     const ComplexMatrix& U)
    582 { res.noalias() = (U * (T.template triangularView<Upper>() * U.adjoint())).real(); }
    583 
    584 /**
    585  * \ingroup MatrixFunctions_Module
    586  *
    587  * \brief Proxy for the matrix power of some matrix (expression).
    588  *
    589  * \tparam Derived  type of the base, a matrix (expression).
    590  *
    591  * This class holds the arguments to the matrix power until it is
    592  * assigned or evaluated for some other reason (so the argument
    593  * should not be changed in the meantime). It is the return type of
    594  * MatrixBase::pow() and related functions and most of the
    595  * time this is the only way it is used.
    596  */
    597 template<typename Derived>
    598 class MatrixPowerReturnValue : public ReturnByValue< MatrixPowerReturnValue<Derived> >
    599 {
    600   public:
    601     typedef typename Derived::PlainObject PlainObject;
    602     typedef typename Derived::RealScalar RealScalar;
    603     typedef typename Derived::Index Index;
    604 
    605     /**
    606      * \brief Constructor.
    607      *
    608      * \param[in] A  %Matrix (expression), the base of the matrix power.
    609      * \param[in] p  real scalar, the exponent of the matrix power.
    610      */
    611     MatrixPowerReturnValue(const Derived& A, RealScalar p) : m_A(A), m_p(p)
    612     { }
    613 
    614     /**
    615      * \brief Compute the matrix power.
    616      *
    617      * \param[out] result  \f$ A^p \f$ where \p A and \p p are as in the
    618      * constructor.
    619      */
    620     template<typename ResultType>
    621     inline void evalTo(ResultType& res) const
    622     { MatrixPower<PlainObject>(m_A.eval()).compute(res, m_p); }
    623 
    624     Index rows() const { return m_A.rows(); }
    625     Index cols() const { return m_A.cols(); }
    626 
    627   private:
    628     const Derived& m_A;
    629     const RealScalar m_p;
    630 };
    631 
    632 /**
    633  * \ingroup MatrixFunctions_Module
    634  *
    635  * \brief Proxy for the matrix power of some matrix (expression).
    636  *
    637  * \tparam Derived  type of the base, a matrix (expression).
    638  *
    639  * This class holds the arguments to the matrix power until it is
    640  * assigned or evaluated for some other reason (so the argument
    641  * should not be changed in the meantime). It is the return type of
    642  * MatrixBase::pow() and related functions and most of the
    643  * time this is the only way it is used.
    644  */
    645 template<typename Derived>
    646 class MatrixComplexPowerReturnValue : public ReturnByValue< MatrixComplexPowerReturnValue<Derived> >
    647 {
    648   public:
    649     typedef typename Derived::PlainObject PlainObject;
    650     typedef typename std::complex<typename Derived::RealScalar> ComplexScalar;
    651     typedef typename Derived::Index Index;
    652 
    653     /**
    654      * \brief Constructor.
    655      *
    656      * \param[in] A  %Matrix (expression), the base of the matrix power.
    657      * \param[in] p  complex scalar, the exponent of the matrix power.
    658      */
    659     MatrixComplexPowerReturnValue(const Derived& A, const ComplexScalar& p) : m_A(A), m_p(p)
    660     { }
    661 
    662     /**
    663      * \brief Compute the matrix power.
    664      *
    665      * Because \p p is complex, \f$ A^p \f$ is simply evaluated as \f$
    666      * \exp(p \log(A)) \f$.
    667      *
    668      * \param[out] result  \f$ A^p \f$ where \p A and \p p are as in the
    669      * constructor.
    670      */
    671     template<typename ResultType>
    672     inline void evalTo(ResultType& res) const
    673     { res = (m_p * m_A.log()).exp(); }
    674 
    675     Index rows() const { return m_A.rows(); }
    676     Index cols() const { return m_A.cols(); }
    677 
    678   private:
    679     const Derived& m_A;
    680     const ComplexScalar m_p;
    681 };
    682 
    683 namespace internal {
    684 
    685 template<typename MatrixPowerType>
    686 struct traits< MatrixPowerParenthesesReturnValue<MatrixPowerType> >
    687 { typedef typename MatrixPowerType::PlainObject ReturnType; };
    688 
    689 template<typename Derived>
    690 struct traits< MatrixPowerReturnValue<Derived> >
    691 { typedef typename Derived::PlainObject ReturnType; };
    692 
    693 template<typename Derived>
    694 struct traits< MatrixComplexPowerReturnValue<Derived> >
    695 { typedef typename Derived::PlainObject ReturnType; };
    696 
    697 }
    698 
    699 template<typename Derived>
    700 const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(const RealScalar& p) const
    701 { return MatrixPowerReturnValue<Derived>(derived(), p); }
    702 
    703 template<typename Derived>
    704 const MatrixComplexPowerReturnValue<Derived> MatrixBase<Derived>::pow(const std::complex<RealScalar>& p) const
    705 { return MatrixComplexPowerReturnValue<Derived>(derived(), p); }
    706 
    707 } // namespace Eigen
    708 
    709 #endif // EIGEN_MATRIX_POWER
    710