vnl_complex_generalized_schur.cxx
Go to the documentation of this file.
1 // This is core/vnl/algo/vnl_complex_generalized_schur.cxx
2 //:
3 // \file
4 // \author fsm
5 
6 #include <iostream>
7 #include <cassert>
9 
10 #include <vnl/algo/vnl_netlib.h> // zgges_()
11 
12 template <>
13 bool vnl_generalized_schur(vnl_matrix<std::complex<double> > *A,
14  vnl_matrix<std::complex<double> > *B,
15  vnl_vector<std::complex<double> > *alpha,
16  vnl_vector<std::complex<double> > *beta,
17  vnl_matrix<std::complex<double> > *L,
18  vnl_matrix<std::complex<double> > *R)
19 {
20  // Both input matrices should be square and of the same size:
21  assert(A->rows() == A->cols());
22  assert(A->cols() == B->rows());
23  assert(B->rows() == B->cols());
24 
25  long n = A->rows();
26  assert(alpha!=nullptr); alpha->set_size(n); alpha->fill(0);
27  assert(beta!=nullptr); beta ->set_size(n); beta ->fill(0);
28  assert(L!=nullptr); L ->set_size(n, n); L ->fill(0);
29  assert(R!=nullptr); R ->set_size(n, n); R ->fill(0);
30 
31  long sdim = 0;
32  long lwork = 1000 + (8*n + 16);
33  auto *work = new std::complex<double>[lwork];
34  auto *rwork = new double[2*n + 1];
35  auto *bwork = new v3p_netlib_logical[n + 1];
36  long info = 0;
37  A->inplace_transpose();
38  B->inplace_transpose();
39  v3p_netlib_zgges_ ("V", "V",
40  "N",
41  nullptr,
42  &n,
43  A->data_block(), &n,
44  B->data_block(), &n,
45  &sdim,
46  alpha->data_block(),
47  beta->data_block(),
48  L->data_block(), &n,
49  R->data_block(), &n,
50  &work[0], &lwork,
51  &rwork[0], &bwork[0],
52  &info, 1, 1, 1);
53  A->inplace_transpose();
54  B->inplace_transpose();
55  L->inplace_transpose();
56  R->inplace_transpose();
57  delete [] work;
58  delete [] bwork;
59  delete [] rwork;
60 
61  if (info == 0) {
62  // ok
63  return true;
64  }
65  else
66  {
67  // These return codes are taken from zgges.f:
68  //* = 0: successful exit
69  //* < 0: if INFO = -i, the i-th argument had an illegal value.
70  //* =1,...,N:
71  //* The QZ iteration failed. (A,B) are not in Schur
72  //* form, but ALPHA(j) and BETA(j) should be correct for
73  //* j=INFO+1,...,N.
74  //* > N: =N+1: other than QZ iteration failed in ZHGEQZ
75  //* =N+2: after reordering, roundoff changed values of
76  //* some complex eigenvalues so that leading
77  //* eigenvalues in the Generalized Schur form no
78  //* longer satisfy SELCTG=.TRUE. This could also
79  //* be caused due to scaling.
80  //* =N+3: reordering falied in ZTGSEN.
81  std::cerr << __FILE__ ": info = " << info << ", something went wrong:\n";
82  if (info < 0) {
83  std::cerr << __FILE__ ": (internal error) the " << (-info) << "th argument had an illegal value\n";
84  }
85  else if (1 <= info && info <= n) {
86  std::cerr << __FILE__ ": the QZ iteration failed, but the last " << (n - info) << " eigenvalues may be correct\n";
87  }
88  else if (info == n+1) {
89  std::cerr << __FILE__ ": something went wrong in ZHGEQZ\n";
90  }
91  else if (info == n+2) {
92  std::cerr << __FILE__ ": roundoff error -- maybe due to poor scaling\n";
93  }
94  else if (info == n+3) {
95  std::cerr << __FILE__ ": reordering failed in ZTGSEN\n";
96  }
97  else {
98  std::cerr << __FILE__ ": unknown error\n";
99  }
100  return false;
101  }
102 }
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
Declare in a central place the list of symbols from netlib.
Solves the generalized eigenproblem det(t A - s B) = 0.
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
bool vnl_generalized_schur(vnl_matrix< std::complex< double > > *A, vnl_matrix< std::complex< double > > *B, vnl_vector< std::complex< double > > *alpha, vnl_vector< std::complex< double > > *beta, vnl_matrix< std::complex< double > > *L, vnl_matrix< std::complex< double > > *R)