40#ifdef LINE_MP_HAVE_LAPACK
42void dgeev_(
const char* jobvl,
const char* jobvr,
const int* n,
double* a,
const int* lda,
43 double* wr,
double* wi,
double* vl,
const int* ldvl,
double* vr,
const int* ldvr,
44 double* work,
const int* lwork,
int* info);
45void dgesvd_(
const char* jobu,
const char* jobvt,
const int* m,
const int* n,
double* a,
46 const int* lda,
double* s,
double* u,
const int* ldu,
double* vt,
const int* ldvt,
47 double* work,
const int* lwork,
int* info);
48void dgees_(
const char* jobvs,
const char* sort,
int (*select)(
const double*,
const double*),
49 const int* n,
double* a,
const int* lda,
int* sdim,
double* wr,
double* wi,
double* vs,
50 const int* ldvs,
double* work,
const int* lwork,
int* bwork,
int* info);
51void dtrexc_(
const char* compq,
const int* n,
double* t,
const int* ldt,
double* q,
const int* ldq,
52 int* ifst,
int* ilst,
double* work,
int* info);
60#ifndef LINE_MP_HAVE_LAPACK
63 "eig_values requires LAPACK: reconfigure with -DLINE_MP_USE_LAPACK=ON and liblapack "
66 const std::size_t n = A.
rows();
67 if (A.
cols() != n)
throw InputError(
"eig_values: matrix is not square");
68 if (n == 0)
return {};
71 std::vector<double> a(n * n);
72 for (std::size_t i = 0; i < n; ++i)
73 for (std::size_t j = 0; j < n; ++j) a[j * n + i] = A(i, j);
75 const int ni =
static_cast<int>(n);
76 std::vector<double> wr(n), wi(n);
78 int info = 0, lwork = -1;
81 dgeev_(
"N",
"N", &ni, a.data(), &ni, wr.data(), wi.data(), &vdummy, &one, &vdummy, &one, &wopt,
83 if (info != 0)
throw NumericError(
"eig_values: LAPACK workspace query failed");
84 lwork =
static_cast<int>(wopt);
85 std::vector<double> work(
static_cast<std::size_t
>(lwork));
86 dgeev_(
"N",
"N", &ni, a.data(), &ni, wr.data(), wi.data(), &vdummy, &one, &vdummy, &one,
87 work.data(), &lwork, &info);
88 if (info != 0)
throw NumericError(
"eig_values: LAPACK dgeev failed to converge");
90 std::vector<std::complex<double>> out(n);
91 for (std::size_t i = 0; i < n; ++i) out[i] = std::complex<double>(wr[i], wi[i]);
99 for (
const std::complex<double>& z :
eig_values(A)) {
100 const double m = std::abs(z);
112 std::vector<std::complex<double>> e =
eig_values(A);
113 if (e.size() < 2)
return 0.0;
114 double first = 0.0, second = 0.0;
115 for (
const std::complex<double>& z : e) {
116 const double m = std::abs(z);
120 }
else if (m > second) {
129#ifndef LINE_MP_HAVE_LAPACK
132 "svd_values requires LAPACK: reconfigure with -DLINE_MP_USE_LAPACK=ON and liblapack "
135 const std::size_t m = A.
rows(), n = A.
cols();
136 if (m == 0 || n == 0)
return {};
137 std::vector<double> a(m * n);
138 for (std::size_t i = 0; i < m; ++i)
139 for (std::size_t j = 0; j < n; ++j) a[j * m + i] = A(i, j);
141 const int mi =
static_cast<int>(m), nj =
static_cast<int>(n);
142 const std::size_t k = m < n ? m : n;
143 std::vector<double> s(k);
144 double udummy = 0.0, vtdummy = 0.0;
145 int info = 0, lwork = -1;
148 dgesvd_(
"N",
"N", &mi, &nj, a.data(), &mi, s.data(), &udummy, &one, &vtdummy, &one, &wopt,
150 if (info != 0)
throw NumericError(
"svd_values: LAPACK workspace query failed");
151 lwork =
static_cast<int>(wopt);
152 std::vector<double> work(
static_cast<std::size_t
>(lwork));
153 dgesvd_(
"N",
"N", &mi, &nj, a.data(), &mi, s.data(), &udummy, &one, &vtdummy, &one, work.data(),
155 if (info != 0)
throw NumericError(
"svd_values: LAPACK dgesvd failed to converge");
183#ifndef LINE_MP_HAVE_LAPACK
186 "schur_decomposition requires LAPACK: reconfigure with -DLINE_MP_USE_LAPACK=ON and "
187 "liblapack available");
189 const std::size_t n = A.
rows();
190 if (A.
cols() != n)
throw InputError(
"schur_decomposition: matrix is not square");
194 if (n == 0)
return out;
196 std::vector<double> a(n * n);
197 for (std::size_t i = 0; i < n; ++i)
198 for (std::size_t j = 0; j < n; ++j) a[j * n + i] = A(i, j);
200 const int ni =
static_cast<int>(n);
201 std::vector<double> wr(n), wi(n), vs(n * n);
202 int sdim = 0, info = 0, lwork = -1;
204 dgees_(
"V",
"N",
nullptr, &ni, a.data(), &ni, &sdim, wr.data(), wi.data(), vs.data(), &ni,
205 &wopt, &lwork,
nullptr, &info);
206 if (info != 0)
throw NumericError(
"schur_decomposition: LAPACK workspace query failed");
207 lwork =
static_cast<int>(wopt);
208 std::vector<double> work(
static_cast<std::size_t
>(lwork));
209 dgees_(
"V",
"N",
nullptr, &ni, a.data(), &ni, &sdim, wr.data(), wi.data(), vs.data(), &ni,
210 work.data(), &lwork,
nullptr, &info);
211 if (info != 0)
throw NumericError(
"schur_decomposition: LAPACK dgees failed to converge");
213 for (std::size_t i = 0; i < n; ++i)
214 for (std::size_t j = 0; j < n; ++j) {
215 out.
T(i, j) = a[j * n + i];
216 out.
Z(i, j) = vs[j * n + i];
249#ifndef LINE_MP_HAVE_LAPACK
253 "schur_reorder requires LAPACK: reconfigure with -DLINE_MP_USE_LAPACK=ON and liblapack "
256 const std::size_t n = s.
T.
rows();
258 throw InputError(
"schur_reorder: the factors are not square or not conformable");
259 if (key.size() != n)
throw InputError(
"schur_reorder: one key per diagonal entry is required");
263 if (n <= 1)
return out;
266 std::vector<double> t(n * n), q(n * n);
267 for (std::size_t i = 0; i < n; ++i)
268 for (std::size_t j = 0; j < n; ++j) {
269 t[j * n + i] = s.
T(i, j);
270 q[j * n + i] = s.
Z(i, j);
273 std::vector<double> k = key;
275 const int ni =
static_cast<int>(n);
276 std::vector<double> work(n);
277 const double tiny = 0.0;
285 std::size_t best = pos;
286 double bestkey = k[pos];
289 const std::size_t sz = (i + 1 < n && t[i * n + (i + 1)] != tiny) ? 2u : 1u;
290 if (k[i] > bestkey) {
296 const std::size_t bsz =
297 (best + 1 < n && t[best * n + (best + 1)] != tiny) ? 2u : 1u;
299 int ifst =
static_cast<int>(best) + 1;
300 int ilst =
static_cast<int>(pos) + 1;
302 dtrexc_(
"V", &ni, t.data(), &ni, q.data(), &ni, &ifst, &ilst, work.data(), &info);
305 "schur_reorder: dtrexc could not separate two eigenvalues that are too close; "
306 "the requested ordering splits a 2 x 2 block");
307 if (info != 0)
throw NumericError(
"schur_reorder: LAPACK dtrexc failed");
310 const std::vector<double> moved(k.begin() +
static_cast<long>(best),
311 k.begin() +
static_cast<long>(best + bsz));
312 k.erase(k.begin() +
static_cast<long>(best),
313 k.begin() +
static_cast<long>(best + bsz));
314 k.insert(k.begin() +
static_cast<long>(pos), moved.begin(), moved.end());
319 for (std::size_t i = 0; i < n; ++i)
320 for (std::size_t j = 0; j < n; ++j) {
321 out.
T(i, j) = t[j * n + i];
322 out.
Z(i, j) = q[j * n + i];
331 if (s.empty())
return 0;
333 const double tol =
static_cast<double>(dim) * 2.220446049250313e-16 * s[0];
NumericError(const std::string &what)
UnsupportedError(const std::string &what)
The exception types the port throws.
Dense matrix and non-owning view.
Conservation laws of a layered queueing network, enumerated from its structure.
double subdominant_modulus(const Matrix< double > &A)
Second largest modulus over the spectrum.
double spectral_radius(const Matrix< double > &A)
Largest modulus over the spectrum, i.e.
RealSchur schur_reorder(const RealSchur &s, const std::vector< double > &key)
Reorder the diagonal blocks of a real Schur form into DESCENDING key order, stably,...
std::vector< std::complex< double > > eig_values(const Matrix< double > &A)
Eigenvalues of a general real square matrix, in LAPACK's order.
std::size_t matrix_rank(const Matrix< double > &A)
Numerical rank at the standard max(m,n) eps sigma_1 threshold.
std::vector< double > svd_values(const Matrix< double > &A)
Singular values in descending order.
RealSchur schur_decomposition(const Matrix< double > &A)
Real Schur factorization of a general square matrix (LAPACK dgees, unsorted).
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