40 #include <Eigen/Eigenvalues>
43 extern "C" void ztrsyl_(
char *TRANA,
char *TRANB,
int *ISGN,
int *M,
int *N,
44 double *A,
int *lda,
double *B,
int *ldb,
45 double *C,
int *ldc,
double *scale,
int *info);
68 virtual const char * what()
const throw() {
73 namespace tomo_internal {
76 "TRANA",
"TRANB",
"ISGN",
"M",
"N",
"A",
"lda",
"B",
"ldb",
"C",
"ldc",
"scale",
"info"
80 template<
bool debug_perform_check>
81 struct solve_check_helper {
82 template<
typename XT,
typename AT,
typename CT,
typename Log>
83 static inline void check(
const XT&,
const AT&,
const CT&, Log&)
90 struct solve_check_helper<true> {
91 template<
typename XT,
typename AT,
typename CT,
typename Log>
92 static inline void check(
const XT& X,
const AT& A,
const CT& C, Log & logger)
96 double n1 = (A.adjoint() * X + X * A - C).norm();
97 double n2 = A.norm() + C.norm();
99 logger.debug(
"LyapCSolve::solve/check",
100 "(A.adjoint() * X + X * A - C).norm()/(A.norm()+C.norm()) == %g/%g == %g ; norm(C)=%g",
101 n1, n2, ok, (
double)C.norm());
103 logger.warning(
"LyapCSolve::solve/check",
"Bad solution quality! rel norm error = %g", (
double)ok);
124 template<
bool debug_perform_check = false,
typename Log,
typename DerX,
typename DerA,
typename DerC>
130 const int d = A.rows();
135 throw SolveError(
"Can't diagonalize matrix A: No Convergence");
142 for (
int k = 0; k < d; ++k) {
143 if (eigvalsA(k) > tol) {
152 MatType D = MatType::Zero(M, M);
153 MatType W = MatType::Zero(d, M);
158 for (
int k = 0; k < d; ++k) {
159 if (eigvalsA(k) < tol) {
163 W.col(counter) = eigU.col(k);
164 D(counter, counter) = eigvalsA(k);
180 Z = W.adjoint() * C * W;
187 int lda = D.outerStride();
189 int ldc = Z.outerStride();
191 ztrsyl_((
char*)
"C", (
char*)
"N", &plusone, &M, &M, (
double*)D.data(), &lda, (
double*)D.data(), &ldb,
192 (
double*)Z.
data(), &ldc, &scale, &info);
196 logger.warning(
"SolveCLyap::solve()",
"Warning: A and B have common or very close eigenvalues; "
197 "perturbed values were used to solve the equation");
200 X.
noalias() = W * Z * W.adjoint() / scale;
203 tomo_internal::solve_check_helper<debug_perform_check>::check(X, A, C, logger);
208 throw SolveError(
"Argument " + tomo_internal::ztrsyl_argnames[(-info)-1] +
" to ztrsyl_ was invalid.");
ComputationInfo info() const
const Scalar * data() const
Base namespace for the Tomographer project.
Error while attempting to solve complex Lyapunov/Sylvester equation.
const RealVectorType & eigenvalues() const
void solve(Eigen::MatrixBase< DerX > &X, const Eigen::MatrixBase< DerA > &A, const Eigen::MatrixBase< DerC > &C, Log &logger, const double tol=1e-8)
Solve complex Lyapunov equation of the form A'*X + X*A == C
NoAlias< Derived, Eigen::MatrixBase > noalias()
internal::plain_col_type< MatrixType, RealScalar >::type RealVectorType
const MatrixType & eigenvectors() const