28 #ifndef TOMOGRAPHER_MATHTOOLS_SOLVECLYAP_H 29 #define TOMOGRAPHER_MATHTOOLS_SOLVECLYAP_H 41 #include <Eigen/Eigenvalues> 46 extern "C" void ztrsyl_(
char *TRANA,
char *TRANB,
int *ISGN,
int *M,
int *N,
47 double *A,
int *lda,
double *B,
int *ldb,
48 double *C,
int *ldc,
double *scale,
int *info);
52 namespace SolveCLyap {
66 virtual const char * what()
const throw() {
71 namespace tomo_internal {
74 "TRANA",
"TRANB",
"ISGN",
"M",
"N",
"A",
"lda",
"B",
"ldb",
"C",
"ldc",
"scale",
"info" 78 template<
bool debug_perform_check>
79 struct solve_check_helper {
80 template<
typename XT,
typename AT,
typename CT,
typename LoggerType>
81 static inline void check(
const XT&,
const AT&,
const CT&, LoggerType&)
88 struct solve_check_helper<true> {
89 template<
typename XT,
typename AT,
typename CT,
typename LoggerType>
90 static inline void check(
const XT& X,
const AT& A,
const CT& C, LoggerType & logger)
94 double n1 = (A.adjoint() * X + X * A - C).norm();
95 double n2 = A.norm() + C.norm();
97 logger.debug(
"LyapCSolve::solve/check",
98 "(A.adjoint() * X + X * A - C).norm()/(A.norm()+C.norm()) == %g/%g == %g ; norm(C)=%g",
99 n1, n2, ok, (
double)C.norm());
101 logger.warning(
"LyapCSolve::solve/check",
"Bad solution quality! rel norm error = %g", (
double)ok);
128 template<
bool debug_perform_check = false,
typename LoggerType>
132 LoggerType & logger,
const double tol = 1e-8)
136 const Eigen::Index d = A.rows();
147 throw SolveError(
"Can't diagonalize matrix A: No Convergence");
154 for (
int k = 0; k < d; ++k) {
155 if (eigvalsA(k) > tol) {
162 MatType D = MatType::Zero(M, M);
163 MatType W = MatType::Zero(d, M);
168 for (
int k = 0; k < d; ++k) {
169 if (eigvalsA(k) < tol) {
173 W.col(counter) = eigU.col(k);
174 D(counter, counter) = eigvalsA(k);
190 Z = W.adjoint() * C * W;
197 int lda = (int)D.outerStride();
199 int ldc = (int)Z.outerStride();
201 ztrsyl_((
char*)
"C", (
char*)
"N", &plusone, &M, &M, (
double*)D.data(), &lda, (
double*)D.data(), &ldb,
202 (
double*)Z.data(), &ldc, &scale, &info);
206 logger.warning(
"SolveCLyap::solve()",
"Warning: A and B have common or very close eigenvalues; " 207 "perturbed values were used to solve the equation");
210 X.noalias() = W * Z * W.adjoint() / scale;
213 tomo_internal::solve_check_helper<debug_perform_check>::check(X, A, C, logger);
218 throw SolveError(
"Argument " + tomo_internal::ztrsyl_argnames[(-info)-1] +
" to ztrsyl_ was invalid.");
ComputationInfo info() const
Base namespace for the Tomographer project.
const RealVectorType & eigenvalues() const
Some C++ utilities, with a tad of C++11 tricks.
Matrix< std::complex< double >, Dynamic, Dynamic > MatrixXcd
internal::plain_col_type< MatrixType, RealScalar >::type RealVectorType
const MatrixType & eigenvectors() const
#define tomographer_assert(...)
Assertion test macro.