core/vnl/algo/vnl_complex_eigensystem.cxx
Go to the documentation of this file.
00001 // This is core/vnl/algo/vnl_complex_eigensystem.cxx
00002 #include "vnl_complex_eigensystem.h"
00003 // \author fsm
00004 
00005 #include <vcl_cassert.h>
00006 #include <vcl_iostream.h>
00007 
00008 #include <vnl/vnl_matlab_print.h>
00009 #include <vnl/vnl_complexify.h>
00010 #include <vnl/algo/vnl_netlib.h> // zgeev_()
00011 
00012 void vnl_complex_eigensystem::compute(vnl_matrix<vcl_complex<double> > const & A,
00013                                       bool right,
00014                                       bool left)
00015 {
00016   A.assert_size(N, N);
00017 
00018   A.assert_finite();
00019   assert(! A.is_zero());
00020 
00021   if (right)
00022     R.set_size(N, N);
00023   if (left)
00024     L.set_size(N, N);
00025 
00026   //
00027   // Remember that fortran matrices and C matrices are transposed
00028   // relative to each other. Moreover, the documentation for zgeev
00029   // says that left eigenvectors u satisfy u^h A = lambda u^h,
00030   // where ^h denotes adjoint (conjugate transpose).
00031   // So we pass our left eigenvector storage as their right
00032   // eigenvector storage and vice versa.
00033   // But then we also have to conjugate our R after calling the routine.
00034   //
00035   vnl_matrix<vcl_complex<double> > tmp(A);
00036 
00037   long work_space=10*N;
00038   vnl_vector<vcl_complex<double> > work(work_space);
00039 
00040   long rwork_space=2*N;
00041   vnl_vector<double> rwork(rwork_space);
00042 
00043   long info;
00044   long tmpN = N;
00045   v3p_netlib_zgeev_(
00046          right ? "V" : "N",          // jobvl
00047          left  ? "V" : "N",          // jobvr
00048          &tmpN,                      // n
00049          tmp.data_block(),           // a
00050          &tmpN,                      // lda
00051          W.data_block(),             // w
00052          right ? R.data_block() : 0, // vl
00053          &tmpN,                      // ldvl
00054          left  ? L.data_block() : 0, // vr
00055          &tmpN,                      // ldvr
00056          work.data_block(),          // work
00057          &work_space,                // lwork
00058          rwork.data_block(),         // rwork
00059          &info,                      // info
00060          1, 1);
00061   assert(tmpN == int(N));
00062 
00063   if (right) {
00064     // conjugate all elements of R :
00065     for (unsigned int i=0;i<N;i++)
00066       for (unsigned int j=0;j<N;j++)
00067         R(i,j) = vcl_conj( R(i,j) );
00068   }
00069 
00070   if (info == 0) {
00071     // success
00072   }
00073   else if (info < 0) {
00074     vcl_cerr << __FILE__ ": info = " << info << vcl_endl
00075              << __FILE__ ": " << (-info) << "th argument has illegal value\n";
00076     assert(false);
00077   }
00078   else /* if (info > 0) */ {
00079     vcl_cerr << __FILE__ ": info = " << info << vcl_endl
00080              << __FILE__ ": QR algorithm failed to compute all eigenvalues.\n";
00081     vnl_matlab_print(vcl_cerr, A, "A", vnl_matlab_print_format_long);
00082     assert(false);
00083   }
00084 }
00085 
00086 //--------------------------------------------------------------------------------
00087 
00088 //
00089 vnl_complex_eigensystem::vnl_complex_eigensystem(vnl_matrix<vcl_complex<double> > const &A,
00090                                                  bool right,
00091                                                  bool left)
00092   : N(A.rows())
00093   // L and R are intentionally not initialized.
00094   , W(N)
00095 {
00096   compute(A, right, left);
00097 }
00098 
00099 //
00100 vnl_complex_eigensystem::vnl_complex_eigensystem(vnl_matrix<double> const &A_real,
00101                                                  vnl_matrix<double> const &A_imag,
00102                                                  bool right,
00103                                                  bool left)
00104   : N(A_real.rows())
00105   // L and R are intentionally not initialized.
00106   , W(N)
00107 {
00108   A_real.assert_size(N,N);
00109   A_imag.assert_size(N,N);
00110 
00111   vnl_matrix<vcl_complex<double> > A(N,N);
00112   vnl_complexify(A_real.begin(), A_imag.begin(), A.begin(), A.size());
00113 
00114   compute(A, right, left);
00115 }