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