EIG.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1994-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include "EIG.h"
00028 #include "dColVector.h"
00029 #include "f77-fcn.h"
00030 #include "lo-error.h"
00031 
00032 extern "C"
00033 {
00034   F77_RET_T
00035   F77_FUNC (dgeev, DGEEV) (F77_CONST_CHAR_ARG_DECL,
00036                            F77_CONST_CHAR_ARG_DECL,
00037                            const octave_idx_type&, double*,
00038                            const octave_idx_type&, double*, double*,
00039                            double*, const octave_idx_type&, double*,
00040                            const octave_idx_type&, double*,
00041                            const octave_idx_type&, octave_idx_type&
00042                            F77_CHAR_ARG_LEN_DECL
00043                            F77_CHAR_ARG_LEN_DECL);
00044 
00045   F77_RET_T
00046   F77_FUNC (zgeev, ZGEEV) (F77_CONST_CHAR_ARG_DECL,
00047                            F77_CONST_CHAR_ARG_DECL,
00048                            const octave_idx_type&, Complex*,
00049                            const octave_idx_type&, Complex*,
00050                            Complex*, const octave_idx_type&, Complex*,
00051                            const octave_idx_type&, Complex*,
00052                            const octave_idx_type&, double*, octave_idx_type&
00053                            F77_CHAR_ARG_LEN_DECL
00054                            F77_CHAR_ARG_LEN_DECL);
00055 
00056   F77_RET_T
00057   F77_FUNC (dsyev, DSYEV) (F77_CONST_CHAR_ARG_DECL,
00058                            F77_CONST_CHAR_ARG_DECL,
00059                            const octave_idx_type&, double*,
00060                            const octave_idx_type&, double*, double*,
00061                            const octave_idx_type&, octave_idx_type&
00062                            F77_CHAR_ARG_LEN_DECL
00063                            F77_CHAR_ARG_LEN_DECL);
00064 
00065   F77_RET_T
00066   F77_FUNC (zheev, ZHEEV) (F77_CONST_CHAR_ARG_DECL,
00067                            F77_CONST_CHAR_ARG_DECL,
00068                            const octave_idx_type&, Complex*,
00069                            const octave_idx_type&, double*,
00070                            Complex*, const octave_idx_type&, double*,
00071                            octave_idx_type&
00072                            F77_CHAR_ARG_LEN_DECL
00073                            F77_CHAR_ARG_LEN_DECL);
00074 
00075   F77_RET_T
00076   F77_FUNC (dpotrf, DPOTRF) (F77_CONST_CHAR_ARG_DECL,
00077                              const octave_idx_type&, double*,
00078                              const octave_idx_type&, octave_idx_type&
00079                              F77_CHAR_ARG_LEN_DECL
00080                              F77_CHAR_ARG_LEN_DECL);
00081 
00082   F77_RET_T
00083   F77_FUNC (zpotrf, ZPOTRF) (F77_CONST_CHAR_ARG_DECL,
00084                              const octave_idx_type&,
00085                              Complex*, const octave_idx_type&,
00086                              octave_idx_type&
00087                              F77_CHAR_ARG_LEN_DECL
00088                              F77_CHAR_ARG_LEN_DECL);
00089 
00090   F77_RET_T
00091   F77_FUNC (dggev, DGGEV) (F77_CONST_CHAR_ARG_DECL,
00092                            F77_CONST_CHAR_ARG_DECL,
00093                            const octave_idx_type&,
00094                            double*, const octave_idx_type&,
00095                            double*, const octave_idx_type&,
00096                            double*, double*, double *, double*,
00097                            const octave_idx_type&, double*,
00098                            const octave_idx_type&, double*,
00099                            const octave_idx_type&, octave_idx_type&
00100                            F77_CHAR_ARG_LEN_DECL
00101                            F77_CHAR_ARG_LEN_DECL);
00102 
00103   F77_RET_T
00104   F77_FUNC (dsygv, DSYGV) (const octave_idx_type&,
00105                            F77_CONST_CHAR_ARG_DECL,
00106                            F77_CONST_CHAR_ARG_DECL,
00107                            const octave_idx_type&, double*,
00108                            const octave_idx_type&, double*,
00109                            const octave_idx_type&, double*, double*,
00110                            const octave_idx_type&, octave_idx_type&
00111                            F77_CHAR_ARG_LEN_DECL
00112                            F77_CHAR_ARG_LEN_DECL);
00113 
00114   F77_RET_T
00115   F77_FUNC (zggev, ZGGEV) (F77_CONST_CHAR_ARG_DECL,
00116                            F77_CONST_CHAR_ARG_DECL,
00117                            const octave_idx_type&,
00118                            Complex*, const octave_idx_type&,
00119                            Complex*, const octave_idx_type&,
00120                            Complex*, Complex*, Complex*,
00121                            const octave_idx_type&, Complex*,
00122                            const octave_idx_type&, Complex*,
00123                            const octave_idx_type&, double*, octave_idx_type&
00124                            F77_CHAR_ARG_LEN_DECL
00125                            F77_CHAR_ARG_LEN_DECL);
00126 
00127   F77_RET_T
00128   F77_FUNC (zhegv, ZHEGV) (const octave_idx_type&,
00129                            F77_CONST_CHAR_ARG_DECL,
00130                            F77_CONST_CHAR_ARG_DECL,
00131                            const octave_idx_type&, Complex*,
00132                            const octave_idx_type&, Complex*,
00133                            const octave_idx_type&, double*, Complex*,
00134                            const octave_idx_type&, double*, octave_idx_type&
00135                            F77_CHAR_ARG_LEN_DECL
00136                            F77_CHAR_ARG_LEN_DECL);
00137 }
00138 
00139 octave_idx_type
00140 EIG::init (const Matrix& a, bool calc_ev)
00141 {
00142   if (a.any_element_is_inf_or_nan ())
00143     {
00144       (*current_liboctave_error_handler)
00145         ("EIG: matrix contains Inf or NaN values");
00146       return -1;
00147     }
00148 
00149   if (a.is_symmetric ())
00150     return symmetric_init (a, calc_ev);
00151 
00152   octave_idx_type n = a.rows ();
00153 
00154   if (n != a.cols ())
00155     {
00156       (*current_liboctave_error_handler) ("EIG requires square matrix");
00157       return -1;
00158     }
00159 
00160   octave_idx_type info = 0;
00161 
00162   Matrix atmp = a;
00163   double *tmp_data = atmp.fortran_vec ();
00164 
00165   Array<double> wr (dim_vector (n, 1));
00166   double *pwr = wr.fortran_vec ();
00167 
00168   Array<double> wi (dim_vector (n, 1));
00169   double *pwi = wi.fortran_vec ();
00170 
00171   octave_idx_type tnvr = calc_ev ? n : 0;
00172   Matrix vr (tnvr, tnvr);
00173   double *pvr = vr.fortran_vec ();
00174 
00175   octave_idx_type lwork = -1;
00176   double dummy_work;
00177 
00178   double *dummy = 0;
00179   octave_idx_type idummy = 1;
00180 
00181   F77_XFCN (dgeev, DGEEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00182                            F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00183                            n, tmp_data, n, pwr, pwi, dummy,
00184                            idummy, pvr, n, &dummy_work, lwork, info
00185                            F77_CHAR_ARG_LEN (1)
00186                            F77_CHAR_ARG_LEN (1)));
00187 
00188   if (info == 0)
00189     {
00190       lwork = static_cast<octave_idx_type> (dummy_work);
00191       Array<double> work (dim_vector (lwork, 1));
00192       double *pwork = work.fortran_vec ();
00193 
00194       F77_XFCN (dgeev, DGEEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00195                                F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00196                                n, tmp_data, n, pwr, pwi, dummy,
00197                                idummy, pvr, n, pwork, lwork, info
00198                                F77_CHAR_ARG_LEN (1)
00199                                F77_CHAR_ARG_LEN (1)));
00200 
00201       if (info < 0)
00202         {
00203           (*current_liboctave_error_handler) ("unrecoverable error in dgeev");
00204           return info;
00205         }
00206 
00207       if (info > 0)
00208         {
00209           (*current_liboctave_error_handler) ("dgeev failed to converge");
00210           return info;
00211         }
00212 
00213       lambda.resize (n);
00214       octave_idx_type nvr = calc_ev ? n : 0;
00215       v.resize (nvr, nvr);
00216 
00217       for (octave_idx_type j = 0; j < n; j++)
00218         {
00219           if (wi.elem (j) == 0.0)
00220             {
00221               lambda.elem (j) = Complex (wr.elem (j));
00222               for (octave_idx_type i = 0; i < nvr; i++)
00223                 v.elem (i, j) = vr.elem (i, j);
00224             }
00225           else
00226             {
00227               if (j+1 >= n)
00228                 {
00229                   (*current_liboctave_error_handler) ("EIG: internal error");
00230                   return -1;
00231                 }
00232 
00233               lambda.elem(j) = Complex (wr.elem(j), wi.elem(j));
00234               lambda.elem(j+1) = Complex (wr.elem(j+1), wi.elem(j+1));
00235 
00236               for (octave_idx_type i = 0; i < nvr; i++)
00237                 {
00238                   double real_part = vr.elem (i, j);
00239                   double imag_part = vr.elem (i, j+1);
00240                   v.elem (i, j) = Complex (real_part, imag_part);
00241                   v.elem (i, j+1) = Complex (real_part, -imag_part);
00242                 }
00243               j++;
00244             }
00245         }
00246     }
00247   else
00248     (*current_liboctave_error_handler) ("dgeev workspace query failed");
00249 
00250   return info;
00251 }
00252 
00253 octave_idx_type
00254 EIG::symmetric_init (const Matrix& a, bool calc_ev)
00255 {
00256   octave_idx_type n = a.rows ();
00257 
00258   if (n != a.cols ())
00259     {
00260       (*current_liboctave_error_handler) ("EIG requires square matrix");
00261       return -1;
00262     }
00263 
00264   octave_idx_type info = 0;
00265 
00266   Matrix atmp = a;
00267   double *tmp_data = atmp.fortran_vec ();
00268 
00269   ColumnVector wr (n);
00270   double *pwr = wr.fortran_vec ();
00271 
00272   octave_idx_type lwork = -1;
00273   double dummy_work;
00274 
00275   F77_XFCN (dsyev, DSYEV, (F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00276                            F77_CONST_CHAR_ARG2 ("U", 1),
00277                            n, tmp_data, n, pwr, &dummy_work, lwork, info
00278                            F77_CHAR_ARG_LEN (1)
00279                            F77_CHAR_ARG_LEN (1)));
00280 
00281   if (info == 0)
00282     {
00283       lwork = static_cast<octave_idx_type> (dummy_work);
00284       Array<double> work (dim_vector (lwork, 1));
00285       double *pwork = work.fortran_vec ();
00286 
00287       F77_XFCN (dsyev, DSYEV, (F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00288                                F77_CONST_CHAR_ARG2 ("U", 1),
00289                                n, tmp_data, n, pwr, pwork, lwork, info
00290                                F77_CHAR_ARG_LEN (1)
00291                                F77_CHAR_ARG_LEN (1)));
00292 
00293       if (info < 0)
00294         {
00295           (*current_liboctave_error_handler) ("unrecoverable error in dsyev");
00296           return info;
00297         }
00298 
00299       if (info > 0)
00300         {
00301           (*current_liboctave_error_handler) ("dsyev failed to converge");
00302           return info;
00303         }
00304 
00305       lambda = ComplexColumnVector (wr);
00306       v = calc_ev ? ComplexMatrix (atmp) : ComplexMatrix ();
00307     }
00308   else
00309     (*current_liboctave_error_handler) ("dsyev workspace query failed");
00310 
00311   return info;
00312 }
00313 
00314 octave_idx_type
00315 EIG::init (const ComplexMatrix& a, bool calc_ev)
00316 {
00317   if (a.any_element_is_inf_or_nan ())
00318     {
00319       (*current_liboctave_error_handler)
00320         ("EIG: matrix contains Inf or NaN values");
00321       return -1;
00322     }
00323 
00324   if (a.is_hermitian ())
00325     return hermitian_init (a, calc_ev);
00326 
00327   octave_idx_type n = a.rows ();
00328 
00329   if (n != a.cols ())
00330     {
00331       (*current_liboctave_error_handler) ("EIG requires square matrix");
00332       return -1;
00333     }
00334 
00335   octave_idx_type info = 0;
00336 
00337   ComplexMatrix atmp = a;
00338   Complex *tmp_data = atmp.fortran_vec ();
00339 
00340   ComplexColumnVector w (n);
00341   Complex *pw = w.fortran_vec ();
00342 
00343   octave_idx_type nvr = calc_ev ? n : 0;
00344   ComplexMatrix vtmp (nvr, nvr);
00345   Complex *pv = vtmp.fortran_vec ();
00346 
00347   octave_idx_type lwork = -1;
00348   Complex dummy_work;
00349 
00350   octave_idx_type lrwork = 2*n;
00351   Array<double> rwork (dim_vector (lrwork, 1));
00352   double *prwork = rwork.fortran_vec ();
00353 
00354   Complex *dummy = 0;
00355   octave_idx_type idummy = 1;
00356 
00357   F77_XFCN (zgeev, ZGEEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00358                            F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00359                            n, tmp_data, n, pw, dummy, idummy,
00360                            pv, n, &dummy_work, lwork, prwork, info
00361                            F77_CHAR_ARG_LEN (1)
00362                            F77_CHAR_ARG_LEN (1)));
00363 
00364   if (info == 0)
00365     {
00366       lwork = static_cast<octave_idx_type> (dummy_work.real ());
00367       Array<Complex> work (dim_vector (lwork, 1));
00368       Complex *pwork = work.fortran_vec ();
00369 
00370       F77_XFCN (zgeev, ZGEEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00371                                F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00372                                n, tmp_data, n, pw, dummy, idummy,
00373                                pv, n, pwork, lwork, prwork, info
00374                                F77_CHAR_ARG_LEN (1)
00375                                F77_CHAR_ARG_LEN (1)));
00376 
00377       if (info < 0)
00378         {
00379           (*current_liboctave_error_handler) ("unrecoverable error in zgeev");
00380           return info;
00381         }
00382 
00383       if (info > 0)
00384         {
00385           (*current_liboctave_error_handler) ("zgeev failed to converge");
00386           return info;
00387         }
00388 
00389       lambda = w;
00390       v = vtmp;
00391     }
00392   else
00393     (*current_liboctave_error_handler) ("zgeev workspace query failed");
00394 
00395   return info;
00396 }
00397 
00398 octave_idx_type
00399 EIG::hermitian_init (const ComplexMatrix& a, bool calc_ev)
00400 {
00401   octave_idx_type n = a.rows ();
00402 
00403   if (n != a.cols ())
00404     {
00405       (*current_liboctave_error_handler) ("EIG requires square matrix");
00406       return -1;
00407     }
00408 
00409   octave_idx_type info = 0;
00410 
00411   ComplexMatrix atmp = a;
00412   Complex *tmp_data = atmp.fortran_vec ();
00413 
00414   ColumnVector wr (n);
00415   double *pwr = wr.fortran_vec ();
00416 
00417   octave_idx_type lwork = -1;
00418   Complex dummy_work;
00419 
00420   octave_idx_type lrwork = 3*n;
00421   Array<double> rwork (dim_vector (lrwork, 1));
00422   double *prwork = rwork.fortran_vec ();
00423 
00424   F77_XFCN (zheev, ZHEEV, (F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00425                            F77_CONST_CHAR_ARG2 ("U", 1),
00426                            n, tmp_data, n, pwr, &dummy_work, lwork,
00427                            prwork, info
00428                            F77_CHAR_ARG_LEN (1)
00429                            F77_CHAR_ARG_LEN (1)));
00430 
00431   if (info == 0)
00432     {
00433       lwork = static_cast<octave_idx_type> (dummy_work.real ());
00434       Array<Complex> work (dim_vector (lwork, 1));
00435       Complex *pwork = work.fortran_vec ();
00436 
00437       F77_XFCN (zheev, ZHEEV, (F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00438                                F77_CONST_CHAR_ARG2 ("U", 1),
00439                                n, tmp_data, n, pwr, pwork, lwork, prwork, info
00440                                F77_CHAR_ARG_LEN (1)
00441                                F77_CHAR_ARG_LEN (1)));
00442 
00443       if (info < 0)
00444         {
00445           (*current_liboctave_error_handler) ("unrecoverable error in zheev");
00446           return info;
00447         }
00448 
00449       if (info > 0)
00450         {
00451           (*current_liboctave_error_handler) ("zheev failed to converge");
00452           return info;
00453         }
00454 
00455       lambda = ComplexColumnVector (wr);
00456       v = calc_ev ? ComplexMatrix (atmp) : ComplexMatrix ();
00457     }
00458   else
00459     (*current_liboctave_error_handler) ("zheev workspace query failed");
00460 
00461   return info;
00462 }
00463 
00464 octave_idx_type
00465 EIG::init (const Matrix& a, const Matrix& b, bool calc_ev)
00466 {
00467   if (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ())
00468     {
00469       (*current_liboctave_error_handler)
00470         ("EIG: matrix contains Inf or NaN values");
00471       return -1;
00472     }
00473 
00474   octave_idx_type n = a.rows ();
00475   octave_idx_type nb = b.rows ();
00476 
00477   if (n != a.cols () || nb != b.cols ())
00478     {
00479       (*current_liboctave_error_handler) ("EIG requires square matrix");
00480       return -1;
00481     }
00482 
00483   if (n != nb)
00484     {
00485       (*current_liboctave_error_handler) ("EIG requires same size matrices");
00486       return -1;
00487     }
00488 
00489   octave_idx_type info = 0;
00490 
00491   Matrix tmp = b;
00492   double *tmp_data = tmp.fortran_vec ();
00493 
00494   F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1),
00495                              n, tmp_data, n,
00496                              info
00497                              F77_CHAR_ARG_LEN (1)
00498                              F77_CHAR_ARG_LEN (1)));
00499 
00500   if (a.is_symmetric () && b.is_symmetric () && info == 0)
00501     return symmetric_init (a, b, calc_ev);
00502 
00503   Matrix atmp = a;
00504   double *atmp_data = atmp.fortran_vec ();
00505 
00506   Matrix btmp = b;
00507   double *btmp_data = btmp.fortran_vec ();
00508 
00509   Array<double> ar (dim_vector (n, 1));
00510   double *par = ar.fortran_vec ();
00511 
00512   Array<double> ai (dim_vector (n, 1));
00513   double *pai = ai.fortran_vec ();
00514 
00515   Array<double> beta (dim_vector (n, 1));
00516   double *pbeta = beta.fortran_vec ();
00517 
00518   octave_idx_type tnvr = calc_ev ? n : 0;
00519   Matrix vr (tnvr, tnvr);
00520   double *pvr = vr.fortran_vec ();
00521 
00522   octave_idx_type lwork = -1;
00523   double dummy_work;
00524 
00525   double *dummy = 0;
00526   octave_idx_type idummy = 1;
00527 
00528   F77_XFCN (dggev, DGGEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00529                            F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00530                            n, atmp_data, n, btmp_data, n,
00531                            par, pai, pbeta,
00532                            dummy, idummy, pvr, n,
00533                            &dummy_work, lwork, info
00534                            F77_CHAR_ARG_LEN (1)
00535                            F77_CHAR_ARG_LEN (1)));
00536 
00537   if (info == 0)
00538     {
00539       lwork = static_cast<octave_idx_type> (dummy_work);
00540       Array<double> work (dim_vector (lwork, 1));
00541       double *pwork = work.fortran_vec ();
00542 
00543       F77_XFCN (dggev, DGGEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00544                                F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00545                                n, atmp_data, n, btmp_data, n,
00546                                par, pai, pbeta,
00547                                dummy, idummy, pvr, n,
00548                                pwork, lwork, info
00549                                F77_CHAR_ARG_LEN (1)
00550                                F77_CHAR_ARG_LEN (1)));
00551 
00552       if (info < 0)
00553         {
00554           (*current_liboctave_error_handler) ("unrecoverable error in dggev");
00555           return info;
00556         }
00557 
00558       if (info > 0)
00559         {
00560           (*current_liboctave_error_handler) ("dggev failed to converge");
00561           return info;
00562         }
00563 
00564       lambda.resize (n);
00565       octave_idx_type nvr = calc_ev ? n : 0;
00566       v.resize (nvr, nvr);
00567 
00568       for (octave_idx_type j = 0; j < n; j++)
00569         {
00570           if (ai.elem (j) == 0.0)
00571             {
00572               lambda.elem (j) = Complex (ar.elem (j) / beta.elem (j));
00573               for (octave_idx_type i = 0; i < nvr; i++)
00574                 v.elem (i, j) = vr.elem (i, j);
00575             }
00576           else
00577             {
00578               if (j+1 >= n)
00579                 {
00580                   (*current_liboctave_error_handler) ("EIG: internal error");
00581                   return -1;
00582                 }
00583 
00584               lambda.elem(j) = Complex (ar.elem(j) / beta.elem (j),
00585                                         ai.elem(j) / beta.elem (j));
00586               lambda.elem(j+1) = Complex (ar.elem(j+1) / beta.elem (j+1),
00587                                           ai.elem(j+1) / beta.elem (j+1));
00588 
00589               for (octave_idx_type i = 0; i < nvr; i++)
00590                 {
00591                   double real_part = vr.elem (i, j);
00592                   double imag_part = vr.elem (i, j+1);
00593                   v.elem (i, j) = Complex (real_part, imag_part);
00594                   v.elem (i, j+1) = Complex (real_part, -imag_part);
00595                 }
00596               j++;
00597             }
00598         }
00599     }
00600   else
00601     (*current_liboctave_error_handler) ("dggev workspace query failed");
00602 
00603   return info;
00604 }
00605 
00606 octave_idx_type
00607 EIG::symmetric_init (const Matrix& a, const Matrix& b, bool calc_ev)
00608 {
00609   octave_idx_type n = a.rows ();
00610   octave_idx_type nb = b.rows ();
00611 
00612   if (n != a.cols () || nb != b.cols ())
00613     {
00614       (*current_liboctave_error_handler) ("EIG requires square matrix");
00615       return -1;
00616     }
00617 
00618   if (n != nb)
00619     {
00620       (*current_liboctave_error_handler) ("EIG requires same size matrices");
00621       return -1;
00622     }
00623 
00624   octave_idx_type info = 0;
00625 
00626   Matrix atmp = a;
00627   double *atmp_data = atmp.fortran_vec ();
00628 
00629   Matrix btmp = b;
00630   double *btmp_data = btmp.fortran_vec ();
00631 
00632   ColumnVector wr (n);
00633   double *pwr = wr.fortran_vec ();
00634 
00635   octave_idx_type lwork = -1;
00636   double dummy_work;
00637 
00638   F77_XFCN (dsygv, DSYGV, (1, F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00639                            F77_CONST_CHAR_ARG2 ("U", 1),
00640                            n, atmp_data, n,
00641                            btmp_data, n,
00642                            pwr, &dummy_work, lwork, info
00643                            F77_CHAR_ARG_LEN (1)
00644                            F77_CHAR_ARG_LEN (1)));
00645 
00646   if (info == 0)
00647     {
00648       lwork = static_cast<octave_idx_type> (dummy_work);
00649       Array<double> work (dim_vector (lwork, 1));
00650       double *pwork = work.fortran_vec ();
00651 
00652       F77_XFCN (dsygv, DSYGV, (1, F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00653                                F77_CONST_CHAR_ARG2 ("U", 1),
00654                                n, atmp_data, n,
00655                                btmp_data, n,
00656                                pwr, pwork, lwork, info
00657                                F77_CHAR_ARG_LEN (1)
00658                                F77_CHAR_ARG_LEN (1)));
00659 
00660       if (info < 0)
00661         {
00662           (*current_liboctave_error_handler) ("unrecoverable error in dsygv");
00663           return info;
00664         }
00665 
00666       if (info > 0)
00667         {
00668           (*current_liboctave_error_handler) ("dsygv failed to converge");
00669           return info;
00670         }
00671 
00672       lambda = ComplexColumnVector (wr);
00673       v = calc_ev ? ComplexMatrix (atmp) : ComplexMatrix ();
00674     }
00675   else
00676     (*current_liboctave_error_handler) ("dsygv workspace query failed");
00677 
00678   return info;
00679 }
00680 
00681 octave_idx_type
00682 EIG::init (const ComplexMatrix& a, const ComplexMatrix& b, bool calc_ev)
00683 {
00684   if (a.any_element_is_inf_or_nan () || b.any_element_is_inf_or_nan ())
00685     {
00686       (*current_liboctave_error_handler)
00687         ("EIG: matrix contains Inf or NaN values");
00688       return -1;
00689     }
00690 
00691   octave_idx_type n = a.rows ();
00692   octave_idx_type nb = b.rows ();
00693 
00694   if (n != a.cols () || nb != b.cols())
00695     {
00696       (*current_liboctave_error_handler) ("EIG requires square matrix");
00697       return -1;
00698     }
00699 
00700   if (n != nb)
00701     {
00702       (*current_liboctave_error_handler) ("EIG requires same size matrices");
00703       return -1;
00704     }
00705 
00706   octave_idx_type info = 0;
00707 
00708   ComplexMatrix tmp = b;
00709   Complex*tmp_data = tmp.fortran_vec ();
00710 
00711   F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1),
00712                              n, tmp_data, n,
00713                              info
00714                              F77_CHAR_ARG_LEN (1)
00715                              F77_CHAR_ARG_LEN (1)));
00716 
00717   if (a.is_hermitian () && b.is_hermitian () && info == 0)
00718     return hermitian_init (a, calc_ev);
00719 
00720   ComplexMatrix atmp = a;
00721   Complex *atmp_data = atmp.fortran_vec ();
00722 
00723   ComplexMatrix btmp = b;
00724   Complex *btmp_data = btmp.fortran_vec ();
00725 
00726   ComplexColumnVector alpha (n);
00727   Complex *palpha = alpha.fortran_vec ();
00728 
00729   ComplexColumnVector beta (n);
00730   Complex *pbeta = beta.fortran_vec ();
00731 
00732   octave_idx_type nvr = calc_ev ? n : 0;
00733   ComplexMatrix vtmp (nvr, nvr);
00734   Complex *pv = vtmp.fortran_vec ();
00735 
00736   octave_idx_type lwork = -1;
00737   Complex dummy_work;
00738 
00739   octave_idx_type lrwork = 8*n;
00740   Array<double> rwork (dim_vector (lrwork, 1));
00741   double *prwork = rwork.fortran_vec ();
00742 
00743   Complex *dummy = 0;
00744   octave_idx_type idummy = 1;
00745 
00746   F77_XFCN (zggev, ZGGEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00747                            F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00748                            n, atmp_data, n, btmp_data, n,
00749                            palpha, pbeta, dummy, idummy,
00750                            pv, n, &dummy_work, lwork, prwork, info
00751                            F77_CHAR_ARG_LEN (1)
00752                            F77_CHAR_ARG_LEN (1)));
00753 
00754   if (info == 0)
00755     {
00756       lwork = static_cast<octave_idx_type> (dummy_work.real ());
00757       Array<Complex> work (dim_vector (lwork, 1));
00758       Complex *pwork = work.fortran_vec ();
00759 
00760       F77_XFCN (zggev, ZGGEV, (F77_CONST_CHAR_ARG2 ("N", 1),
00761                                F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00762                                n, atmp_data, n, btmp_data, n,
00763                                palpha, pbeta, dummy, idummy,
00764                                pv, n, pwork, lwork, prwork, info
00765                                F77_CHAR_ARG_LEN (1)
00766                                F77_CHAR_ARG_LEN (1)));
00767 
00768       if (info < 0)
00769         {
00770           (*current_liboctave_error_handler) ("unrecoverable error in zggev");
00771           return info;
00772         }
00773 
00774       if (info > 0)
00775         {
00776           (*current_liboctave_error_handler) ("zggev failed to converge");
00777           return info;
00778         }
00779 
00780       lambda.resize (n);
00781 
00782       for (octave_idx_type j = 0; j < n; j++)
00783         lambda.elem (j) = alpha.elem (j) / beta.elem(j);
00784 
00785       v = vtmp;
00786     }
00787   else
00788     (*current_liboctave_error_handler) ("zggev workspace query failed");
00789 
00790   return info;
00791 }
00792 
00793 octave_idx_type
00794 EIG::hermitian_init (const ComplexMatrix& a, const ComplexMatrix& b, bool calc_ev)
00795 {
00796   octave_idx_type n = a.rows ();
00797   octave_idx_type nb = b.rows ();
00798 
00799   if (n != a.cols () || nb != b.cols ())
00800     {
00801       (*current_liboctave_error_handler) ("EIG requires square matrix");
00802       return -1;
00803     }
00804 
00805   if (n != nb)
00806     {
00807       (*current_liboctave_error_handler) ("EIG requires same size matrices");
00808       return -1;
00809     }
00810 
00811   octave_idx_type info = 0;
00812 
00813   ComplexMatrix atmp = a;
00814   Complex *atmp_data = atmp.fortran_vec ();
00815 
00816   ComplexMatrix btmp = b;
00817   Complex *btmp_data = btmp.fortran_vec ();
00818 
00819   ColumnVector wr (n);
00820   double *pwr = wr.fortran_vec ();
00821 
00822   octave_idx_type lwork = -1;
00823   Complex dummy_work;
00824 
00825   octave_idx_type lrwork = 3*n;
00826   Array<double> rwork (dim_vector (lrwork, 1));
00827   double *prwork = rwork.fortran_vec ();
00828 
00829   F77_XFCN (zhegv, ZHEGV, (1, F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00830                            F77_CONST_CHAR_ARG2 ("U", 1),
00831                            n, atmp_data, n,
00832                            btmp_data, n,
00833                            pwr, &dummy_work, lwork,
00834                            prwork, info
00835                            F77_CHAR_ARG_LEN (1)
00836                            F77_CHAR_ARG_LEN (1)));
00837 
00838   if (info == 0)
00839     {
00840       lwork = static_cast<octave_idx_type> (dummy_work.real ());
00841       Array<Complex> work (dim_vector (lwork, 1));
00842       Complex *pwork = work.fortran_vec ();
00843 
00844       F77_XFCN (zhegv, ZHEGV, (1, F77_CONST_CHAR_ARG2 (calc_ev ? "V" : "N", 1),
00845                                F77_CONST_CHAR_ARG2 ("U", 1),
00846                                n, atmp_data, n,
00847                                btmp_data, n,
00848                                pwr, pwork, lwork, prwork, info
00849                                F77_CHAR_ARG_LEN (1)
00850                                F77_CHAR_ARG_LEN (1)));
00851 
00852       if (info < 0)
00853         {
00854           (*current_liboctave_error_handler) ("unrecoverable error in zhegv");
00855           return info;
00856         }
00857 
00858       if (info > 0)
00859         {
00860           (*current_liboctave_error_handler) ("zhegv failed to converge");
00861           return info;
00862         }
00863 
00864       lambda = ComplexColumnVector (wr);
00865       v = calc_ev ? ComplexMatrix (atmp) : ComplexMatrix ();
00866     }
00867   else
00868     (*current_liboctave_error_handler) ("zhegv workspace query failed");
00869 
00870   return info;
00871 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines