core/vnl/algo/vnl_complex_generalized_schur.cxx
Go to the documentation of this file.
00001 // This is core/vnl/algo/vnl_complex_generalized_schur.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 
00009 #include "vnl_complex_generalized_schur.h"
00010 
00011 #include <vcl_iostream.h>
00012 #include <vcl_cassert.h>
00013 
00014 #include <vnl/vnl_vector.h>
00015 
00016 #include <vnl/algo/vnl_netlib.h> // zgges_()
00017 
00018 VCL_DEFINE_SPECIALIZATION
00019 bool vnl_generalized_schur(vnl_matrix<vcl_complex<double> > *A,
00020                            vnl_matrix<vcl_complex<double> > *B,
00021                            vnl_vector<vcl_complex<double> > *alpha,
00022                            vnl_vector<vcl_complex<double> > *beta,
00023                            vnl_matrix<vcl_complex<double> > *L,
00024                            vnl_matrix<vcl_complex<double> > *R)
00025 {
00026   // Both input matrices should be square and of the same size:
00027   assert(A->rows() == A->cols());
00028   assert(A->cols() == B->rows());
00029   assert(B->rows() == B->cols());
00030 
00031   long n = A->rows();
00032   assert(alpha!=0); alpha->set_size(n);    alpha->fill(0);
00033   assert(beta!=0);  beta ->set_size(n);    beta ->fill(0);
00034   assert(L!=0);     L    ->set_size(n, n); L    ->fill(0);
00035   assert(R!=0);     R    ->set_size(n, n); R    ->fill(0);
00036 
00037   long sdim = 0;
00038   long lwork = 1000 + (8*n + 16);
00039   vcl_complex<double> *work = new vcl_complex<double>[lwork];
00040   double *rwork = new double[2*n + 1];
00041   v3p_netlib_logical *bwork = new v3p_netlib_logical[n + 1];
00042   long info = 0;
00043   A->inplace_transpose();
00044   B->inplace_transpose();
00045   v3p_netlib_zgges_ ("V", "V",
00046                      "N",
00047                      0,
00048                      &n,
00049                      A->data_block(), &n,
00050                      B->data_block(), &n,
00051                      &sdim,
00052                      alpha->data_block(),
00053                      beta->data_block(),
00054                      L->data_block(), &n,
00055                      R->data_block(), &n,
00056                      &work[0], &lwork,
00057                      &rwork[0], &bwork[0],
00058                      &info, 1, 1, 1);
00059   A->inplace_transpose();
00060   B->inplace_transpose();
00061   L->inplace_transpose();
00062   R->inplace_transpose();
00063   delete [] work;
00064   delete [] bwork;
00065   delete [] rwork;
00066 
00067   if (info == 0) {
00068     // ok
00069     return true;
00070   }
00071   else
00072   {
00073     // These return codes are taken from zgges.f:
00074     //*          = 0:  successful exit
00075     //*          < 0:  if INFO = -i, the i-th argument had an illegal value.
00076     //*          =1,...,N:
00077     //*                The QZ iteration failed.  (A,B) are not in Schur
00078     //*                form, but ALPHA(j) and BETA(j) should be correct for
00079     //*                j=INFO+1,...,N.
00080     //*          > N:  =N+1: other than QZ iteration failed in ZHGEQZ
00081     //*                =N+2: after reordering, roundoff changed values of
00082     //*                      some complex eigenvalues so that leading
00083     //*                      eigenvalues in the Generalized Schur form no
00084     //*                      longer satisfy SELCTG=.TRUE.  This could also
00085     //*                      be caused due to scaling.
00086     //*                =N+3: reordering falied in ZTGSEN.
00087     vcl_cerr << __FILE__ ": info = " << info << ", something went wrong:\n";
00088     if (info < 0) {
00089       vcl_cerr << __FILE__ ": (internal error) the " << (-info) << "th argument had an illegal value\n";
00090     }
00091     else if (1 <= info && info <= n) {
00092       vcl_cerr << __FILE__ ": the QZ iteration failed, but the last " << (n - info) << " eigenvalues may be correct\n";
00093     }
00094     else if (info == n+1) {
00095       vcl_cerr << __FILE__ ": something went wrong in ZHGEQZ\n";
00096     }
00097     else if (info == n+2) {
00098       vcl_cerr << __FILE__ ": roundoff error -- maybe due to poor scaling\n";
00099     }
00100     else if (info == n+3) {
00101       vcl_cerr << __FILE__ ": reordering failed in ZTGSEN\n";
00102     }
00103     else {
00104       vcl_cerr << __FILE__ ": unknown error\n";
00105     }
00106     return false;
00107   }
00108 }