WPILibC++ 2024.3.2
MatrixPower.h
Go to the documentation of this file.
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// IWYU pragma: private
15
16namespace Eigen {
17
18template <typename MatrixType>
19class MatrixPower;
20
21/**
22 * \ingroup MatrixFunctions_Module
23 *
24 * \brief Proxy for the matrix power of some matrix.
25 *
26 * \tparam MatrixType type of the base, a matrix.
27 *
28 * This class holds the arguments to the matrix power until it is
29 * assigned or evaluated for some other reason (so the argument
30 * should not be changed in the meantime). It is the return type of
31 * MatrixPower::operator() and related functions and most of the
32 * time this is the only way it is used.
33 */
34/* TODO This class is only used by MatrixPower, so it should be nested
35 * into MatrixPower, like MatrixPower::ReturnValue. However, my
36 * compiler complained about unused template parameter in the
37 * following declaration in namespace internal.
38 *
39 * template<typename MatrixType>
40 * struct traits<MatrixPower<MatrixType>::ReturnValue>;
41 */
42template <typename MatrixType>
43class MatrixPowerParenthesesReturnValue : public ReturnByValue<MatrixPowerParenthesesReturnValue<MatrixType> > {
44 public:
45 typedef typename MatrixType::RealScalar RealScalar;
46
47 /**
48 * \brief Constructor.
49 *
50 * \param[in] pow %MatrixPower storing the base.
51 * \param[in] p scalar, the exponent of the matrix power.
52 */
54
55 /**
56 * \brief Compute the matrix power.
57 *
58 * \param[out] result
59 */
60 template <typename ResultType>
61 inline void evalTo(ResultType& result) const {
62 m_pow.compute(result, m_p);
63 }
64
65 Index rows() const { return m_pow.rows(); }
66 Index cols() const { return m_pow.cols(); }
67
68 private:
70 const RealScalar m_p;
71};
72
73/**
74 * \ingroup MatrixFunctions_Module
75 *
76 * \brief Class for computing matrix powers.
77 *
78 * \tparam MatrixType type of the base, expected to be an instantiation
79 * of the Matrix class template.
80 *
81 * This class is capable of computing triangular real/complex matrices
82 * raised to a power in the interval \f$ (-1, 1) \f$.
83 *
84 * \note Currently this class is only used by MatrixPower. One may
85 * insist that this be nested into MatrixPower. This class is here to
86 * facilitate future development of triangular matrix functions.
87 */
88template <typename MatrixType>
89class MatrixPowerAtomic : internal::noncopyable {
90 private:
91 enum { RowsAtCompileTime = MatrixType::RowsAtCompileTime, MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime };
92 typedef typename MatrixType::Scalar Scalar;
93 typedef typename MatrixType::RealScalar RealScalar;
94 typedef std::complex<RealScalar> ComplexScalar;
95 typedef Block<MatrixType, Dynamic, Dynamic> ResultType;
96
97 const MatrixType& m_A;
98 RealScalar m_p;
99
100 void computePade(int degree, const MatrixType& IminusT, ResultType& res) const;
101 void compute2x2(ResultType& res, RealScalar p) const;
102 void computeBig(ResultType& res) const;
103 static int getPadeDegree(float normIminusT);
104 static int getPadeDegree(double normIminusT);
105 static int getPadeDegree(long double normIminusT);
106 static ComplexScalar computeSuperDiag(const ComplexScalar&, const ComplexScalar&, RealScalar p);
107 static RealScalar computeSuperDiag(RealScalar, RealScalar, RealScalar p);
108
109 public:
110 /**
111 * \brief Constructor.
112 *
113 * \param[in] T the base of the matrix power.
114 * \param[in] p the exponent of the matrix power, should be in
115 * \f$ (-1, 1) \f$.
116 *
117 * The class stores a reference to T, so it should not be changed
118 * (or destroyed) before evaluation. Only the upper triangular
119 * part of T is read.
120 */
121 MatrixPowerAtomic(const MatrixType& T, RealScalar p);
122
123 /**
124 * \brief Compute the matrix power.
125 *
126 * \param[out] res \f$ A^p \f$ where A and p are specified in the
127 * constructor.
128 */
129 void compute(ResultType& res) const;
130};
131
132template <typename MatrixType>
133MatrixPowerAtomic<MatrixType>::MatrixPowerAtomic(const MatrixType& T, RealScalar p) : m_A(T), m_p(p) {
134 eigen_assert(T.rows() == T.cols());
135 eigen_assert(p > -1 && p < 1);
136}
137
138template <typename MatrixType>
139void MatrixPowerAtomic<MatrixType>::compute(ResultType& res) const {
140 using std::pow;
141 switch (m_A.rows()) {
142 case 0:
143 break;
144 case 1:
145 res(0, 0) = pow(m_A(0, 0), m_p);
146 break;
147 case 2:
148 compute2x2(res, m_p);
149 break;
150 default:
151 computeBig(res);
152 }
153}
154
155template <typename MatrixType>
156void MatrixPowerAtomic<MatrixType>::computePade(int degree, const MatrixType& IminusT, ResultType& res) const {
157 int i = 2 * degree;
158 res = (m_p - RealScalar(degree)) / RealScalar(2 * i - 2) * IminusT;
159
160 for (--i; i; --i) {
161 res = (MatrixType::Identity(IminusT.rows(), IminusT.cols()) + res)
162 .template triangularView<Upper>()
163 .solve((i == 1 ? -m_p
164 : i & 1 ? (-m_p - RealScalar(i / 2)) / RealScalar(2 * i)
165 : (m_p - RealScalar(i / 2)) / RealScalar(2 * i - 2)) *
166 IminusT)
167 .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)
173template <typename MatrixType>
174void MatrixPowerAtomic<MatrixType>::compute2x2(ResultType& res, RealScalar p) const {
175 using std::abs;
176 using std::pow;
177 res.coeffRef(0, 0) = pow(m_A.coeff(0, 0), p);
178
179 for (Index i = 1; i < m_A.cols(); ++i) {
180 res.coeffRef(i, i) = pow(m_A.coeff(i, i), p);
181 if (m_A.coeff(i - 1, i - 1) == m_A.coeff(i, i))
182 res.coeffRef(i - 1, i) = p * pow(m_A.coeff(i, i), p - 1);
183 else if (2 * abs(m_A.coeff(i - 1, i - 1)) < abs(m_A.coeff(i, i)) ||
184 2 * abs(m_A.coeff(i, i)) < abs(m_A.coeff(i - 1, i - 1)))
185 res.coeffRef(i - 1, i) =
186 (res.coeff(i, i) - res.coeff(i - 1, i - 1)) / (m_A.coeff(i, i) - m_A.coeff(i - 1, i - 1));
187 else
188 res.coeffRef(i - 1, i) = computeSuperDiag(m_A.coeff(i, i), m_A.coeff(i - 1, i - 1), p);
189 res.coeffRef(i - 1, i) *= m_A.coeff(i - 1, i);
190 }
191}
192
193template <typename MatrixType>
194void MatrixPowerAtomic<MatrixType>::computeBig(ResultType& res) const {
195 using std::ldexp;
196 const int digits = std::numeric_limits<RealScalar>::digits;
197 const RealScalar maxNormForPade =
198 RealScalar(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) eigen_assert(m_A(i, i) != RealScalar(0));
209
210 while (true) {
211 IminusT = MatrixType::Identity(m_A.rows(), m_A.cols()) - T;
212 normIminusT = IminusT.cwiseAbs().colwise().sum().maxCoeff();
213 if (normIminusT < maxNormForPade) {
214 degree = getPadeDegree(normIminusT);
215 degree2 = getPadeDegree(normIminusT / 2);
216 if (degree - degree2 <= 1 || hasExtraSquareRoot) break;
217 hasExtraSquareRoot = true;
218 }
219 matrix_sqrt_triangular(T, sqrtT);
220 T = sqrtT.template triangularView<Upper>();
221 ++numberOfSquareRoots;
222 }
223 computePade(degree, IminusT, res);
224
225 for (; numberOfSquareRoots; --numberOfSquareRoots) {
226 compute2x2(res, ldexp(m_p, -numberOfSquareRoots));
227 res = res.template triangularView<Upper>() * res;
228 }
229 compute2x2(res, m_p);
230}
231
232template <typename MatrixType>
233inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(float normIminusT) {
234 const float maxNormForPade[] = {2.8064004e-1f /* degree = 3 */, 4.3386528e-1f};
235 int degree = 3;
236 for (; degree <= 4; ++degree)
237 if (normIminusT <= maxNormForPade[degree - 3]) break;
238 return degree;
239}
240
241template <typename MatrixType>
242inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(double normIminusT) {
243 const double maxNormForPade[] = {1.884160592658218e-2 /* degree = 3 */, 6.038881904059573e-2, 1.239917516308172e-1,
244 1.999045567181744e-1, 2.789358995219730e-1};
245 int degree = 3;
246 for (; degree <= 7; ++degree)
247 if (normIminusT <= maxNormForPade[degree - 3]) break;
248 return degree;
249}
250
251template <typename MatrixType>
252inline int MatrixPowerAtomic<MatrixType>::getPadeDegree(long double normIminusT) {
253#if LDBL_MANT_DIG == 53
254 const int maxPadeDegree = 7;
255 const double maxNormForPade[] = {1.884160592658218e-2L /* degree = 3 */, 6.038881904059573e-2L, 1.239917516308172e-1L,
256 1.999045567181744e-1L, 2.789358995219730e-1L};
257#elif LDBL_MANT_DIG <= 64
258 const int maxPadeDegree = 8;
259 const long double maxNormForPade[] = {6.3854693117491799460e-3L /* degree = 3 */,
260 2.6394893435456973676e-2L,
261 6.4216043030404063729e-2L,
262 1.1701165502926694307e-1L,
263 1.7904284231268670284e-1L,
264 2.4471944416607995472e-1L};
265#elif LDBL_MANT_DIG <= 106
266 const int maxPadeDegree = 10;
267 const double maxNormForPade[] = {1.0007161601787493236741409687186e-4L /* degree = 3 */,
268 1.0007161601787493236741409687186e-3L,
269 4.7069769360887572939882574746264e-3L,
270 1.3220386624169159689406653101695e-2L,
271 2.8063482381631737920612944054906e-2L,
272 4.9625993951953473052385361085058e-2L,
273 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,
279 3.227716520106894279249709728084626e-3L,
280 9.619593944683432960546978734646284e-3L,
281 2.134595382433742403911124458161147e-2L,
282 3.908166513900489428442993794761185e-2L,
283 6.266780814639442865832535460550138e-2L,
284 9.134603732914548552537150753385375e-2L};
285#endif
286 int degree = 3;
287 for (; degree <= maxPadeDegree; ++degree)
288 if (normIminusT <= static_cast<long double>(maxNormForPade[degree - 3])) break;
289 return degree;
290}
291
292template <typename MatrixType>
293inline typename MatrixPowerAtomic<MatrixType>::ComplexScalar MatrixPowerAtomic<MatrixType>::computeSuperDiag(
294 const ComplexScalar& curr, const ComplexScalar& prev, RealScalar p) {
295 using std::ceil;
296 using std::exp;
297 using std::log;
298 using std::sinh;
299
300 ComplexScalar logCurr = log(curr);
301 ComplexScalar logPrev = log(prev);
302 RealScalar unwindingNumber =
303 ceil((numext::imag(logCurr - logPrev) - RealScalar(EIGEN_PI)) / RealScalar(2 * EIGEN_PI));
304 ComplexScalar w =
305 numext::log1p((curr - prev) / prev) / RealScalar(2) + ComplexScalar(0, RealScalar(EIGEN_PI) * unwindingNumber);
306 return RealScalar(2) * exp(RealScalar(0.5) * p * (logCurr + logPrev)) * sinh(p * w) / (curr - prev);
307}
308
309template <typename MatrixType>
310inline typename MatrixPowerAtomic<MatrixType>::RealScalar MatrixPowerAtomic<MatrixType>::computeSuperDiag(
311 RealScalar curr, RealScalar prev, RealScalar p) {
312 using std::exp;
313 using std::log;
314 using std::sinh;
315
316 RealScalar w = numext::log1p((curr - prev) / prev) / RealScalar(2);
317 return 2 * exp(p * (log(curr) + log(prev)) / 2) * sinh(p * w) / (curr - prev);
318}
319
320/**
321 * \ingroup MatrixFunctions_Module
322 *
323 * \brief Class for computing matrix powers.
324 *
325 * \tparam MatrixType type of the base, expected to be an instantiation
326 * of the Matrix class template.
327 *
328 * This class is capable of computing real/complex matrices raised to
329 * an arbitrary real power. Meanwhile, it saves the result of Schur
330 * decomposition if an non-integral power has even been calculated.
331 * Therefore, if you want to compute multiple (>= 2) matrix powers
332 * for the same matrix, using the class directly is more efficient than
333 * calling MatrixBase::pow().
334 *
335 * Example:
336 * \include MatrixPower_optimal.cpp
337 * Output: \verbinclude MatrixPower_optimal.out
338 */
339template <typename MatrixType>
340class MatrixPower : internal::noncopyable {
341 private:
342 typedef typename MatrixType::Scalar Scalar;
343 typedef typename MatrixType::RealScalar RealScalar;
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) : m_A(A), m_conditionNumber(0), m_rank(A.cols()), m_nulls(0) {
355 eigen_assert(A.rows() == A.cols());
356 }
357
358 /**
359 * \brief Returns the matrix power.
360 *
361 * \param[in] p exponent, a real scalar.
362 * \return The expression \f$ A^p \f$, where A is specified in the
363 * constructor.
364 */
367 }
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, MatrixType::RowsAtCompileTime, MatrixType::ColsAtCompileTime>
385 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(Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res, const ComplexMatrix& T,
435 const ComplexMatrix& U);
436
437 template <int Rows, int Cols, int Options, int MaxRows, int MaxCols>
438 static void revertSchur(Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res, const ComplexMatrix& T,
439 const ComplexMatrix& U);
440};
441
442template <typename MatrixType>
443template <typename ResultType>
444void MatrixPower<MatrixType>::compute(ResultType& res, RealScalar p) {
445 using std::pow;
446 switch (cols()) {
447 case 0:
448 break;
449 case 1:
450 res(0, 0) = pow(m_A.coeff(0, 0), p);
451 break;
452 default:
453 RealScalar intpart;
454 split(p, intpart);
455
456 res = MatrixType::Identity(rows(), cols());
457 computeIntPower(res, intpart);
458 if (p) computeFracPower(res, p);
459 }
460}
461
462template <typename MatrixType>
463void MatrixPower<MatrixType>::split(RealScalar& p, RealScalar& intpart) {
464 using std::floor;
465 using std::pow;
466
467 intpart = floor(p);
468 p -= intpart;
469
470 // Perform Schur decomposition if it is not yet performed and the power is
471 // not an integer.
472 if (!m_conditionNumber && p) initialize();
473
474 // Choose the more stable of intpart = floor(p) and intpart = ceil(p).
475 if (p > RealScalar(0.5) && p > (1 - p) * pow(m_conditionNumber, p)) {
476 --p;
477 ++intpart;
478 }
479}
480
481template <typename MatrixType>
482void MatrixPower<MatrixType>::initialize() {
483 const ComplexSchur<MatrixType> schurOfA(m_A);
484 JacobiRotation<ComplexScalar> rot;
485 ComplexScalar eigenvalue;
486
487 m_fT.resizeLike(m_A);
488 m_T = schurOfA.matrixT();
489 m_U = schurOfA.matrixU();
490 m_conditionNumber = m_T.diagonal().array().abs().maxCoeff() / m_T.diagonal().array().abs().minCoeff();
491
492 // Move zero eigenvalues to the bottom right corner.
493 for (Index i = cols() - 1; i >= 0; --i) {
494 if (m_rank <= 2) return;
495 if (m_T.coeff(i, i) == RealScalar(0)) {
496 for (Index j = i + 1; j < m_rank; ++j) {
497 eigenvalue = m_T.coeff(j, j);
498 rot.makeGivens(m_T.coeff(j - 1, j), eigenvalue);
499 m_T.applyOnTheRight(j - 1, j, rot);
500 m_T.applyOnTheLeft(j - 1, j, rot.adjoint());
501 m_T.coeffRef(j - 1, j - 1) = eigenvalue;
502 m_T.coeffRef(j, j) = RealScalar(0);
503 m_U.applyOnTheRight(j - 1, j, rot);
504 }
505 --m_rank;
506 }
507 }
508
509 m_nulls = rows() - m_rank;
510 if (m_nulls) {
511 eigen_assert(m_T.bottomRightCorner(m_nulls, m_nulls).isZero() &&
512 "Base of matrix power should be invertible or with a semisimple zero eigenvalue.");
513 m_fT.bottomRows(m_nulls).fill(RealScalar(0));
514 }
515}
516
517template <typename MatrixType>
518template <typename ResultType>
519void MatrixPower<MatrixType>::computeIntPower(ResultType& res, RealScalar p) {
520 using std::abs;
521 using std::fmod;
522 RealScalar pp = abs(p);
523
524 if (p < 0)
525 m_tmp = m_A.inverse();
526 else
527 m_tmp = m_A;
528
529 while (true) {
530 if (fmod(pp, 2) >= 1) res = m_tmp * res;
531 pp /= 2;
532 if (pp < 1) break;
533 m_tmp *= m_tmp;
534 }
535}
536
537template <typename MatrixType>
538template <typename ResultType>
539void MatrixPower<MatrixType>::computeFracPower(ResultType& res, RealScalar p) {
540 Block<ComplexMatrix, Dynamic, Dynamic> blockTp(m_fT, 0, 0, m_rank, m_rank);
541 eigen_assert(m_conditionNumber);
542 eigen_assert(m_rank + m_nulls == rows());
543
544 MatrixPowerAtomic<ComplexMatrix>(m_T.topLeftCorner(m_rank, m_rank), p).compute(blockTp);
545 if (m_nulls) {
546 m_fT.topRightCorner(m_rank, m_nulls) = m_T.topLeftCorner(m_rank, m_rank)
547 .template triangularView<Upper>()
548 .solve(blockTp * m_T.topRightCorner(m_rank, m_nulls));
549 }
550 revertSchur(m_tmp, m_fT, m_U);
551 res = m_tmp * res;
552}
553
554template <typename MatrixType>
555template <int Rows, int Cols, int Options, int MaxRows, int MaxCols>
556inline void MatrixPower<MatrixType>::revertSchur(Matrix<ComplexScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
557 const ComplexMatrix& T, const ComplexMatrix& U) {
558 res.noalias() = U * (T.template triangularView<Upper>() * U.adjoint());
559}
560
561template <typename MatrixType>
562template <int Rows, int Cols, int Options, int MaxRows, int MaxCols>
563inline void MatrixPower<MatrixType>::revertSchur(Matrix<RealScalar, Rows, Cols, Options, MaxRows, MaxCols>& res,
564 const ComplexMatrix& T, const ComplexMatrix& U) {
565 res.noalias() = (U * (T.template triangularView<Upper>() * U.adjoint())).real();
566}
567
568/**
569 * \ingroup MatrixFunctions_Module
570 *
571 * \brief Proxy for the matrix power of some matrix (expression).
572 *
573 * \tparam Derived type of the base, a matrix (expression).
574 *
575 * This class holds the arguments to the matrix power until it is
576 * assigned or evaluated for some other reason (so the argument
577 * should not be changed in the meantime). It is the return type of
578 * MatrixBase::pow() and related functions and most of the
579 * time this is the only way it is used.
580 */
581template <typename Derived>
582class MatrixPowerReturnValue : public ReturnByValue<MatrixPowerReturnValue<Derived> > {
583 public:
584 typedef typename Derived::PlainObject PlainObject;
585 typedef typename Derived::RealScalar RealScalar;
586
587 /**
588 * \brief Constructor.
589 *
590 * \param[in] A %Matrix (expression), the base of the matrix power.
591 * \param[in] p real scalar, the exponent of the matrix power.
592 */
593 MatrixPowerReturnValue(const Derived& A, RealScalar p) : m_A(A), m_p(p) {}
594
595 /**
596 * \brief Compute the matrix power.
597 *
598 * \param[out] result \f$ A^p \f$ where \p A and \p p are as in the
599 * constructor.
600 */
601 template <typename ResultType>
602 inline void evalTo(ResultType& result) const {
603 MatrixPower<PlainObject>(m_A.eval()).compute(result, m_p);
604 }
605
606 Index rows() const { return m_A.rows(); }
607 Index cols() const { return m_A.cols(); }
608
609 private:
610 const Derived& m_A;
611 const RealScalar m_p;
612};
613
614/**
615 * \ingroup MatrixFunctions_Module
616 *
617 * \brief Proxy for the matrix power of some matrix (expression).
618 *
619 * \tparam Derived type of the base, a matrix (expression).
620 *
621 * This class holds the arguments to the matrix power until it is
622 * assigned or evaluated for some other reason (so the argument
623 * should not be changed in the meantime). It is the return type of
624 * MatrixBase::pow() and related functions and most of the
625 * time this is the only way it is used.
626 */
627template <typename Derived>
628class MatrixComplexPowerReturnValue : public ReturnByValue<MatrixComplexPowerReturnValue<Derived> > {
629 public:
630 typedef typename Derived::PlainObject PlainObject;
631 typedef typename std::complex<typename Derived::RealScalar> ComplexScalar;
632
633 /**
634 * \brief Constructor.
635 *
636 * \param[in] A %Matrix (expression), the base of the matrix power.
637 * \param[in] p complex scalar, the exponent of the matrix power.
638 */
639 MatrixComplexPowerReturnValue(const Derived& A, const ComplexScalar& p) : m_A(A), m_p(p) {}
640
641 /**
642 * \brief Compute the matrix power.
643 *
644 * Because \p p is complex, \f$ A^p \f$ is simply evaluated as \f$
645 * \exp(p \log(A)) \f$.
646 *
647 * \param[out] result \f$ A^p \f$ where \p A and \p p are as in the
648 * constructor.
649 */
650 template <typename ResultType>
651 inline void evalTo(ResultType& result) const {
652 result = (m_p * m_A.log()).exp();
653 }
654
655 Index rows() const { return m_A.rows(); }
656 Index cols() const { return m_A.cols(); }
657
658 private:
659 const Derived& m_A;
660 const ComplexScalar m_p;
661};
662
663namespace internal {
664
665template <typename MatrixPowerType>
666struct traits<MatrixPowerParenthesesReturnValue<MatrixPowerType> > {
667 typedef typename MatrixPowerType::PlainObject ReturnType;
668};
669
670template <typename Derived>
671struct traits<MatrixPowerReturnValue<Derived> > {
672 typedef typename Derived::PlainObject ReturnType;
673};
674
675template <typename Derived>
676struct traits<MatrixComplexPowerReturnValue<Derived> > {
677 typedef typename Derived::PlainObject ReturnType;
678};
679
680} // namespace internal
681
682template <typename Derived>
683const MatrixPowerReturnValue<Derived> MatrixBase<Derived>::pow(const RealScalar& p) const {
684 return MatrixPowerReturnValue<Derived>(derived(), p);
685}
686
687template <typename Derived>
688const MatrixComplexPowerReturnValue<Derived> MatrixBase<Derived>::pow(const std::complex<RealScalar>& p) const {
689 return MatrixComplexPowerReturnValue<Derived>(derived(), p);
690}
691
692} // namespace Eigen
693
694#endif // EIGEN_MATRIX_POWER
Proxy for the matrix power of some matrix (expression).
Definition: MatrixPower.h:628
MatrixComplexPowerReturnValue(const Derived &A, const ComplexScalar &p)
Constructor.
Definition: MatrixPower.h:639
Derived::PlainObject PlainObject
Definition: MatrixPower.h:630
Index cols() const
Definition: MatrixPower.h:656
std::complex< typename Derived::RealScalar > ComplexScalar
Definition: MatrixPower.h:631
void evalTo(ResultType &result) const
Compute the matrix power.
Definition: MatrixPower.h:651
Index rows() const
Definition: MatrixPower.h:655
Class for computing matrix powers.
Definition: MatrixPower.h:89
MatrixPowerAtomic(const MatrixType &T, RealScalar p)
Constructor.
Definition: MatrixPower.h:133
void compute(ResultType &res) const
Compute the matrix power.
Definition: MatrixPower.h:139
Class for computing matrix powers.
Definition: MatrixPower.h:340
Index cols() const
Definition: MatrixPower.h:380
MatrixPower(const MatrixType &A)
Constructor.
Definition: MatrixPower.h:354
const MatrixPowerParenthesesReturnValue< MatrixType > operator()(RealScalar p)
Returns the matrix power.
Definition: MatrixPower.h:365
void compute(ResultType &res, RealScalar p)
Compute the matrix power.
Definition: MatrixPower.h:444
Index rows() const
Definition: MatrixPower.h:379
Proxy for the matrix power of some matrix.
Definition: MatrixPower.h:43
MatrixType::RealScalar RealScalar
Definition: MatrixPower.h:45
Index rows() const
Definition: MatrixPower.h:65
Index cols() const
Definition: MatrixPower.h:66
MatrixPowerParenthesesReturnValue(MatrixPower< MatrixType > &pow, RealScalar p)
Constructor.
Definition: MatrixPower.h:53
void evalTo(ResultType &result) const
Compute the matrix power.
Definition: MatrixPower.h:61
Proxy for the matrix power of some matrix (expression).
Definition: MatrixPower.h:582
Index cols() const
Definition: MatrixPower.h:607
MatrixPowerReturnValue(const Derived &A, RealScalar p)
Constructor.
Definition: MatrixPower.h:593
Derived::RealScalar RealScalar
Definition: MatrixPower.h:585
void evalTo(ResultType &result) const
Compute the matrix power.
Definition: MatrixPower.h:602
Index rows() const
Definition: MatrixPower.h:606
Derived::PlainObject PlainObject
Definition: MatrixPower.h:584
void matrix_sqrt_triangular(const MatrixType &arg, ResultType &result)
Compute matrix square root of triangular matrix.
Definition: MatrixSquareRoot.h:194
UnitType abs(const UnitType x) noexcept
Compute absolute value.
Definition: math.h:721
dimensionless::scalar_t exp(const ScalarUnit x) noexcept
Compute exponential function.
Definition: math.h:332
dimensionless::scalar_t sinh(const AngleUnit angle) noexcept
Compute hyperbolic sine.
Definition: math.h:226
UnitTypeLhs fmod(const UnitTypeLhs numer, const UnitTypeRhs denom) noexcept
Compute remainder of division.
Definition: math.h:558
UnitType floor(const UnitType x) noexcept
Round down value.
Definition: math.h:542
dimensionless::scalar_t log(const ScalarUnit x) noexcept
Compute natural logarithm.
Definition: math.h:349
dimensionless::scalar_t log1p(const ScalarUnit x) noexcept
Compute logarithm plus one.
Definition: math.h:437
UnitType ceil(const UnitType x) noexcept
Round up value.
Definition: math.h:528
Definition: MatrixSquareRoot.h:16
static constexpr const mass::kilogram_t m_p(1.672621898e-27)
proton mass.
auto pow(const UnitType &value) noexcept -> unit_t< typename units::detail::power_of_unit< power, typename units::traits::unit_t_traits< UnitType >::unit_type >::type, typename units::traits::unit_t_traits< UnitType >::underlying_type, linear_scale >
computes the value of value raised to the power
Definition: base.h:2806
degree
Definition: angle.h:43
constexpr std::pair< std::string_view, std::string_view > split(std::string_view str, char separator) noexcept
Splits str into two substrings around the first occurrence of a separator character.
Definition: StringExtras.h:441
Derived::PlainObject ReturnType
Definition: MatrixPower.h:677
MatrixPowerType::PlainObject ReturnType
Definition: MatrixPower.h:667
Derived::PlainObject ReturnType
Definition: MatrixPower.h:672