cart-elc

Source code for CART-ELC
git clone git://git.laack.co/cart-elc.git
Log | Files | Refs | README | LICENSE

MatrixPower.h (23422B)


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