00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 }