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 "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 }