5#ifndef LINE_UTIL_SYLVESTER_H
6#define LINE_UTIL_SYLVESTER_H
47#ifdef LINE_MP_HAVE_LAPACK
50void dtrsyl_(
const char* trana,
const char* tranb,
const int* isgn,
const int* m,
const int* n,
51 const double* a,
const int* lda,
const double* b,
const int* ldb,
double* c,
52 const int* ldc,
double* scale,
int* info);
71 if (A.
cols() != n_ || B.
cols() != m_)
72 throw InputError(
"SylvesterFactor: A and B must be square");
73 if (n_ == 0 || m_ == 0)
return;
75 for (std::size_t j = 0; j < m_; ++j)
76 for (std::size_t i = 0; i < n_; ++i) {
77 const std::size_t row = j * n_ + i;
78 for (std::size_t k = 0; k < n_; ++k) LU_(row, j * n_ + k) += A(i, k);
79 for (std::size_t k = 0; k < m_; ++k) LU_(row, k * n_ + i) += B(k, j);
88 if (n_ == 0 || m_ == 0)
return X;
89 if (C.
rows() != n_ || C.
cols() != m_)
90 throw InputError(
"SylvesterFactor: the right-hand side is not conformable");
91 std::vector<T> rhs(n_ * m_, zero);
92 for (std::size_t j = 0; j < m_; ++j)
93 for (std::size_t i = 0; i < n_; ++i) rhs[j * n_ + i] = C(i, j);
95 for (std::size_t j = 0; j < m_; ++j)
96 for (std::size_t i = 0; i < n_; ++i) X(i, j) = rhs[j * n_ + i];
103 for (std::size_t i = 0; i < C.
rows(); ++i)
104 for (std::size_t j = 0; j < C.
cols(); ++j) negC(i, j) = -C(i, j);
111 std::vector<std::size_t> piv_;
124 throw InputError(
"sylvester_solve: the blocks are not conformable");
132 throw InputError(
"lyap_solve: the blocks are not conformable");
158#ifndef LINE_MP_HAVE_LAPACK
163 "sylvester_schur requires LAPACK: reconfigure with -DLINE_MP_USE_LAPACK=ON and liblapack "
166 const std::size_t n = A.
rows(), m = B.
rows();
168 throw InputError(
"sylvester_schur: A and B must be square");
170 throw InputError(
"sylvester_schur: the right-hand side is not conformable");
172 if (n == 0 || m == 0)
return X;
178 std::vector<double> ta(n * n), tb(m * m), c(n * m);
179 for (std::size_t i = 0; i < n; ++i)
180 for (std::size_t j = 0; j < n; ++j) ta[j * n + i] = sa.
T(i, j);
181 for (std::size_t i = 0; i < m; ++i)
182 for (std::size_t j = 0; j < m; ++j) tb[j * m + i] = sb.
T(i, j);
183 for (std::size_t i = 0; i < n; ++i)
184 for (std::size_t j = 0; j < m; ++j) c[j * n + i] = Ct(i, j);
186 const int ni =
static_cast<int>(n), mi =
static_cast<int>(m), isgn = 1;
189 dtrsyl_(
"N",
"N", &isgn, &ni, &mi, ta.data(), &ni, tb.data(), &mi, c.data(), &ni, &scale,
191 if (info < 0)
throw InputError(
"sylvester_schur: LAPACK dtrsyl rejected an argument");
194 "sylvester_schur: A and -B have common or very close eigenvalues, so the Sylvester "
195 "equation is singular or nearly so and its solution is not determined");
197 throw NumericError(
"sylvester_schur: LAPACK dtrsyl returned a zero scale factor");
200 for (std::size_t i = 0; i < n; ++i)
201 for (std::size_t j = 0; j < m; ++j) Y(i, j) = c[j * n + i] / scale;
210 for (std::size_t i = 0; i < C.
rows(); ++i)
211 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.
Conservation laws of a layered queueing network, enumerated from its structure.
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