5#ifndef LINE_UTIL_SYLVESTER_H
6#define LINE_UTIL_SYLVESTER_H
40#ifdef LINE_MP_HAVE_LAPACK
43void dtrsyl_(
const char* trana,
const char* tranb,
const int* isgn,
const int* m,
const int* n,
44 const double* a,
const int* lda,
const double* b,
const int* ldb,
double* c,
45 const int* ldc,
double* scale,
int* info);
64 if (A.
cols() != n_ || B.
cols() != m_)
65 throw InputError(
"SylvesterFactor: A and B must be square");
66 if (n_ == 0 || m_ == 0)
return;
68 for (std::size_t j = 0; j < m_; ++j)
69 for (std::size_t i = 0; i < n_; ++i) {
70 const std::size_t row = j * n_ + i;
71 for (std::size_t k = 0; k < n_; ++k) LU_(row, j * n_ + k) += A(i, k);
72 for (std::size_t k = 0; k < m_; ++k) LU_(row, k * n_ + i) += B(k, j);
81 if (n_ == 0 || m_ == 0)
return X;
82 if (C.
rows() != n_ || C.
cols() != m_)
83 throw InputError(
"SylvesterFactor: the right-hand side is not conformable");
84 std::vector<T> rhs(n_ * m_, zero);
85 for (std::size_t j = 0; j < m_; ++j)
86 for (std::size_t i = 0; i < n_; ++i) rhs[j * n_ + i] = C(i, j);
88 for (std::size_t j = 0; j < m_; ++j)
89 for (std::size_t i = 0; i < n_; ++i) X(i, j) = rhs[j * n_ + i];
96 for (std::size_t i = 0; i < C.
rows(); ++i)
97 for (std::size_t j = 0; j < C.
cols(); ++j) negC(i, j) = -C(i, j);
104 std::vector<std::size_t> piv_;
117 throw InputError(
"sylvester_solve: the blocks are not conformable");
125 throw InputError(
"lyap_solve: the blocks are not conformable");
151#ifndef LINE_MP_HAVE_LAPACK
156 "sylvester_schur requires LAPACK: reconfigure with -DLINE_MP_USE_LAPACK=ON and liblapack "
159 const std::size_t n = A.
rows(), m = B.
rows();
161 throw InputError(
"sylvester_schur: A and B must be square");
163 throw InputError(
"sylvester_schur: the right-hand side is not conformable");
165 if (n == 0 || m == 0)
return X;
171 std::vector<double> ta(n * n), tb(m * m), c(n * m);
172 for (std::size_t i = 0; i < n; ++i)
173 for (std::size_t j = 0; j < n; ++j) ta[j * n + i] = sa.
T(i, j);
174 for (std::size_t i = 0; i < m; ++i)
175 for (std::size_t j = 0; j < m; ++j) tb[j * m + i] = sb.
T(i, j);
176 for (std::size_t i = 0; i < n; ++i)
177 for (std::size_t j = 0; j < m; ++j) c[j * n + i] = Ct(i, j);
179 const int ni =
static_cast<int>(n), mi =
static_cast<int>(m), isgn = 1;
182 dtrsyl_(
"N",
"N", &isgn, &ni, &mi, ta.data(), &ni, tb.data(), &mi, c.data(), &ni, &scale,
184 if (info < 0)
throw InputError(
"sylvester_schur: LAPACK dtrsyl rejected an argument");
187 "sylvester_schur: A and -B have common or very close eigenvalues, so the Sylvester "
188 "equation is singular or nearly so and its solution is not determined");
190 throw NumericError(
"sylvester_schur: LAPACK dtrsyl returned a zero scale factor");
193 for (std::size_t i = 0; i < n; ++i)
194 for (std::size_t j = 0; j < m; ++j) Y(i, j) = c[j * n + i] / scale;
203 for (std::size_t i = 0; i < C.
rows(); ++i)
204 for (std::size_t j = 0; j < C.
cols(); ++j) negC(i, j) = -C(i, j);
NumericError(const std::string &what)
SylvesterFactor(const Matrix< T > &A, const Matrix< T > &B)
Matrix< T > solve_lyap(const Matrix< T > &C) const
Solve A X + X B + C = 0, MATLAB's lyap(A,B,C).
Matrix< T > solve_sylvester(const Matrix< T > &C) const
Solve A X + X B = C.
UnsupportedError(const std::string &what)
Eigenvalues and singular values, backed by LAPACK.
The exception types the port throws.
Dense linear algebra over the templated number type: products, identity, inverse, and powers.
LU factorization with partial pivoting, templated on the number type.
Dense matrix and non-owning view.
void lu_solve(const Matrix< T > &LU, const std::vector< std::size_t > &piv, std::vector< T > &b)
Solve LUx = Pb in place on b, using the factors from lu_factor.
std::vector< std::size_t > lu_factor(Matrix< T > &A)
In-place LU of A (n x n).
Matrix< T > lyap_solve(const Matrix< T > &A, const Matrix< T > &B, const Matrix< T > &C)
MATLAB lyap(A,B,C) solves A X + X B + C = 0, i.e.
Matrix< T > matmul(const Matrix< T > &A, const Matrix< T > &B)
Matrix product A B.
Matrix< double > sylvester_schur(const Matrix< double > &A, const Matrix< double > &B, const Matrix< double > &C)
A X + X B = C by Bartels-Stewart, at double.
Matrix< T > sylvester_solve(const Matrix< T > &A, const Matrix< T > &B, const Matrix< T > &C)
Solve A X + X B = C for X.
RealSchur schur_decomposition(const Matrix< double > &A)
Real Schur factorization of a general square matrix (LAPACK dgees, unsorted).
Matrix< double > lyap_schur(const Matrix< double > &A, const Matrix< double > &B, const Matrix< double > &C)
MATLAB lyap(A,B,C) at double via Bartels-Stewart: A X + X B + C = 0.
Number-type abstraction for the templated API port.
Real Schur factorization A = Z T Z^T, with Z orthogonal and T upper quasi-triangular: 1 x 1 diagonal ...
Matrix< double > Z
orthogonal Schur vectors
Matrix< double > T
upper quasi-triangular factor