gsl_eigen__genv.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. /* eigen/genv.c
  2. *
  3. * Copyright (C) 2007 Patrick Alken
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. #include <stdlib.h>
  20. #include <math.h>
  21. #include "gsl__config.h"
  22. #include "gsl_eigen.h"
  23. #include "gsl_linalg.h"
  24. #include "gsl_math.h"
  25. #include "gsl_blas.h"
  26. #include "gsl_vector.h"
  27. #include "gsl_vector_complex.h"
  28. #include "gsl_matrix.h"
  29. #include "gsl_errno.h"
  30. /*
  31. * This module computes the eigenvalues and eigenvectors of a
  32. * real generalized eigensystem A x = \lambda B x. Left and right
  33. * Schur vectors are optionally computed as well.
  34. *
  35. * This file contains routines based on original code from LAPACK
  36. * which is distributed under the modified BSD license.
  37. */
  38. static int genv_get_right_eigenvectors(const gsl_matrix *S,
  39. const gsl_matrix *T,
  40. gsl_matrix *Z,
  41. gsl_matrix_complex *evec,
  42. gsl_eigen_genv_workspace *w);
  43. static void genv_normalize_eigenvectors(gsl_vector_complex *alpha,
  44. gsl_matrix_complex *evec);
  45. /*
  46. gsl_eigen_genv_alloc()
  47. Allocate a workspace for solving the generalized eigenvalue problem.
  48. The size of this workspace is O(7n).
  49. Inputs: n - size of matrices
  50. Return: pointer to workspace
  51. */
  52. gsl_eigen_genv_workspace *
  53. gsl_eigen_genv_alloc(const size_t n)
  54. {
  55. gsl_eigen_genv_workspace *w;
  56. if (n == 0)
  57. {
  58. GSL_ERROR_NULL ("matrix dimension must be positive integer",
  59. GSL_EINVAL);
  60. }
  61. w = (gsl_eigen_genv_workspace *) calloc (1, sizeof (gsl_eigen_genv_workspace));
  62. if (w == 0)
  63. {
  64. GSL_ERROR_NULL ("failed to allocate space for workspace", GSL_ENOMEM);
  65. }
  66. w->size = n;
  67. w->Q = NULL;
  68. w->Z = NULL;
  69. w->gen_workspace_p = gsl_eigen_gen_alloc(n);
  70. if (w->gen_workspace_p == 0)
  71. {
  72. gsl_eigen_genv_free(w);
  73. GSL_ERROR_NULL ("failed to allocate space for gen workspace", GSL_ENOMEM);
  74. }
  75. /* compute the full Schur forms */
  76. gsl_eigen_gen_params(1, 1, 1, w->gen_workspace_p);
  77. w->work1 = gsl_vector_alloc(n);
  78. w->work2 = gsl_vector_alloc(n);
  79. w->work3 = gsl_vector_alloc(n);
  80. w->work4 = gsl_vector_alloc(n);
  81. w->work5 = gsl_vector_alloc(n);
  82. w->work6 = gsl_vector_alloc(n);
  83. if (w->work1 == 0 || w->work2 == 0 || w->work3 == 0 ||
  84. w->work4 == 0 || w->work5 == 0 || w->work6 == 0)
  85. {
  86. gsl_eigen_genv_free(w);
  87. GSL_ERROR_NULL ("failed to allocate space for additional workspace", GSL_ENOMEM);
  88. }
  89. return (w);
  90. } /* gsl_eigen_genv_alloc() */
  91. /*
  92. gsl_eigen_genv_free()
  93. Free workspace w
  94. */
  95. void
  96. gsl_eigen_genv_free(gsl_eigen_genv_workspace *w)
  97. {
  98. if (w->gen_workspace_p)
  99. gsl_eigen_gen_free(w->gen_workspace_p);
  100. if (w->work1)
  101. gsl_vector_free(w->work1);
  102. if (w->work2)
  103. gsl_vector_free(w->work2);
  104. if (w->work3)
  105. gsl_vector_free(w->work3);
  106. if (w->work4)
  107. gsl_vector_free(w->work4);
  108. if (w->work5)
  109. gsl_vector_free(w->work5);
  110. if (w->work6)
  111. gsl_vector_free(w->work6);
  112. free(w);
  113. } /* gsl_eigen_genv_free() */
  114. /*
  115. gsl_eigen_genv()
  116. Solve the generalized eigenvalue problem
  117. A x = \lambda B x
  118. for the eigenvalues \lambda and right eigenvectors x.
  119. Inputs: A - general real matrix
  120. B - general real matrix
  121. alpha - (output) where to store eigenvalue numerators
  122. beta - (output) where to store eigenvalue denominators
  123. evec - (output) where to store eigenvectors
  124. w - workspace
  125. Return: success or error
  126. */
  127. int
  128. gsl_eigen_genv (gsl_matrix * A, gsl_matrix * B, gsl_vector_complex * alpha,
  129. gsl_vector * beta, gsl_matrix_complex *evec,
  130. gsl_eigen_genv_workspace * w)
  131. {
  132. const size_t N = A->size1;
  133. /* check matrix and vector sizes */
  134. if (N != A->size2)
  135. {
  136. GSL_ERROR ("matrix must be square to compute eigenvalues", GSL_ENOTSQR);
  137. }
  138. else if ((N != B->size1) || (N != B->size2))
  139. {
  140. GSL_ERROR ("B matrix dimensions must match A", GSL_EBADLEN);
  141. }
  142. else if (alpha->size != N || beta->size != N)
  143. {
  144. GSL_ERROR ("eigenvalue vector must match matrix size", GSL_EBADLEN);
  145. }
  146. else if (w->size != N)
  147. {
  148. GSL_ERROR ("matrix size does not match workspace", GSL_EBADLEN);
  149. }
  150. else if (evec->size1 != N)
  151. {
  152. GSL_ERROR ("eigenvector matrix has wrong size", GSL_EBADLEN);
  153. }
  154. else
  155. {
  156. int s;
  157. gsl_matrix Z;
  158. /*
  159. * We need a place to store the right Schur vectors, so we will
  160. * treat evec as a real matrix and store them in the left
  161. * half - the factor of 2 in the tda corresponds to the
  162. * complex multiplicity
  163. */
  164. Z.size1 = N;
  165. Z.size2 = N;
  166. Z.tda = 2 * N;
  167. Z.data = evec->data;
  168. Z.block = 0;
  169. Z.owner = 0;
  170. s = gsl_eigen_gen_QZ(A, B, alpha, beta, w->Q, &Z, w->gen_workspace_p);
  171. if (w->Z)
  172. {
  173. /* save right Schur vectors */
  174. gsl_matrix_memcpy(w->Z, &Z);
  175. }
  176. /* only compute eigenvectors if we found all eigenvalues */
  177. if (s == GSL_SUCCESS)
  178. {
  179. /* compute eigenvectors */
  180. s = genv_get_right_eigenvectors(A, B, &Z, evec, w);
  181. if (s == GSL_SUCCESS)
  182. genv_normalize_eigenvectors(alpha, evec);
  183. }
  184. return s;
  185. }
  186. } /* gsl_eigen_genv() */
  187. /*
  188. gsl_eigen_genv_QZ()
  189. Solve the generalized eigenvalue problem
  190. A x = \lambda B x
  191. for the eigenvalues \lambda and right eigenvectors x. Optionally
  192. compute left and/or right Schur vectors Q and Z which satisfy:
  193. A = Q S Z^t
  194. B = Q T Z^t
  195. where (S, T) is the generalized Schur form of (A, B)
  196. Inputs: A - general real matrix
  197. B - general real matrix
  198. alpha - (output) where to store eigenvalue numerators
  199. beta - (output) where to store eigenvalue denominators
  200. evec - (output) where to store eigenvectors
  201. Q - (output) if non-null, where to store left Schur vectors
  202. Z - (output) if non-null, where to store right Schur vectors
  203. w - workspace
  204. Return: success or error
  205. */
  206. int
  207. gsl_eigen_genv_QZ (gsl_matrix * A, gsl_matrix * B,
  208. gsl_vector_complex * alpha, gsl_vector * beta,
  209. gsl_matrix_complex * evec,
  210. gsl_matrix * Q, gsl_matrix * Z,
  211. gsl_eigen_genv_workspace * w)
  212. {
  213. if (Q && (A->size1 != Q->size1 || A->size1 != Q->size2))
  214. {
  215. GSL_ERROR("Q matrix has wrong dimensions", GSL_EBADLEN);
  216. }
  217. else if (Z && (A->size1 != Z->size1 || A->size1 != Z->size2))
  218. {
  219. GSL_ERROR("Z matrix has wrong dimensions", GSL_EBADLEN);
  220. }
  221. else
  222. {
  223. int s;
  224. w->Q = Q;
  225. w->Z = Z;
  226. s = gsl_eigen_genv(A, B, alpha, beta, evec, w);
  227. w->Q = NULL;
  228. w->Z = NULL;
  229. return s;
  230. }
  231. } /* gsl_eigen_genv_QZ() */
  232. /********************************************
  233. * INTERNAL ROUTINES *
  234. ********************************************/
  235. /*
  236. genv_get_right_eigenvectors()
  237. Compute right eigenvectors of the Schur form (S, T) and then
  238. backtransform them using the right Schur vectors to get right
  239. eigenvectors of the original system.
  240. Inputs: S - upper quasi-triangular Schur form of A
  241. T - upper triangular Schur form of B
  242. Z - right Schur vectors
  243. evec - (output) where to store eigenvectors
  244. w - workspace
  245. Return: success or error
  246. Notes: 1) based on LAPACK routine DTGEVC
  247. 2) eigenvectors are stored in the order that their
  248. eigenvalues appear in the Schur form
  249. */
  250. static int
  251. genv_get_right_eigenvectors(const gsl_matrix *S, const gsl_matrix *T,
  252. gsl_matrix *Z,
  253. gsl_matrix_complex *evec,
  254. gsl_eigen_genv_workspace *w)
  255. {
  256. const size_t N = w->size;
  257. const double small = GSL_DBL_MIN * N / GSL_DBL_EPSILON;
  258. const double big = 1.0 / small;
  259. const double bignum = 1.0 / (GSL_DBL_MIN * N);
  260. size_t i, j, k, end;
  261. int is;
  262. double anorm, bnorm;
  263. double temp, temp2, temp2r, temp2i;
  264. double ascale, bscale;
  265. double salfar, sbeta;
  266. double acoef, bcoefr, bcoefi, acoefa, bcoefa;
  267. double creala, cimaga, crealb, cimagb, cre2a, cim2a, cre2b, cim2b;
  268. double dmin, xmax;
  269. double scale;
  270. size_t nw, na;
  271. int lsa, lsb;
  272. int complex_pair;
  273. gsl_complex z_zero, z_one;
  274. double bdiag[2] = { 0.0, 0.0 };
  275. double sum[4];
  276. int il2by2;
  277. size_t jr, jc, ja;
  278. double xscale;
  279. gsl_vector_complex_view ecol;
  280. gsl_vector_view re, im, re2, im2;
  281. GSL_SET_COMPLEX(&z_zero, 0.0, 0.0);
  282. GSL_SET_COMPLEX(&z_one, 1.0, 0.0);
  283. /*
  284. * Compute the 1-norm of each column of (S, T) excluding elements
  285. * belonging to the diagonal blocks to check for possible overflow
  286. * in the triangular solver
  287. */
  288. anorm = fabs(gsl_matrix_get(S, 0, 0));
  289. if (N > 1)
  290. anorm += fabs(gsl_matrix_get(S, 1, 0));
  291. bnorm = fabs(gsl_matrix_get(T, 0, 0));
  292. gsl_vector_set(w->work1, 0, 0.0);
  293. gsl_vector_set(w->work2, 0, 0.0);
  294. for (j = 1; j < N; ++j)
  295. {
  296. temp = temp2 = 0.0;
  297. if (gsl_matrix_get(S, j, j - 1) == 0.0)
  298. end = j;
  299. else
  300. end = j - 1;
  301. for (i = 0; i < end; ++i)
  302. {
  303. temp += fabs(gsl_matrix_get(S, i, j));
  304. temp2 += fabs(gsl_matrix_get(T, i, j));
  305. }
  306. gsl_vector_set(w->work1, j, temp);
  307. gsl_vector_set(w->work2, j, temp2);
  308. for (i = end; i < GSL_MIN(j + 2, N); ++i)
  309. {
  310. temp += fabs(gsl_matrix_get(S, i, j));
  311. temp2 += fabs(gsl_matrix_get(T, i, j));
  312. }
  313. anorm = GSL_MAX(anorm, temp);
  314. bnorm = GSL_MAX(bnorm, temp2);
  315. }
  316. ascale = 1.0 / GSL_MAX(anorm, GSL_DBL_MIN);
  317. bscale = 1.0 / GSL_MAX(bnorm, GSL_DBL_MIN);
  318. complex_pair = 0;
  319. for (k = 0; k < N; ++k)
  320. {
  321. size_t je = N - 1 - k;
  322. if (complex_pair)
  323. {
  324. complex_pair = 0;
  325. continue;
  326. }
  327. nw = 1;
  328. if (je > 0)
  329. {
  330. if (gsl_matrix_get(S, je, je - 1) != 0.0)
  331. {
  332. complex_pair = 1;
  333. nw = 2;
  334. }
  335. }
  336. if (!complex_pair)
  337. {
  338. if (fabs(gsl_matrix_get(S, je, je)) <= GSL_DBL_MIN &&
  339. fabs(gsl_matrix_get(T, je, je)) <= GSL_DBL_MIN)
  340. {
  341. /* singular matrix pencil - unit eigenvector */
  342. for (i = 0; i < N; ++i)
  343. gsl_matrix_complex_set(evec, i, je, z_zero);
  344. gsl_matrix_complex_set(evec, je, je, z_one);
  345. continue;
  346. }
  347. /* clear vector */
  348. for (i = 0; i < N; ++i)
  349. gsl_vector_set(w->work3, i, 0.0);
  350. }
  351. else
  352. {
  353. /* clear vectors */
  354. for (i = 0; i < N; ++i)
  355. {
  356. gsl_vector_set(w->work3, i, 0.0);
  357. gsl_vector_set(w->work4, i, 0.0);
  358. }
  359. }
  360. if (!complex_pair)
  361. {
  362. /* real eigenvalue */
  363. temp = 1.0 / GSL_MAX(GSL_DBL_MIN,
  364. GSL_MAX(fabs(gsl_matrix_get(S, je, je)) * ascale,
  365. fabs(gsl_matrix_get(T, je, je)) * bscale));
  366. salfar = (temp * gsl_matrix_get(S, je, je)) * ascale;
  367. sbeta = (temp * gsl_matrix_get(T, je, je)) * bscale;
  368. acoef = sbeta * ascale;
  369. bcoefr = salfar * bscale;
  370. bcoefi = 0.0;
  371. /* scale to avoid underflow */
  372. scale = 1.0;
  373. lsa = fabs(sbeta) >= GSL_DBL_MIN && fabs(acoef) < small;
  374. lsb = fabs(salfar) >= GSL_DBL_MIN && fabs(bcoefr) < small;
  375. if (lsa)
  376. scale = (small / fabs(sbeta)) * GSL_MIN(anorm, big);
  377. if (lsb)
  378. scale = GSL_MAX(scale, (small / fabs(salfar)) * GSL_MIN(bnorm, big));
  379. if (lsa || lsb)
  380. {
  381. scale = GSL_MIN(scale,
  382. 1.0 / (GSL_DBL_MIN *
  383. GSL_MAX(1.0,
  384. GSL_MAX(fabs(acoef), fabs(bcoefr)))));
  385. if (lsa)
  386. acoef = ascale * (scale * sbeta);
  387. else
  388. acoef *= scale;
  389. if (lsb)
  390. bcoefr = bscale * (scale * salfar);
  391. else
  392. bcoefr *= scale;
  393. }
  394. acoefa = fabs(acoef);
  395. bcoefa = fabs(bcoefr);
  396. /* first component is 1 */
  397. gsl_vector_set(w->work3, je, 1.0);
  398. xmax = 1.0;
  399. /* compute contribution from column je of A and B to sum */
  400. for (i = 0; i < je; ++i)
  401. {
  402. gsl_vector_set(w->work3, i,
  403. bcoefr*gsl_matrix_get(T, i, je) -
  404. acoef * gsl_matrix_get(S, i, je));
  405. }
  406. }
  407. else
  408. {
  409. gsl_matrix_const_view vs =
  410. gsl_matrix_const_submatrix(S, je - 1, je - 1, 2, 2);
  411. gsl_matrix_const_view vt =
  412. gsl_matrix_const_submatrix(T, je - 1, je - 1, 2, 2);
  413. /* complex eigenvalue */
  414. gsl_schur_gen_eigvals(&vs.matrix,
  415. &vt.matrix,
  416. &bcoefr,
  417. &temp2,
  418. &bcoefi,
  419. &acoef,
  420. &temp);
  421. if (bcoefi == 0.0)
  422. {
  423. GSL_ERROR("gsl_schur_gen_eigvals failed on complex block", GSL_FAILURE);
  424. }
  425. /* scale to avoid over/underflow */
  426. acoefa = fabs(acoef);
  427. bcoefa = fabs(bcoefr) + fabs(bcoefi);
  428. scale = 1.0;
  429. if (acoefa*GSL_DBL_EPSILON < GSL_DBL_MIN && acoefa >= GSL_DBL_MIN)
  430. scale = (GSL_DBL_MIN / GSL_DBL_EPSILON) / acoefa;
  431. if (bcoefa*GSL_DBL_EPSILON < GSL_DBL_MIN && bcoefa >= GSL_DBL_MIN)
  432. scale = GSL_MAX(scale, (GSL_DBL_MIN/GSL_DBL_EPSILON) / bcoefa);
  433. if (GSL_DBL_MIN*acoefa > ascale)
  434. scale = ascale / (GSL_DBL_MIN * acoefa);
  435. if (GSL_DBL_MIN*bcoefa > bscale)
  436. scale = GSL_MIN(scale, bscale / (GSL_DBL_MIN*bcoefa));
  437. if (scale != 1.0)
  438. {
  439. acoef *= scale;
  440. acoefa = fabs(acoef);
  441. bcoefr *= scale;
  442. bcoefi *= scale;
  443. bcoefa = fabs(bcoefr) + fabs(bcoefi);
  444. }
  445. /* compute first two components of eigenvector */
  446. temp = acoef * gsl_matrix_get(S, je, je - 1);
  447. temp2r = acoef * gsl_matrix_get(S, je, je) -
  448. bcoefr * gsl_matrix_get(T, je, je);
  449. temp2i = -bcoefi * gsl_matrix_get(T, je, je);
  450. if (fabs(temp) >= fabs(temp2r) + fabs(temp2i))
  451. {
  452. gsl_vector_set(w->work3, je, 1.0);
  453. gsl_vector_set(w->work4, je, 0.0);
  454. gsl_vector_set(w->work3, je - 1, -temp2r / temp);
  455. gsl_vector_set(w->work4, je - 1, -temp2i / temp);
  456. }
  457. else
  458. {
  459. gsl_vector_set(w->work3, je - 1, 1.0);
  460. gsl_vector_set(w->work4, je - 1, 0.0);
  461. temp = acoef * gsl_matrix_get(S, je - 1, je);
  462. gsl_vector_set(w->work3, je,
  463. (bcoefr*gsl_matrix_get(T, je - 1, je - 1) -
  464. acoef*gsl_matrix_get(S, je - 1, je - 1)) / temp);
  465. gsl_vector_set(w->work4, je,
  466. bcoefi*gsl_matrix_get(T, je - 1, je - 1) / temp);
  467. }
  468. xmax = GSL_MAX(fabs(gsl_vector_get(w->work3, je)) +
  469. fabs(gsl_vector_get(w->work4, je)),
  470. fabs(gsl_vector_get(w->work3, je - 1)) +
  471. fabs(gsl_vector_get(w->work4, je - 1)));
  472. /* compute contribution from column je and je - 1 */
  473. creala = acoef * gsl_vector_get(w->work3, je - 1);
  474. cimaga = acoef * gsl_vector_get(w->work4, je - 1);
  475. crealb = bcoefr * gsl_vector_get(w->work3, je - 1) -
  476. bcoefi * gsl_vector_get(w->work4, je - 1);
  477. cimagb = bcoefi * gsl_vector_get(w->work3, je - 1) +
  478. bcoefr * gsl_vector_get(w->work4, je - 1);
  479. cre2a = acoef * gsl_vector_get(w->work3, je);
  480. cim2a = acoef * gsl_vector_get(w->work4, je);
  481. cre2b = bcoefr * gsl_vector_get(w->work3, je) -
  482. bcoefi * gsl_vector_get(w->work4, je);
  483. cim2b = bcoefi * gsl_vector_get(w->work3, je) +
  484. bcoefr * gsl_vector_get(w->work4, je);
  485. for (i = 0; i < je - 1; ++i)
  486. {
  487. gsl_vector_set(w->work3, i,
  488. -creala * gsl_matrix_get(S, i, je - 1) +
  489. crealb * gsl_matrix_get(T, i, je - 1) -
  490. cre2a * gsl_matrix_get(S, i, je) +
  491. cre2b * gsl_matrix_get(T, i, je));
  492. gsl_vector_set(w->work4, i,
  493. -cimaga * gsl_matrix_get(S, i, je - 1) +
  494. cimagb * gsl_matrix_get(T, i, je - 1) -
  495. cim2a * gsl_matrix_get(S, i, je) +
  496. cim2b * gsl_matrix_get(T, i, je));
  497. }
  498. }
  499. dmin = GSL_MAX(GSL_DBL_MIN,
  500. GSL_MAX(GSL_DBL_EPSILON*acoefa*anorm,
  501. GSL_DBL_EPSILON*bcoefa*bnorm));
  502. /* triangular solve of (a A - b B) x = 0 */
  503. il2by2 = 0;
  504. for (is = (int) je - (int) nw; is >= 0; --is)
  505. {
  506. j = (size_t) is;
  507. if (!il2by2 && j > 0)
  508. {
  509. if (gsl_matrix_get(S, j, j - 1) != 0.0)
  510. {
  511. il2by2 = 1;
  512. continue;
  513. }
  514. }
  515. bdiag[0] = gsl_matrix_get(T, j, j);
  516. if (il2by2)
  517. {
  518. na = 2;
  519. bdiag[1] = gsl_matrix_get(T, j + 1, j + 1);
  520. }
  521. else
  522. na = 1;
  523. if (nw == 1)
  524. {
  525. gsl_matrix_const_view sv =
  526. gsl_matrix_const_submatrix(S, j, j, na, na);
  527. gsl_vector_view xv, bv;
  528. bv = gsl_vector_subvector(w->work3, j, na);
  529. /*
  530. * the loop below expects the solution in the first column
  531. * of sum, so set stride to 2
  532. */
  533. xv = gsl_vector_view_array_with_stride(sum, 2, na);
  534. gsl_schur_solve_equation(acoef,
  535. &sv.matrix,
  536. bcoefr,
  537. bdiag[0],
  538. bdiag[1],
  539. &bv.vector,
  540. &xv.vector,
  541. &scale,
  542. &temp,
  543. dmin);
  544. }
  545. else
  546. {
  547. double bdat[4];
  548. gsl_matrix_const_view sv =
  549. gsl_matrix_const_submatrix(S, j, j, na, na);
  550. gsl_vector_complex_view xv =
  551. gsl_vector_complex_view_array(sum, na);
  552. gsl_vector_complex_view bv =
  553. gsl_vector_complex_view_array(bdat, na);
  554. gsl_complex z;
  555. bdat[0] = gsl_vector_get(w->work3, j);
  556. bdat[1] = gsl_vector_get(w->work4, j);
  557. if (na == 2)
  558. {
  559. bdat[2] = gsl_vector_get(w->work3, j + 1);
  560. bdat[3] = gsl_vector_get(w->work4, j + 1);
  561. }
  562. GSL_SET_COMPLEX(&z, bcoefr, bcoefi);
  563. gsl_schur_solve_equation_z(acoef,
  564. &sv.matrix,
  565. &z,
  566. bdiag[0],
  567. bdiag[1],
  568. &bv.vector,
  569. &xv.vector,
  570. &scale,
  571. &temp,
  572. dmin);
  573. }
  574. if (scale < 1.0)
  575. {
  576. for (jr = 0; jr <= je; ++jr)
  577. {
  578. gsl_vector_set(w->work3, jr,
  579. scale * gsl_vector_get(w->work3, jr));
  580. if (nw == 2)
  581. {
  582. gsl_vector_set(w->work4, jr,
  583. scale * gsl_vector_get(w->work4, jr));
  584. }
  585. }
  586. }
  587. xmax = GSL_MAX(scale * xmax, temp);
  588. for (jr = 0; jr < na; ++jr)
  589. {
  590. gsl_vector_set(w->work3, j + jr, sum[jr*na]);
  591. if (nw == 2)
  592. gsl_vector_set(w->work4, j + jr, sum[jr*na + 1]);
  593. }
  594. if (j > 0)
  595. {
  596. xscale = 1.0 / GSL_MAX(1.0, xmax);
  597. temp = acoefa * gsl_vector_get(w->work1, j) +
  598. bcoefa * gsl_vector_get(w->work2, j);
  599. if (il2by2)
  600. {
  601. temp = GSL_MAX(temp,
  602. acoefa * gsl_vector_get(w->work1, j + 1) +
  603. bcoefa * gsl_vector_get(w->work2, j + 1));
  604. }
  605. temp = GSL_MAX(temp, GSL_MAX(acoefa, bcoefa));
  606. if (temp > bignum * xscale)
  607. {
  608. for (jr = 0; jr <= je; ++jr)
  609. {
  610. gsl_vector_set(w->work3, jr,
  611. xscale * gsl_vector_get(w->work3, jr));
  612. if (nw == 2)
  613. {
  614. gsl_vector_set(w->work4, jr,
  615. xscale * gsl_vector_get(w->work4, jr));
  616. }
  617. }
  618. xmax *= xscale;
  619. }
  620. for (ja = 0; ja < na; ++ja)
  621. {
  622. if (complex_pair)
  623. {
  624. creala = acoef * gsl_vector_get(w->work3, j + ja);
  625. cimaga = acoef * gsl_vector_get(w->work4, j + ja);
  626. crealb = bcoefr * gsl_vector_get(w->work3, j + ja) -
  627. bcoefi * gsl_vector_get(w->work4, j + ja);
  628. cimagb = bcoefi * gsl_vector_get(w->work3, j + ja) +
  629. bcoefr * gsl_vector_get(w->work4, j + ja);
  630. for (jr = 0; jr <= j - 1; ++jr)
  631. {
  632. gsl_vector_set(w->work3, jr,
  633. gsl_vector_get(w->work3, jr) -
  634. creala * gsl_matrix_get(S, jr, j + ja) +
  635. crealb * gsl_matrix_get(T, jr, j + ja));
  636. gsl_vector_set(w->work4, jr,
  637. gsl_vector_get(w->work4, jr) -
  638. cimaga * gsl_matrix_get(S, jr, j + ja) +
  639. cimagb * gsl_matrix_get(T, jr, j + ja));
  640. }
  641. }
  642. else
  643. {
  644. creala = acoef * gsl_vector_get(w->work3, j + ja);
  645. crealb = bcoefr * gsl_vector_get(w->work3, j + ja);
  646. for (jr = 0; jr <= j - 1; ++jr)
  647. {
  648. gsl_vector_set(w->work3, jr,
  649. gsl_vector_get(w->work3, jr) -
  650. creala * gsl_matrix_get(S, jr, j + ja) +
  651. crealb * gsl_matrix_get(T, jr, j + ja));
  652. }
  653. } /* if (!complex_pair) */
  654. } /* for (ja = 0; ja < na; ++ja) */
  655. } /* if (j > 0) */
  656. il2by2 = 0;
  657. } /* for (i = 0; i < je - nw; ++i) */
  658. for (jr = 0; jr < N; ++jr)
  659. {
  660. gsl_vector_set(w->work5, jr,
  661. gsl_vector_get(w->work3, 0) * gsl_matrix_get(Z, jr, 0));
  662. if (nw == 2)
  663. {
  664. gsl_vector_set(w->work6, jr,
  665. gsl_vector_get(w->work4, 0) * gsl_matrix_get(Z, jr, 0));
  666. }
  667. }
  668. for (jc = 1; jc <= je; ++jc)
  669. {
  670. for (jr = 0; jr < N; ++jr)
  671. {
  672. gsl_vector_set(w->work5, jr,
  673. gsl_vector_get(w->work5, jr) +
  674. gsl_vector_get(w->work3, jc) * gsl_matrix_get(Z, jr, jc));
  675. if (nw == 2)
  676. {
  677. gsl_vector_set(w->work6, jr,
  678. gsl_vector_get(w->work6, jr) +
  679. gsl_vector_get(w->work4, jc) * gsl_matrix_get(Z, jr, jc));
  680. }
  681. }
  682. }
  683. /* store the eigenvector */
  684. if (complex_pair)
  685. {
  686. ecol = gsl_matrix_complex_column(evec, je - 1);
  687. re = gsl_vector_complex_real(&ecol.vector);
  688. im = gsl_vector_complex_imag(&ecol.vector);
  689. ecol = gsl_matrix_complex_column(evec, je);
  690. re2 = gsl_vector_complex_real(&ecol.vector);
  691. im2 = gsl_vector_complex_imag(&ecol.vector);
  692. }
  693. else
  694. {
  695. ecol = gsl_matrix_complex_column(evec, je);
  696. re = gsl_vector_complex_real(&ecol.vector);
  697. im = gsl_vector_complex_imag(&ecol.vector);
  698. }
  699. for (jr = 0; jr < N; ++jr)
  700. {
  701. gsl_vector_set(&re.vector, jr, gsl_vector_get(w->work5, jr));
  702. if (complex_pair)
  703. {
  704. gsl_vector_set(&im.vector, jr, gsl_vector_get(w->work6, jr));
  705. gsl_vector_set(&re2.vector, jr, gsl_vector_get(w->work5, jr));
  706. gsl_vector_set(&im2.vector, jr, -gsl_vector_get(w->work6, jr));
  707. }
  708. else
  709. {
  710. gsl_vector_set(&im.vector, jr, 0.0);
  711. }
  712. }
  713. /* scale eigenvector */
  714. xmax = 0.0;
  715. if (complex_pair)
  716. {
  717. for (j = 0; j < N; ++j)
  718. {
  719. xmax = GSL_MAX(xmax,
  720. fabs(gsl_vector_get(&re.vector, j)) +
  721. fabs(gsl_vector_get(&im.vector, j)));
  722. }
  723. }
  724. else
  725. {
  726. for (j = 0; j < N; ++j)
  727. {
  728. xmax = GSL_MAX(xmax, fabs(gsl_vector_get(&re.vector, j)));
  729. }
  730. }
  731. if (xmax > GSL_DBL_MIN)
  732. {
  733. xscale = 1.0 / xmax;
  734. for (j = 0; j < N; ++j)
  735. {
  736. gsl_vector_set(&re.vector, j,
  737. gsl_vector_get(&re.vector, j) * xscale);
  738. if (complex_pair)
  739. {
  740. gsl_vector_set(&im.vector, j,
  741. gsl_vector_get(&im.vector, j) * xscale);
  742. gsl_vector_set(&re2.vector, j,
  743. gsl_vector_get(&re2.vector, j) * xscale);
  744. gsl_vector_set(&im2.vector, j,
  745. gsl_vector_get(&im2.vector, j) * xscale);
  746. }
  747. }
  748. }
  749. } /* for (k = 0; k < N; ++k) */
  750. return GSL_SUCCESS;
  751. } /* genv_get_right_eigenvectors() */
  752. /*
  753. genv_normalize_eigenvectors()
  754. Normalize eigenvectors so that their Euclidean norm is 1
  755. Inputs: alpha - eigenvalue numerators
  756. evec - eigenvectors
  757. */
  758. static void
  759. genv_normalize_eigenvectors(gsl_vector_complex *alpha,
  760. gsl_matrix_complex *evec)
  761. {
  762. const size_t N = evec->size1;
  763. size_t i; /* looping */
  764. gsl_complex ai;
  765. gsl_vector_complex_view vi;
  766. gsl_vector_view re, im;
  767. double scale; /* scaling factor */
  768. for (i = 0; i < N; ++i)
  769. {
  770. ai = gsl_vector_complex_get(alpha, i);
  771. vi = gsl_matrix_complex_column(evec, i);
  772. re = gsl_vector_complex_real(&vi.vector);
  773. if (GSL_IMAG(ai) == 0.0)
  774. {
  775. scale = 1.0 / gsl_blas_dnrm2(&re.vector);
  776. gsl_blas_dscal(scale, &re.vector);
  777. }
  778. else if (GSL_IMAG(ai) > 0.0)
  779. {
  780. im = gsl_vector_complex_imag(&vi.vector);
  781. scale = 1.0 / gsl_hypot(gsl_blas_dnrm2(&re.vector),
  782. gsl_blas_dnrm2(&im.vector));
  783. gsl_blas_zdscal(scale, &vi.vector);
  784. vi = gsl_matrix_complex_column(evec, i + 1);
  785. gsl_blas_zdscal(scale, &vi.vector);
  786. }
  787. }
  788. } /* genv_normalize_eigenvectors() */