10 #ifndef EIGEN_MATRIX_FUNCTION_H
11 #define EIGEN_MATRIX_FUNCTION_H
31 template <
typename MatrixType>
32 class MatrixFunctionAtomic
36 typedef typename MatrixType::Scalar Scalar;
37 typedef typename stem_function<Scalar>::type StemFunction;
42 MatrixFunctionAtomic(StemFunction f) : m_f(f) { }
54 template <
typename MatrixType>
57 typedef typename plain_col_type<MatrixType>::type VectorType;
60 VectorType
e = VectorType::Ones(
rows);
61 N.template triangularView<Upper>().solveInPlace(
e);
62 return e.cwiseAbs().maxCoeff();
65 template <
typename MatrixType>
71 Scalar avgEival =
A.trace() / Scalar(RealScalar(rows));
72 MatrixType Ashifted =
A - avgEival * MatrixType::Identity(rows, rows);
74 MatrixType F = m_f(avgEival, 0) * MatrixType::Identity(rows, rows);
77 for (
Index s = 1; double(s) < 1.1 * double(rows) + 10.0; s++) {
78 Fincr = m_f(avgEival,
static_cast<int>(s)) *
P;
80 P = Scalar(RealScalar(1)/RealScalar(s + 1)) *
P * Ashifted;
83 const RealScalar F_norm = F.cwiseAbs().rowwise().sum().maxCoeff();
84 const RealScalar Fincr_norm = Fincr.cwiseAbs().rowwise().sum().maxCoeff();
87 RealScalar rfactorial = 1;
91 mx = (
std::max)(mx,
std::abs(m_f(Ashifted(i, i) + avgEival,
static_cast<int>(s+r))));
93 rfactorial *= RealScalar(r);
94 delta = (
std::max)(delta, mx / rfactorial);
96 const RealScalar P_norm =
P.cwiseAbs().rowwise().sum().maxCoeff();
97 if (mu * delta * P_norm < NumTraits<Scalar>::epsilon() * F_norm)
109 template <
typename Index,
typename ListOfClusters>
112 typename std::list<Index>::iterator
j;
113 for (
typename ListOfClusters::iterator
i = clusters.begin();
i != clusters.end(); ++
i) {
114 j = std::find(
i->begin(),
i->end(), key);
118 return clusters.end();
132 template <
typename EivalsType,
typename Cluster>
135 typedef typename EivalsType::RealScalar RealScalar;
139 if (qi == clusters.end()) {
142 clusters.push_back(l);
150 && std::find(qi->begin(), qi->end(),
j) == qi->end()) {
152 if (qj == clusters.end()) {
155 qi->insert(qi->end(), qj->begin(), qj->end());
164 template <
typename ListOfClusters,
typename Index>
167 const Index numClusters =
static_cast<Index>(clusters.size());
168 clusterSize.
setZero(numClusters);
169 Index clusterIndex = 0;
170 for (
typename ListOfClusters::const_iterator cluster = clusters.begin(); cluster != clusters.end(); ++cluster) {
171 clusterSize[clusterIndex] = cluster->
size();
177 template <
typename VectorType>
180 blockStart.resize(clusterSize.rows());
182 for (
Index i = 1;
i < clusterSize.rows();
i++) {
183 blockStart(
i) = blockStart(
i-1) + clusterSize(
i-1);
188 template <
typename EivalsType,
typename ListOfClusters,
typename VectorType>
191 eivalToCluster.resize(
eivals.rows());
192 Index clusterIndex = 0;
193 for (
typename ListOfClusters::const_iterator cluster = clusters.begin(); cluster != clusters.end(); ++cluster) {
195 if (std::find(cluster->begin(), cluster->end(),
i) != cluster->end()) {
196 eivalToCluster[
i] = clusterIndex;
204 template <
typename DynVectorType,
typename VectorType>
207 DynVectorType indexNextEntry = blockStart;
208 permutation.resize(eivalToCluster.rows());
209 for (
Index i = 0;
i < eivalToCluster.rows();
i++) {
210 Index cluster = eivalToCluster[
i];
211 permutation[
i] = indexNextEntry[cluster];
212 ++indexNextEntry[cluster];
217 template <
typename VectorType,
typename MatrixType>
220 for (
Index i = 0;
i < permutation.rows() - 1;
i++) {
222 for (
j =
i;
j < permutation.rows();
j++) {
223 if (permutation(
j) ==
i)
break;
226 for (
Index k =
j-1; k >=
i; k--) {
229 T.applyOnTheLeft(k, k+1, rotation.
adjoint());
230 T.applyOnTheRight(k, k+1, rotation);
231 U.applyOnTheRight(k, k+1, rotation);
232 std::swap(permutation.coeffRef(k), permutation.coeffRef(k+1));
243 template <
typename MatrixType,
typename AtomicType,
typename VectorType>
246 fT.setZero(
T.rows(),
T.cols());
247 for (
Index i = 0;
i < clusterSize.rows(); ++
i) {
248 fT.block(blockStart(
i), blockStart(
i), clusterSize(
i), clusterSize(
i))
249 = atomic.compute(
T.block(blockStart(
i), blockStart(
i), clusterSize(
i), clusterSize(
i)));
275 template <
typename MatrixType>
285 typedef typename MatrixType::Scalar Scalar;
324 template <
typename MatrixType,
typename VectorType>
327 typedef internal::traits<MatrixType> Traits;
328 typedef typename MatrixType::Scalar Scalar;
329 static const int Options = MatrixType::Options;
332 for (
Index k = 1; k < clusterSize.rows(); k++) {
333 for (
Index i = 0;
i < clusterSize.rows() - k;
i++) {
335 DynMatrixType
A =
T.block(blockStart(
i), blockStart(
i), clusterSize(
i), clusterSize(
i));
336 DynMatrixType
B = -
T.block(blockStart(
i+k), blockStart(
i+k), clusterSize(
i+k), clusterSize(
i+k));
337 DynMatrixType C = fT.block(blockStart(
i), blockStart(
i), clusterSize(
i), clusterSize(
i))
338 *
T.block(blockStart(
i), blockStart(
i+k), clusterSize(
i), clusterSize(
i+k));
339 C -=
T.block(blockStart(
i), blockStart(
i+k), clusterSize(
i), clusterSize(
i+k))
340 * fT.block(blockStart(
i+k), blockStart(
i+k), clusterSize(
i+k), clusterSize(
i+k));
342 C += fT.block(blockStart(
i), blockStart(
m), clusterSize(
i), clusterSize(
m))
343 *
T.block(blockStart(
m), blockStart(
i+k), clusterSize(
m), clusterSize(
i+k));
344 C -=
T.block(blockStart(
i), blockStart(
m), clusterSize(
i), clusterSize(
m))
345 * fT.block(blockStart(
m), blockStart(
i+k), clusterSize(
m), clusterSize(
i+k));
347 fT.block(blockStart(
i), blockStart(
i+k), clusterSize(
i), clusterSize(
i+k))
368 template <typename MatrixType, int IsComplex = NumTraits<typename internal::traits<MatrixType>::Scalar>::IsComplex>
369 struct matrix_function_compute
381 template <
typename AtomicType,
typename ResultType>
382 static void run(
const MatrixType& A, AtomicType& atomic, ResultType &result);
391 template <
typename MatrixType>
394 template <
typename MatA,
typename AtomicType,
typename ResultType>
395 static void run(
const MatA& A, AtomicType& atomic, ResultType &result)
397 typedef internal::traits<MatrixType> Traits;
398 typedef typename Traits::Scalar Scalar;
399 static const int Rows = Traits::RowsAtCompileTime, Cols = Traits::ColsAtCompileTime;
400 static const int MaxRows = Traits::MaxRowsAtCompileTime, MaxCols = Traits::MaxColsAtCompileTime;
402 typedef std::complex<Scalar> ComplexScalar;
403 typedef Matrix<ComplexScalar, Rows, Cols, 0, MaxRows, MaxCols> ComplexMatrix;
405 ComplexMatrix CA =
A.template cast<ComplexScalar>();
406 ComplexMatrix Cresult;
407 matrix_function_compute<ComplexMatrix>::run(CA, atomic, Cresult);
408 result = Cresult.real();
415 template <
typename MatrixType>
418 template <
typename MatA,
typename AtomicType,
typename ResultType>
419 static void run(
const MatA& A, AtomicType& atomic, ResultType &result)
421 typedef internal::traits<MatrixType> Traits;
430 std::list<std::list<Index> > clusters;
434 Matrix<Index, Dynamic, 1> clusterSize;
438 Matrix<Index, Dynamic, 1> blockStart;
442 Matrix<Index, Dynamic, 1> eivalToCluster;
446 Matrix<Index, Traits::RowsAtCompileTime, 1> permutation;
456 result = U * (fT.template triangularView<Upper>() * U.adjoint());
472 template<
typename Derived>
class MatrixFunctionReturnValue
473 :
public ReturnByValue<MatrixFunctionReturnValue<Derived> >
476 typedef typename Derived::Scalar Scalar;
477 typedef typename internal::stem_function<Scalar>::type StemFunction;
480 typedef typename internal::ref_selector<Derived>::type DerivedNested;
489 MatrixFunctionReturnValue(
const Derived& A, StemFunction f) : m_A(
A), m_f(f) { }
495 template <
typename ResultType>
496 inline void evalTo(ResultType& result)
const
498 typedef typename internal::nested_eval<Derived, 10>::type NestedEvalType;
499 typedef internal::remove_all_t<NestedEvalType> NestedEvalTypeClean;
500 typedef internal::traits<NestedEvalTypeClean> Traits;
501 typedef std::complex<typename NumTraits<Scalar>::Real> ComplexScalar;
502 typedef Matrix<ComplexScalar, Dynamic, Dynamic, 0, Traits::RowsAtCompileTime, Traits::ColsAtCompileTime> DynMatrixType;
504 typedef internal::MatrixFunctionAtomic<DynMatrixType> AtomicType;
505 AtomicType atomic(m_f);
507 internal::matrix_function_compute<typename NestedEvalTypeClean::PlainObject>::run(m_A, atomic, result);
510 Index rows()
const {
return m_A.rows(); }
511 Index cols()
const {
return m_A.cols(); }
514 const DerivedNested m_A;
519 template<
typename Derived>
520 struct traits<MatrixFunctionReturnValue<Derived> >
522 typedef typename Derived::PlainObject ReturnType;
530 template <
typename Derived>
534 return MatrixFunctionReturnValue<Derived>(derived(), f);
537 template <
typename Derived>
541 typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
542 return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_sin<ComplexScalar>);
545 template <
typename Derived>
549 typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
550 return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_cos<ComplexScalar>);
553 template <
typename Derived>
557 typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
558 return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_sinh<ComplexScalar>);
561 template <
typename Derived>
565 typedef typename internal::stem_function<Scalar>::ComplexScalar ComplexScalar;
566 return MatrixFunctionReturnValue<Derived>(derived(), internal::stem_function_cosh<ComplexScalar>);
SparseMatrix< double > A(n, n)
cout<< "Here is a random 4x4 matrix, A:"<< endl<< A<< endl<< endl;ComplexSchur< MatrixXcf > schurOfA(A, false)
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Projective3d P(Matrix4d::Random())
Matrix< float, 1, Dynamic > MatrixType
EIGEN_CONSTEXPR Index size() const EIGEN_NOEXCEPT
JacobiRotation adjoint() const
void makeGivens(const Scalar &p, const Scalar &q, Scalar *r=0)
const MatrixFunctionReturnValue< Derived > sin() const
const MatrixFunctionReturnValue< Derived > matrixFunction(StemFunction f) const
const MatrixFunctionReturnValue< Derived > cos() const
const MatrixFunctionReturnValue< Derived > cosh() const
const MatrixFunctionReturnValue< Derived > sinh() const
Matrix< Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_ > & setZero(Index rows, Index cols)
void matrix_function_compute_permutation(const DynVectorType &blockStart, const DynVectorType &eivalToCluster, VectorType &permutation)
Compute permutation which groups ei'vals in same cluster together.
void matrix_function_compute_cluster_size(const ListOfClusters &clusters, Matrix< Index, Dynamic, 1 > &clusterSize)
Compute size of each cluster given a partitioning.
void matrix_function_compute_block_start(const VectorType &clusterSize, VectorType &blockStart)
Compute start of each block using clusterSize.
void matrix_function_compute_block_atomic(const MatrixType &T, AtomicType &atomic, const VectorType &blockStart, const VectorType &clusterSize, MatrixType &fT)
Compute block diagonal part of matrix function.
void matrix_function_permute_schur(VectorType &permutation, MatrixType &U, MatrixType &T)
Permute Schur decomposition in U and T according to permutation.
static const float matrix_function_separation
Maximum distance allowed between eigenvalues to be considered "close".
void matrix_function_compute_above_diagonal(const MatrixType &T, const VectorType &blockStart, const VectorType &clusterSize, MatrixType &fT)
Compute part of matrix function above block diagonal.
void matrix_function_partition_eigenvalues(const EivalsType &eivals, std::list< Cluster > &clusters)
Partition eigenvalues in clusters of ei'vals close to each other.
NumTraits< typename MatrixType::Scalar >::Real matrix_function_compute_mu(const MatrixType &A)
MatrixType matrix_function_solve_triangular_sylvester(const MatrixType &A, const MatrixType &B, const MatrixType &C)
Solve a triangular Sylvester equation AX + XB = C.
void matrix_function_compute_map(const EivalsType &eivals, const ListOfClusters &clusters, VectorType &eivalToCluster)
Compute mapping of eigenvalue indices to cluster indices.
ListOfClusters::iterator matrix_function_find_cluster(Index key, ListOfClusters &clusters)
Find cluster in clusters containing some value.
: TensorContractionSycl.h, provides various tensor contraction kernel for SYCL backend
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
CleanedUpDerType< DerType >::type() max(const AutoDiffScalar< DerType > &x, const T &y)
const Eigen::CwiseUnaryOp< Eigen::internal::scalar_abs_op< typename Derived::Scalar >, const Derived > abs(const Eigen::ArrayBase< Derived > &x)
adouble abs(const adouble &x)