My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
eqnsys.cpp
Go to the documentation of this file.
1 /*
2  * eqnsys.cpp - equation system solver class implementation
3  *
4  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id: eqnsys.cpp 1825 2011-03-11 20:42:14Z ela $
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 #include <time.h>
34 #include <math.h>
35 #include <float.h>
36 
37 #include "compat.h"
38 #include "logging.h"
39 #include "precision.h"
40 #include "complex.h"
41 #include "tmatrix.h"
42 #include "eqnsys.h"
43 #include "exception.h"
44 #include "exceptionstack.h"
45 
46 // Little helper macro.
47 #define Swap(type,a,b) { type t; t = a; a = b; b = t; }
48 
49 using namespace qucs;
50 
51 // Constructor creates an unnamed instance of the eqnsys class.
52 template <class nr_type_t>
54  A = V = NULL;
55  B = X = NULL;
56  S = E = NULL;
57  T = R = NULL;
58  nPvt = NULL;
59  cMap = rMap = NULL;
60  update = 1;
61  pivoting = PIVOT_PARTIAL;
62  N = 0;
63 }
64 
65 // Destructor deletes the eqnsys class object.
66 template <class nr_type_t>
68  if (R != NULL) delete R;
69  if (T != NULL) delete T;
70  if (B != NULL) delete B;
71  if (S != NULL) delete S;
72  if (E != NULL) delete E;
73  if (V != NULL) delete V;
74  if (rMap != NULL) delete[] rMap;
75  if (cMap != NULL) delete[] cMap;
76  if (nPvt != NULL) delete[] nPvt;
77 }
78 
79 /* The copy constructor creates a new instance of the eqnsys class
80  based on the given eqnsys object. */
81 template <class nr_type_t>
83  A = e.A;
84  V = NULL;
85  S = E = NULL;
86  T = R = NULL;
87  B = e.B ? new tvector<nr_type_t> (*(e.B)) : NULL;
88  cMap = rMap = NULL;
89  nPvt = NULL;
90  update = 1;
91  X = e.X;
92  N = 0;
93 }
94 
95 /* With this function the describing matrices for the equation system
96  is passed to the equation system solver class. Matrix A is the
97  left hand side of the equation system and B the right hand side
98  vector. The reference pointer to the X vector is going to be the
99  solution vector. The B vector will be locally copied. */
100 template <class nr_type_t>
102  tvector<nr_type_t> * refX,
103  tvector<nr_type_t> * nB) {
104  if (nA != NULL) {
105  A = nA;
106  update = 1;
107  if (N != A->getCols ()) {
108  N = A->getCols ();
109  if (cMap) delete[] cMap; cMap = new int[N];
110  if (rMap) delete[] rMap; rMap = new int[N];
111  if (nPvt) delete[] nPvt; nPvt = new nr_double_t[N];
112  }
113  }
114  else {
115  update = 0;
116  }
117  if (B != NULL) delete B;
118  B = new tvector<nr_type_t> (*nB);
119  X = refX;
120 }
121 
122 /* Depending on the algorithm applied to the equation system solver
123  the function stores the solution of the system into the matrix
124  pointed to by the X matrix reference. */
125 template <class nr_type_t>
127 #if DEBUG && 0
128  time_t t = time (NULL);
129 #endif
130  switch (algo) {
131  case ALGO_INVERSE:
132  solve_inverse ();
133  break;
134  case ALGO_GAUSS:
135  solve_gauss ();
136  break;
137  case ALGO_GAUSS_JORDAN:
138  solve_gauss_jordan ();
139  break;
141  solve_lu_crout ();
142  break;
144  solve_lu_doolittle ();
145  break;
147  factorize_lu_crout ();
148  break;
150  factorize_lu_doolittle ();
151  break;
153  substitute_lu_crout ();
154  break;
156  substitute_lu_doolittle ();
157  break;
158  case ALGO_JACOBI: case ALGO_GAUSS_SEIDEL:
159  solve_iterative ();
160  break;
161  case ALGO_SOR:
162  solve_sor ();
163  break;
165  solve_qr ();
166  break;
168  solve_qr_ls ();
169  break;
171  solve_svd ();
172  break;
174  solve_qrh ();
175  break;
176  }
177 #if DEBUG && 0
178  logprint (LOG_STATUS, "NOTIFY: %dx%d eqnsys solved in %ld seconds\n",
179  A->getRows (), A->getCols (), time (NULL) - t);
180 #endif
181 }
182 
183 /* Simple matrix inversion is used to solve the equation system. */
184 template <class nr_type_t>
186  *X = inverse (*A) * *B;
187 }
188 
189 #define A_ (*A)
190 #define X_ (*X)
191 #define B_ (*B)
192 
193 /* The function solves the equation system applying Gaussian
194  elimination with full column pivoting only (no row pivoting). */
195 template <class nr_type_t>
196 void eqnsys<nr_type_t>::solve_gauss (void) {
197  nr_double_t MaxPivot;
198  nr_type_t f;
199  int i, c, r, pivot;
200 
201  // triangulate the matrix
202  for (i = 0; i < N; i++) {
203  // find maximum column value for pivoting
204  for (MaxPivot = 0, pivot = r = i; r < N; r++) {
205  if (abs (A_(r, i)) > MaxPivot) {
206  MaxPivot = abs (A_(r, i));
207  pivot = r;
208  }
209  }
210  // exchange rows if necessary
211  assert (MaxPivot != 0);
212  if (i != pivot) {
213  A->exchangeRows (i, pivot);
214  B->exchangeRows (i, pivot);
215  }
216  // compute new rows and columns
217  for (r = i + 1; r < N; r++) {
218  f = A_(r, i) / A_(i, i);
219  for (c = i + 1; c < N; c++) A_(r, c) -= f * A_(i, c);
220  B_(r) -= f * B_(i);
221  }
222  }
223 
224  // backward substitution
225  for (i = N - 1; i >= 0; i--) {
226  f = B_(i);
227  for (c = i + 1; c < N; c++) f -= A_(i, c) * X_(c);
228  X_(i) = f / A_(i, i);
229  }
230 }
231 
232 /* The function solves the equation system applying a modified
233  Gaussian elimination with full column pivoting only (no row
234  pivoting). */
235 template <class nr_type_t>
237  nr_double_t MaxPivot;
238  nr_type_t f;
239  int i, c, r, pivot;
240 
241  // create the eye matrix
242  for (i = 0; i < N; i++) {
243  // find maximum column value for pivoting
244  for (MaxPivot = 0, pivot = r = i; r < N; r++) {
245  if (abs (A_(r, i)) > MaxPivot) {
246  MaxPivot = abs (A_(r, i));
247  pivot = r;
248  }
249  }
250  // exchange rows if necessary
251  assert (MaxPivot != 0);
252  if (i != pivot) {
253  A->exchangeRows (i, pivot);
254  B->exchangeRows (i, pivot);
255  }
256 
257  // compute current row
258  f = A_(i, i);
259  for (c = i + 1; c < N; c++) A_(i, c) /= f;
260  B_(i) /= f;
261 
262  // compute new rows and columns
263  for (r = 0; r < N; r++) {
264  if (r != i) {
265  f = A_(r, i);
266  for (c = i + 1; c < N; c++) A_(r, c) -= f * A_(i, c);
267  B_(r) -= f * B_(i);
268  }
269  }
270  }
271 
272  // right hand side is now the solution
273  *X = *B;
274 }
275 
276 #define LU_FAILURE 0
277 #define VIRTUAL_RES(txt,i) { \
278  qucs::exception * e = new qucs::exception (EXCEPTION_SINGULAR); \
279  e->setText (txt); \
280  e->setData (rMap[i]); \
281  A_(i, i) = NR_TINY; /* virtual resistance to ground */ \
282  throw_exception (e); }
283 
284 /* The function uses LU decomposition and the appropriate forward and
285  backward substitutions in order to solve the linear equation
286  system. It is very useful when dealing with equation systems where
287  the left hand side (the A matrix) does not change but the right
288  hand side (the B vector) only. */
289 template <class nr_type_t>
291 
292  // skip decomposition if requested
293  if (update) {
294  // perform LU composition
295  factorize_lu_crout ();
296  }
297 
298  // finally solve the equation system
299  substitute_lu_crout ();
300 }
301 
302 /* The other LU decomposition. */
303 template <class nr_type_t>
305 
306  // skip decomposition if requested
307  if (update) {
308  // perform LU composition
309  factorize_lu_doolittle ();
310  }
311 
312  // finally solve the equation system
313  substitute_lu_doolittle ();
314 }
315 
316 /* This function decomposes the left hand matrix into an upper U and
317  lower L matrix. The algorithm is called LU decomposition (Crout's
318  definition). The function performs the actual LU decomposition of
319  the matrix A using (implicit) partial row pivoting. */
320 template <class nr_type_t>
322  nr_double_t d, MaxPivot;
323  nr_type_t f;
324  int k, c, r, pivot;
325 
326  // initialize pivot exchange table
327  for (r = 0; r < N; r++) {
328  for (MaxPivot = 0, c = 0; c < N; c++)
329  if ((d = abs (A_(r, c))) > MaxPivot)
330  MaxPivot = d;
331  if (MaxPivot <= 0) MaxPivot = NR_TINY;
332  nPvt[r] = 1 / MaxPivot;
333  rMap[r] = r;
334  }
335 
336  // decompose the matrix into L (lower) and U (upper) matrix
337  for (c = 0; c < N; c++) {
338  // upper matrix entries
339  for (r = 0; r < c; r++) {
340  f = A_(r, c);
341  for (k = 0; k < r; k++) f -= A_(r, k) * A_(k, c);
342  A_(r, c) = f / A_(r, r);
343  }
344  // lower matrix entries
345  for (MaxPivot = 0, pivot = r; r < N; r++) {
346  f = A_(r, c);
347  for (k = 0; k < c; k++) f -= A_(r, k) * A_(k, c);
348  A_(r, c) = f;
349  // larger pivot ?
350  if ((d = nPvt[r] * abs (f)) > MaxPivot) {
351  MaxPivot = d;
352  pivot = r;
353  }
354  }
355 
356  // check pivot element and throw appropriate exception
357  if (MaxPivot <= 0) {
358 #if LU_FAILURE
360  e->setText ("no pivot != 0 found during Crout LU decomposition");
361  e->setData (c);
362  throw_exception (e);
363  goto fail;
364 #else /* insert virtual resistance */
365  VIRTUAL_RES ("no pivot != 0 found during Crout LU decomposition", c);
366 #endif
367  }
368 
369  // swap matrix rows if necessary and remember that step in the
370  // exchange table
371  if (c != pivot) {
372  A->exchangeRows (c, pivot);
373  Swap (int, rMap[c], rMap[pivot]);
374  Swap (nr_double_t, nPvt[c], nPvt[pivot]);
375  }
376  }
377 #if LU_FAILURE
378  fail:
379 #endif
380 }
381 
382 /* This function decomposes the left hand matrix into an upper U and
383  lower L matrix. The algorithm is called LU decomposition
384  (Doolittle's definition). The function performs the actual LU
385  decomposition of the matrix A using (implicit) partial row pivoting. */
386 template <class nr_type_t>
388  nr_double_t d, MaxPivot;
389  nr_type_t f;
390  int k, c, r, pivot;
391 
392  // initialize pivot exchange table
393  for (r = 0; r < N; r++) {
394  for (MaxPivot = 0, c = 0; c < N; c++)
395  if ((d = abs (A_(r, c))) > MaxPivot)
396  MaxPivot = d;
397  if (MaxPivot <= 0) MaxPivot = NR_TINY;
398  nPvt[r] = 1 / MaxPivot;
399  rMap[r] = r;
400  }
401 
402  // decompose the matrix into L (lower) and U (upper) matrix
403  for (c = 0; c < N; c++) {
404  // upper matrix entries
405  for (r = 0; r < c; r++) {
406  f = A_(r, c);
407  for (k = 0; k < r; k++) f -= A_(r, k) * A_(k, c);
408  A_(r, c) = f;
409  }
410  // lower matrix entries
411  for (MaxPivot = 0, pivot = r; r < N; r++) {
412  f = A_(r, c);
413  for (k = 0; k < c; k++) f -= A_(r, k) * A_(k, c);
414  A_(r, c) = f;
415  // larger pivot ?
416  if ((d = nPvt[r] * abs (f)) > MaxPivot) {
417  MaxPivot = d;
418  pivot = r;
419  }
420  }
421 
422  // check pivot element and throw appropriate exception
423  if (MaxPivot <= 0) {
424 #if LU_FAILURE
426  e->setText ("no pivot != 0 found during Doolittle LU decomposition");
427  e->setData (c);
428  throw_exception (e);
429  goto fail;
430 #else /* insert virtual resistance */
431  VIRTUAL_RES ("no pivot != 0 found during Doolittle LU decomposition", c);
432 #endif
433  }
434 
435  // swap matrix rows if necessary and remember that step in the
436  // exchange table
437  if (c != pivot) {
438  A->exchangeRows (c, pivot);
439  Swap (int, rMap[c], rMap[pivot]);
440  Swap (nr_double_t, nPvt[c], nPvt[pivot]);
441  }
442 
443  // finally divide by the pivot element
444  if (c < N - 1) {
445  f = 1.0 / A_(c, c);
446  for (r = c + 1; r < N; r++) A_(r, c) *= f;
447  }
448  }
449 #if LU_FAILURE
450  fail:
451 #endif
452 }
453 
454 /* The function is used in order to run the forward and backward
455  substitutions using the LU decomposed matrix (Crout's definition -
456  Uii are ones). */
457 template <class nr_type_t>
459  nr_type_t f;
460  int i, c;
461 
462  // forward substitution in order to solve LY = B
463  for (i = 0; i < N; i++) {
464  f = B_(rMap[i]);
465  for (c = 0; c < i; c++) f -= A_(i, c) * X_(c);
466  X_(i) = f / A_(i, i);
467  }
468 
469  // backward substitution in order to solve UX = Y
470  for (i = N - 1; i >= 0; i--) {
471  f = X_(i);
472  for (c = i + 1; c < N; c++) f -= A_(i, c) * X_(c);
473  // remember that the Uii diagonal are ones only in Crout's definition
474  X_(i) = f;
475  }
476 }
477 
478 /* The function is used in order to run the forward and backward
479  substitutions using the LU decomposed matrix (Doolittle's
480  definition - Lii are ones). This function is here because of
481  transposed LU matrices as used in the AC noise analysis. */
482 template <class nr_type_t>
484  nr_type_t f;
485  int i, c;
486 
487  // forward substitution in order to solve LY = B
488  for (i = 0; i < N; i++) {
489  f = B_(rMap[i]);
490  for (c = 0; c < i; c++) f -= A_(i, c) * X_(c);
491  // remember that the Lii diagonal are ones only in Doolittle's definition
492  X_(i) = f;
493  }
494 
495  // backward substitution in order to solve UX = Y
496  for (i = N - 1; i >= 0; i--) {
497  f = X_(i);
498  for (c = i + 1; c < N; c++) f -= A_(i, c) * X_(c);
499  X_(i) = f / A_(i, i);
500  }
501 }
502 
503 /* The function solves the equation system using a full-step iterative
504  method (called Jacobi's method) or a single-step method (called
505  Gauss-Seidel) depending on the given algorithm. If the current X
506  vector (the solution vector) is the solution within a
507  Newton-Raphson iteration it is a good initial guess and the method
508  is very likely to converge. On divergence the method falls back to
509  LU decomposition. */
510 template <class nr_type_t>
512  nr_type_t f;
513  int error, conv, i, c, r;
514  int MaxIter = N; // -> less than N^3 operations
515  nr_double_t reltol = 1e-4;
516  nr_double_t abstol = NR_TINY;
517  nr_double_t diff, crit;
518 
519  // ensure that all diagonal values are non-zero
520  ensure_diagonal ();
521 
522  // try to raise diagonal dominance
523  preconditioner ();
524 
525  // decide here about possible convergence
526  if ((crit = convergence_criteria ()) >= 1) {
527 #if DEBUG && 0
528  logprint (LOG_STATUS, "NOTIFY: convergence criteria: %g >= 1 (%dx%d)\n",
529  crit, N, N);
530 #endif
531  //solve_lu ();
532  //return;
533  }
534 
535  // normalize the equation system to have ones on its diagonal
536  for (r = 0; r < N; r++) {
537  f = A_(r, r);
538  assert (f != 0); // singular matrix
539  for (c = 0; c < N; c++) A_(r, c) /= f;
540  B_(r) /= f;
541  }
542 
543  // the current X vector is a good initial guess for the iteration
544  tvector<nr_type_t> * Xprev = new tvector<nr_type_t> (*X);
545 
546  // start iterating here
547  i = 0; error = 0;
548  do {
549  // compute new solution vector
550  for (r = 0; r < N; r++) {
551  for (f = 0, c = 0; c < N; c++) {
552  if (algo == ALGO_GAUSS_SEIDEL) {
553  // Gauss-Seidel
554  if (c < r) f += A_(r, c) * X_(c);
555  else if (c > r) f += A_(r, c) * Xprev->get (c);
556  }
557  else {
558  // Jacobi
559  if (c != r) f += A_(r, c) * Xprev->get (c);
560  }
561  }
562  X_(r) = B_(r) - f;
563  }
564  // check for convergence
565  for (conv = 1, r = 0; r < N; r++) {
566  diff = abs (X_(r) - Xprev->get (r));
567  if (diff >= abstol + reltol * abs (X_(r))) {
568  conv = 0;
569  break;
570  }
571  if (!finite (diff)) { error++; break; }
572  }
573  // save last values
574  *Xprev = *X;
575  }
576  while (++i < MaxIter && !conv);
577 
578  delete Xprev;
579 
580  if (!conv || error) {
582  "WARNING: no convergence after %d %s iterations\n",
583  i, algo == ALGO_JACOBI ? "jacobi" : "gauss-seidel");
584  solve_lu_crout ();
585  }
586 #if DEBUG && 0
587  else {
589  "NOTIFY: %s convergence after %d iterations\n",
590  algo == ALGO_JACOBI ? "jacobi" : "gauss-seidel", i);
591  }
592 #endif
593 }
594 
595 /* The function solves the linear equation system using a single-step
596  iterative algorithm. It is a modification of the Gauss-Seidel
597  method and is called successive over relaxation. The function uses
598  an adaptive scheme to adjust the relaxation parameter. */
599 template <class nr_type_t>
600 void eqnsys<nr_type_t>::solve_sor (void) {
601  nr_type_t f;
602  int error, conv, i, c, r;
603  int MaxIter = N; // -> less than N^3 operations
604  nr_double_t reltol = 1e-4;
605  nr_double_t abstol = NR_TINY;
606  nr_double_t diff, crit, l = 1, d, s;
607 
608  // ensure that all diagonal values are non-zero
609  ensure_diagonal ();
610 
611  // try to raise diagonal dominance
612  preconditioner ();
613 
614  // decide here about possible convergence
615  if ((crit = convergence_criteria ()) >= 1) {
616 #if DEBUG && 0
617  logprint (LOG_STATUS, "NOTIFY: convergence criteria: %g >= 1 (%dx%d)\n",
618  crit, N, N);
619 #endif
620  //solve_lu ();
621  //return;
622  }
623 
624  // normalize the equation system to have ones on its diagonal
625  for (r = 0; r < N; r++) {
626  f = A_(r, r);
627  assert (f != 0); // singular matrix
628  for (c = 0; c < N; c++) A_(r, c) /= f;
629  B_(r) /= f;
630  }
631 
632  // the current X vector is a good initial guess for the iteration
633  tvector<nr_type_t> * Xprev = new tvector<nr_type_t> (*X);
634 
635  // start iterating here
636  i = 0; error = 0;
637  do {
638  // compute new solution vector
639  for (r = 0; r < N; r++) {
640  for (f = 0, c = 0; c < N; c++) {
641  if (c < r) f += A_(r, c) * X_(c);
642  else if (c > r) f += A_(r, c) * Xprev->get (c);
643  }
644  X_(r) = (1 - l) * Xprev->get (r) + l * (B_(r) - f);
645  }
646  // check for convergence
647  for (s = 0, d = 0, conv = 1, r = 0; r < N; r++) {
648  diff = abs (X_(r) - Xprev->get (r));
649  if (diff >= abstol + reltol * abs (X_(r))) {
650  conv = 0;
651  break;
652  }
653  d += diff; s += abs (X_(r));
654  if (!finite (diff)) { error++; break; }
655  }
656  if (!error) {
657  // adjust relaxation based on average errors
658  if ((s == 0 && d == 0) || d >= abstol * N + reltol * s) {
659  // values <= 1 -> non-convergence to convergence
660  if (l >= 0.6) l -= 0.1;
661  if (l >= 1.0) l = 1.0;
662  }
663  else {
664  // values >= 1 -> faster convergence
665  if (l < 1.5) l += 0.01;
666  if (l < 1.0) l = 1.0;
667  }
668  }
669  // save last values
670  *Xprev = *X;
671  }
672  while (++i < MaxIter && !conv);
673 
674  delete Xprev;
675 
676  if (!conv || error) {
678  "WARNING: no convergence after %d sor iterations (l = %g)\n",
679  i, l);
680  solve_lu_crout ();
681  }
682 #if DEBUG && 0
683  else {
685  "NOTIFY: sor convergence after %d iterations\n", i);
686  }
687 #endif
688 }
689 
690 /* The function computes the convergence criteria for iterative
691  methods like Jacobi or Gauss-Seidel as defined by Schmidt and
692  v.Mises. */
693 template <class nr_type_t>
694 nr_double_t eqnsys<nr_type_t>::convergence_criteria (void) {
695  nr_double_t f = 0;
696  for (int r = 0; r < A->getCols (); r++) {
697  for (int c = 0; c < A->getCols (); c++) {
698  if (r != c) f += norm (A_(r, c) / A_(r, r));
699  }
700  }
701  return sqrt (f);
702 }
703 
704 /* The function tries to ensure that there are non-zero diagonal
705  elements in the equation system matrix A. This is required for
706  iterative solution methods. */
707 template <class nr_type_t>
709  ensure_diagonal_MNA ();
710 }
711 
712 /* The function ensures that there are non-zero diagonal elements in
713  the equation system matrix A. It achieves this condition for
714  non-singular matrices which have been produced by the modified
715  nodal analysis. It takes advantage of the fact that the zero
716  diagonal elements have pairs of 1 and -1 on the same column and
717  row. */
718 template <class nr_type_t>
720  int restart, exchanged, begin = 0, pairs;
721  int pivot1, pivot2, i;
722  do {
723  restart = exchanged = 0;
724  /* search for zero diagonals with lone pairs */
725  for (i = begin; i < N; i++) {
726  if (A_(i, i) == 0) {
727  pairs = countPairs (i, pivot1, pivot2);
728  if (pairs == 1) { /* lone pair found, substitute rows */
729  A->exchangeRows (i, pivot1);
730  B->exchangeRows (i, pivot1);
731  exchanged = 1;
732  }
733  else if ((pairs > 1) && !restart) {
734  restart = 1;
735  begin = i;
736  }
737  }
738  }
739 
740  /* all lone pairs are gone, look for zero diagonals with multiple pairs */
741  if (restart) {
742  for (i = begin; !exchanged && i < N; i++) {
743  if (A_(i, i) == 0) {
744  pairs = countPairs (i, pivot1, pivot2);
745  A->exchangeRows (i, pivot1);
746  B->exchangeRows (i, pivot1);
747  exchanged = 1;
748  }
749  }
750  }
751  }
752  while (restart);
753 }
754 
755 /* Helper function for the above ensure_diagonal_MNA() function. It
756  looks for the pairs of 1 and -1 on the given row and column index. */
757 template <class nr_type_t>
758 int eqnsys<nr_type_t>::countPairs (int i, int& r1, int& r2) {
759  int pairs = 0;
760  for (int r = 0; r < N; r++) {
761  if (fabs (real (A_(r, i))) == 1.0) {
762  r1 = r;
763  pairs++;
764  for (r++; r < N; r++) {
765  if (fabs (real (A_(r, i))) == 1.0) {
766  r2 = r;
767  if (++pairs >= 2) return pairs;
768  }
769  }
770  }
771  }
772  return pairs;
773 }
774 
775 /* The function tries to raise the absolute value of diagonal elements
776  by swapping rows and thereby make the A matrix diagonally
777  dominant. */
778 template <class nr_type_t>
780  int pivot, r;
781  nr_double_t MaxPivot;
782  for (int i = 0; i < N; i++) {
783  // find maximum column value for pivoting
784  for (MaxPivot = 0, pivot = i, r = 0; r < N; r++) {
785  if (abs (A_(r, i)) > MaxPivot &&
786  abs (A_(i, r)) >= abs (A_(r, r))) {
787  MaxPivot = abs (A_(r, i));
788  pivot = r;
789  }
790  }
791  // swap matrix rows if possible
792  if (i != pivot) {
793  A->exchangeRows (i, pivot);
794  B->exchangeRows (i, pivot);
795  }
796  }
797 }
798 
799 #define R_ (*R)
800 #define T_ (*T)
801 
802 /* This function uses the QR decomposition using householder
803  transformations in order to solve the given equation system. */
804 template <class nr_type_t>
805 void eqnsys<nr_type_t>::solve_qrh (void) {
806  factorize_qrh ();
807  substitute_qrh ();
808 }
809 
810 /* This function uses the QR decomposition using householder
811  transformations in order to solve the given equation system. */
812 template <class nr_type_t>
813 void eqnsys<nr_type_t>::solve_qr (void) {
814  factorize_qr_householder ();
815  substitute_qr_householder ();
816 }
817 
818 /* The function uses the QR decomposition using householder
819  transformations in order to solve the given under-determined
820  equation system in its minimum norm (least square) sense. */
821 template <class nr_type_t>
822 void eqnsys<nr_type_t>::solve_qr_ls (void) {
823  A->transpose ();
824  factorize_qr_householder ();
825  substitute_qr_householder_ls ();
826 }
827 
828 /* Helper function for the euclidian norm calculators. */
829 static void
830 euclidian_update (nr_double_t a, nr_double_t& n, nr_double_t& scale) {
831  nr_double_t x, ax;
832  if ((x = a) != 0) {
833  ax = fabs (x);
834  if (scale < ax) {
835  x = scale / ax;
836  n = 1 + n * x * x;
837  scale = ax;
838  }
839  else {
840  x = ax / scale;
841  n += x * x;
842  }
843  }
844 }
845 
846 /* The following function computes the euclidian norm of the given
847  column vector of the matrix A starting from the given row. */
848 template <class nr_type_t>
849 nr_double_t eqnsys<nr_type_t>::euclidian_c (int c, int r) {
850  nr_double_t scale = 0, n = 1;
851  for (int i = r; i < N; i++) {
852  euclidian_update (real (A_(i, c)), n, scale);
853  euclidian_update (imag (A_(i, c)), n, scale);
854  }
855  return scale * sqrt (n);
856 }
857 
858 /* The following function computes the euclidian norm of the given
859  row vector of the matrix A starting from the given column. */
860 template <class nr_type_t>
861 nr_double_t eqnsys<nr_type_t>::euclidian_r (int r, int c) {
862  nr_double_t scale = 0, n = 1;
863  for (int i = c; i < N; i++) {
864  euclidian_update (real (A_(r, i)), n, scale);
865  euclidian_update (imag (A_(r, i)), n, scale);
866  }
867  return scale * sqrt (n);
868 }
869 
870 /* The function decomposes the matrix A into two matrices, the
871  orthonormal matrix Q and the upper triangular matrix R. The
872  original matrix is replaced by the householder vectors in the lower
873  triangular (including the diagonal) and the upper triangular R
874  matrix with its diagonal elements stored in the R vector. */
875 template <class nr_type_t>
877  int c, r, k, pivot;
878  nr_type_t f, t;
879  nr_double_t s, MaxPivot;
880 
881  if (R) delete R; R = new tvector<nr_type_t> (N);
882 
883  for (c = 0; c < N; c++) {
884  // compute column norms and save in work array
885  nPvt[c] = euclidian_c (c);
886  cMap[c] = c; // initialize permutation vector
887  }
888 
889  for (c = 0; c < N; c++) {
890 
891  // put column with largest norm into pivot position
892  MaxPivot = nPvt[c]; pivot = c;
893  for (r = c + 1; r < N; r++) {
894  if ((s = nPvt[r]) > MaxPivot) {
895  pivot = r;
896  MaxPivot = s;
897  }
898  }
899  if (pivot != c) {
900  A->exchangeCols (pivot, c);
901  Swap (int, cMap[pivot], cMap[c]);
902  Swap (nr_double_t, nPvt[pivot], nPvt[c]);
903  }
904 
905  // compute householder vector
906  if (c < N) {
907  nr_type_t a, b;
908  s = euclidian_c (c, c + 1);
909  a = A_(c, c);
910  b = -sign (a) * xhypot (a, s); // Wj
911  t = xhypot (s, a - b); // || Vi - Wi ||
912  R_(c) = b;
913  // householder vector entries Ui
914  A_(c, c) = (a - b) / t;
915  for (r = c + 1; r < N; r++) A_(r, c) /= t;
916  }
917  else {
918  R_(c) = A_(c, c);
919  }
920 
921  // apply householder transformation to remaining columns
922  for (r = c + 1; r < N; r++) {
923  for (f = 0, k = c; k < N; k++) f += conj (A_(k, c)) * A_(k, r);
924  for (k = c; k < N; k++) A_(k, r) -= 2.0 * f * A_(k, c);
925  }
926 
927  // update norms of remaining columns too
928  for (r = c + 1; r < N; r++) {
929  nPvt[r] = euclidian_c (r, c + 1);
930  }
931  }
932 }
933 
934 /* The function decomposes the matrix A into two matrices, the
935  orthonormal matrix Q and the upper triangular matrix R. The
936  original matrix is replaced by the householder vectors in the lower
937  triangular and the upper triangular R matrix (including the
938  diagonal). The householder vectors are normalized to have one in
939  their first position. */
940 template <class nr_type_t>
942  int c, r, pivot;
943  nr_double_t s, MaxPivot;
944 
945  if (T) delete T; T = new tvector<nr_type_t> (N);
946 
947  for (c = 0; c < N; c++) {
948  // compute column norms and save in work array
949  nPvt[c] = euclidian_c (c);
950  cMap[c] = c; // initialize permutation vector
951  }
952 
953  for (c = 0; c < N; c++) {
954 
955  // put column with largest norm into pivot position
956  MaxPivot = nPvt[c]; pivot = c;
957  for (r = c + 1; r < N; r++)
958  if ((s = nPvt[r]) > MaxPivot) {
959  pivot = r;
960  MaxPivot = s;
961  }
962  if (pivot != c) {
963  A->exchangeCols (pivot, c);
964  Swap (int, cMap[pivot], cMap[c]);
965  Swap (nr_double_t, nPvt[pivot], nPvt[c]);
966  }
967 
968  // compute and apply householder vector
969  T_(c) = householder_left (c);
970 
971  // update norms of remaining columns too
972  for (r = c + 1; r < N; r++) {
973  if ((s = nPvt[r]) > 0) {
974  nr_double_t y = 0;
975  nr_double_t t = norm (A_(c, r) / s);
976  if (t < 1)
977  y = s * sqrt (1 - t);
978  if (fabs (y / s) < NR_TINY)
979  nPvt[r] = euclidian_c (r, c + 1);
980  else
981  nPvt[r] = y;
982  }
983  }
984  }
985 }
986 
987 /* The function uses the householder vectors in order to compute Q'B,
988  then the equation system RX = B is solved by backward substitution. */
989 template <class nr_type_t>
991  int c, r;
992  nr_type_t f;
993 
994  // form the new right hand side Q'B
995  for (c = 0; c < N - 1; c++) {
996  // scalar product u_k^T * B
997  for (f = 0, r = c; r < N; r++) f += conj (A_(r, c)) * B_(r);
998  // z - 2 * f * u_k
999  for (r = c; r < N; r++) B_(r) -= 2.0 * f * A_(r, c);
1000  }
1001 
1002  // backward substitution in order to solve RX = Q'B
1003  for (r = N - 1; r >= 0; r--) {
1004  f = B_(r);
1005  for (c = r + 1; c < N; c++) f -= A_(r, c) * X_(cMap[c]);
1006  if (abs (R_(r)) > NR_EPSI)
1007  X_(cMap[r]) = f / R_(r);
1008  else
1009  X_(cMap[r]) = 0;
1010  }
1011 }
1012 
1013 /* The function uses the householder vectors in order to compute Q'B,
1014  then the equation system RX = B is solved by backward substitution. */
1015 template <class nr_type_t>
1017  int c, r;
1018  nr_type_t f;
1019 
1020  // form the new right hand side Q'B
1021  for (c = 0; c < N; c++) {
1022  if (T_(c) != 0) {
1023  // scalar product u' * B
1024  for (f = B_(c), r = c + 1; r < N; r++) f += conj (A_(r, c)) * B_(r);
1025  // z - T * f * u
1026  f *= conj (T_(c)); B_(c) -= f;
1027  for (r = c + 1; r < N; r++) B_(r) -= f * A_(r, c);
1028  }
1029  }
1030 
1031  // backward substitution in order to solve RX = Q'B
1032  for (r = N - 1; r >= 0; r--) {
1033  for (f = B_(r), c = r + 1; c < N; c++) f -= A_(r, c) * X_(cMap[c]);
1034  if (abs (A_(r, r)) > NR_EPSI)
1035  X_(cMap[r]) = f / A_(r, r);
1036  else
1037  X_(cMap[r]) = 0;
1038  }
1039 }
1040 
1041 /* The function uses the householder vectors in order to the solve the
1042  equation system R'X = B by forward substitution, then QX is computed
1043  to obtain the least square solution of the under-determined equation
1044  system AX = B. */
1045 template <class nr_type_t>
1047  int c, r;
1048  nr_type_t f;
1049 
1050  // forward substitution in order to solve R'X = B
1051  for (r = 0; r < N; r++) {
1052  for (f = B_(r), c = 0; c < r; c++) f -= A_(c, r) * B_(c);
1053  if (abs (A_(r, r)) > NR_EPSI)
1054  B_(r) = f / A_(r, r);
1055  else
1056  B_(r) = 0;
1057  }
1058 
1059  // compute the least square solution QX
1060  for (c = N - 1; c >= 0; c--) {
1061  if (T_(c) != 0) {
1062  // scalar product u' * B
1063  for (f = B_(c), r = c + 1; r < N; r++) f += conj (A_(r, c)) * B_(r);
1064  // z - T * f * u_k
1065  f *= T_(c); B_(c) -= f;
1066  for (r = c + 1; r < N; r++) B_(r) -= f * A_(r, c);
1067  }
1068  }
1069 
1070  // permute solution vector
1071  for (r = 0; r < N; r++) X_(cMap[r]) = B_(r);
1072 }
1073 
1074 #define sign_(a) (real (a) < 0 ? -1 : 1)
1075 
1076 /* The function creates the left-hand householder vector for a given
1077  column which eliminates the column except the first element. The
1078  householder vector is normalized to have one in the first position.
1079  The diagonal element is replaced by the applied householder vector
1080  and the vector itself is located in the free matrix positions. The
1081  function returns the normalization factor. */
1082 template <class nr_type_t>
1084  nr_type_t a, b, t;
1085  nr_double_t s, g;
1086  s = euclidian_c (c, c + 1);
1087  if (s == 0 && imag (A_(c, c)) == 0) {
1088  // no reflection necessary
1089  t = 0;
1090  }
1091  else {
1092  // calculate householder reflection
1093  a = A_(c, c);
1094  g = sign_(a) * xhypot (a, s);
1095  b = a + g;
1096  t = b / g;
1097  // store householder vector
1098  for (int r = c + 1; r < N; r++) A_(r, c) /= b;
1099  A_(c, c) = -g;
1100  }
1101  return t;
1102 }
1103 
1104 /* The function computes a Householder vector to zero-out the matrix
1105  entries in the given column, stores it in the annihilated vector
1106  space (in a packed form) and applies the transformation to the
1107  remaining right-hand columns. */
1108 template <class nr_type_t>
1109 nr_type_t eqnsys<nr_type_t>::householder_left (int c) {
1110  // compute householder vector
1111  nr_type_t t = householder_create_left (c);
1112  // apply householder transformation to remaining columns if necessary
1113  if (t != 0) {
1114  householder_apply_left (c, t);
1115  }
1116  return t;
1117 }
1118 
1119 /* The function computes a Householder vector to zero-out the matrix
1120  entries in the given row, stores it in the annihilated vector space
1121  (in a packed form) and applies the transformation to the remaining
1122  downward rows. */
1123 template <class nr_type_t>
1124 nr_type_t eqnsys<nr_type_t>::householder_right (int r) {
1125  // compute householder vector
1126  nr_type_t t = householder_create_right (r);
1127  // apply householder transformation to remaining rows if necessary
1128  if (t != 0) {
1129  householder_apply_right (r, t);
1130  }
1131  return t;
1132 }
1133 
1134 /* The function creates the right-hand householder vector for a given
1135  row which eliminates the row except the first element. The
1136  householder vector is normalized to have one in the first position.
1137  The super-diagonal element is replaced by the applied householder
1138  vector and the vector itself is located in the free matrix
1139  positions. The function returns the normalization factor. */
1140 template <class nr_type_t>
1142  nr_type_t a, b, t;
1143  nr_double_t s, g;
1144  s = euclidian_r (r, r + 2);
1145  if (s == 0 && imag (A_(r, r + 1)) == 0) {
1146  // no reflection necessary
1147  t = 0;
1148  }
1149  else {
1150  // calculate householder reflection
1151  a = A_(r, r + 1);
1152  g = sign_(a) * xhypot (a, s);
1153  b = a + g;
1154  t = b / g;
1155  // store householder vector
1156  for (int c = r + 2; c < N; c++) A_(r, c) /= b;
1157  A_(r, r + 1) = -g;
1158  }
1159  return t;
1160 }
1161 
1162 /* Applies the householder vector stored in the given column to the
1163  right-hand columns using the given normalization factor. */
1164 template <class nr_type_t>
1165 void eqnsys<nr_type_t>::householder_apply_left (int c, nr_type_t t) {
1166  nr_type_t f;
1167  int k, r;
1168  // apply the householder vector to each right-hand column
1169  for (r = c + 1; r < N; r++) {
1170  // calculate f = u' * A (a scalar product)
1171  f = A_(c, r);
1172  for (k = c + 1; k < N; k++) f += conj (A_(k, c)) * A_(k, r);
1173  // calculate A -= T * f * u
1174  f *= conj (t); A_(c, r) -= f;
1175  for (k = c + 1; k < N; k++) A_(k, r) -= f * A_(k, c);
1176  }
1177 }
1178 
1179 /* Applies the householder vector stored in the given row to the
1180  downward rows using the given normalization factor. */
1181 template <class nr_type_t>
1182 void eqnsys<nr_type_t>::householder_apply_right (int r, nr_type_t t) {
1183  nr_type_t f;
1184  int k, c;
1185  // apply the householder vector to each downward row
1186  for (c = r + 1; c < N; c++) {
1187  // calculate f = u' * A (a scalar product)
1188  f = A_(c, r + 1);
1189  for (k = r + 2; k < N; k++) f += conj (A_(r, k)) * A_(c, k);
1190  // calculate A -= T * f * u
1191  f *= conj (t); A_(c, r + 1) -= f;
1192  for (k = r + 2; k < N; k++) A_(c, k) -= f * A_(r, k);
1193  }
1194 }
1195 
1196 // Some helper defines for SVD.
1197 #define V_ (*V)
1198 #define S_ (*S)
1199 #define E_ (*E)
1200 #define U_ (*A)
1201 
1202 /* The function does exactly the same as householder_apply_right()
1203  except that it applies the householder transformations to another
1204  matrix. */
1205 template <class nr_type_t>
1206 void eqnsys<nr_type_t>::householder_apply_right_extern (int r, nr_type_t t) {
1207  nr_type_t f;
1208  int k, c;
1209  // apply the householder vector to each downward row
1210  for (c = r + 1; c < N; c++) {
1211  // calculate f = u' * A (a scalar product)
1212  f = V_(c, r + 1);
1213  for (k = r + 2; k < N; k++) f += conj (A_(r, k)) * V_(c, k);
1214  // calculate A -= T * f * u
1215  f *= conj (t); V_(c, r + 1) -= f;
1216  for (k = r + 2; k < N; k++) V_(c, k) -= f * A_(r, k);
1217  }
1218 }
1219 
1220 /* This function solves the equation system AX = B using the singular
1221  value decomposition (Golub-Reinsch-SVD). */
1222 template <class nr_type_t>
1223 void eqnsys<nr_type_t>::solve_svd (void) {
1224  factorize_svd ();
1225  chop_svd ();
1226  substitute_svd ();
1227 }
1228 
1229 // Annihilates near-zero singular values.
1230 template <class nr_type_t>
1231 void eqnsys<nr_type_t>::chop_svd (void) {
1232  int c;
1233  nr_double_t Max, Min;
1234  Max = 0.0;
1235  for (c = 0; c < N; c++) if (fabs (S_(c)) > Max) Max = fabs (S_(c));
1236  Min = Max * NR_EPSI;
1237  for (c = 0; c < N; c++) if (fabs (S_(c)) < Min) S_(c) = 0.0;
1238 }
1239 
1240 /* The function uses the singular value decomposition A = USV' to
1241  solve the equation system AX = B by simple matrix multiplications.
1242  Remember that the factorization actually computed U, S and V'. */
1243 template <class nr_type_t>
1245  int c, r;
1246  nr_type_t f;
1247  // calculate U'B
1248  for (c = 0; c < N; c++) {
1249  f = 0.0;
1250  // non-zero result only if S is non-zero
1251  if (S_(c) != 0.0) {
1252  for (r = 0; r < N; r++) f += conj (U_(r, c)) * B_(r);
1253  // this is the divide by S
1254  f /= S_(c);
1255  }
1256  R_(c) = f;
1257  }
1258  // matrix multiply by V to get the final solution
1259  for (r = 0; r < N; r++) {
1260  for (f = 0.0, c = 0; c < N; c++) f += conj (V_(c, r)) * R_(c);
1261  X_(r) = f;
1262  }
1263 }
1264 
1265 /* The function decomposes the matrix A into three other matrices U, S
1266  and V'. The matrix A is overwritten by the U matrix, S is stored
1267  in a separate vector and V in a separate matrix. */
1268 template <class nr_type_t>
1270  int i, j, l;
1271  nr_type_t t;
1272 
1273  // allocate space for vectors and matrices
1274  if (R) delete R; R = new tvector<nr_type_t> (N);
1275  if (T) delete T; T = new tvector<nr_type_t> (N);
1276  if (V) delete V; V = new tmatrix<nr_type_t> (N);
1277  if (S) delete S; S = new tvector<nr_double_t> (N);
1278  if (E) delete E; E = new tvector<nr_double_t> (N);
1279 
1280  // bidiagonalization through householder transformations
1281  for (i = 0; i < N; i++) {
1282  T_(i) = householder_left (i);
1283  if (i < N - 1) R_(i) = householder_right (i);
1284  }
1285 
1286  // copy over the real valued bidiagonal values
1287  for (i = 0; i < N; i++) S_(i) = real (A_(i, i));
1288  for (E_(0) = 0, i = 1; i < N; i++) E_(i) = real (A_(i - 1, i));
1289 
1290  // backward accumulation of right-hand householder transformations
1291  // yields the V' matrix
1292  for (l = N, i = N - 1; i >= 0; l = i--) {
1293  if (i < N - 1) {
1294  if ((t = R_(i)) != 0.0) {
1295  householder_apply_right_extern (i, conj (t));
1296  }
1297  else for (j = l; j < N; j++) // cleanup this row
1298  V_(i, j) = V_(j, i) = 0.0;
1299  }
1300  V_(i, i) = 1.0;
1301  }
1302 
1303  // backward accumulation of left-hand householder transformations
1304  // yields the U matrix in place of the A matrix
1305  for (l = N, i = N - 1; i >= 0; l = i--) {
1306  for (j = l; j < N; j++) // cleanup upper row
1307  A_(i, j) = 0.0;
1308  if ((t = T_(i)) != 0.0) {
1309  householder_apply_left (i, conj (t));
1310  for (j = l; j < N; j++) A_(j, i) *= -t;
1311  }
1312  else for (j = l; j < N; j++) // cleanup this column
1313  A_(j, i) = 0.0;
1314  A_(i, i) = 1.0 - t;
1315  }
1316 
1317  // S and E contain diagonal and super-diagonal, A contains U, V'
1318  // calculated; now diagonalization can begin
1319  diagonalize_svd ();
1320 }
1321 
1322 #ifndef MAX
1323 # define MAX(x,y) (((x) > (y)) ? (x) : (y))
1324 #endif
1325 
1326 // Helper function computes Givens rotation.
1327 static nr_double_t
1328 givens (nr_double_t a, nr_double_t b, nr_double_t& c, nr_double_t& s) {
1329  nr_double_t z = xhypot (a, b);
1330  c = a / z;
1331  s = b / z;
1332  return z;
1333 }
1334 
1335 template <class nr_type_t>
1336 void eqnsys<nr_type_t>::givens_apply_u (int c1, int c2,
1337  nr_double_t c, nr_double_t s) {
1338  for (int i = 0; i < N; i++) {
1339  nr_type_t y = U_(i, c1);
1340  nr_type_t z = U_(i, c2);
1341  U_(i, c1) = y * c + z * s;
1342  U_(i, c2) = z * c - y * s;
1343  }
1344 }
1345 
1346 template <class nr_type_t>
1347 void eqnsys<nr_type_t>::givens_apply_v (int r1, int r2,
1348  nr_double_t c, nr_double_t s) {
1349  for (int i = 0; i < N; i++) {
1350  nr_type_t y = V_(r1, i);
1351  nr_type_t z = V_(r2, i);
1352  V_(r1, i) = y * c + z * s;
1353  V_(r2, i) = z * c - y * s;
1354  }
1355 }
1356 
1357 /* This function diagonalizes the upper bidiagonal matrix fromed by
1358  the diagonal S and the super-diagonal vector E. Both vectors are
1359  real valued. Thus real valued calculations even when solving a
1360  complex valued equation systems is possible except for the matrix
1361  updates of U and V'. */
1362 template <class nr_type_t>
1364  bool split;
1365  int i, l, j, its, k, n, MaxIters = 30;
1366  nr_double_t an, f, g, h, d, c, s, b, a;
1367 
1368  // find largest bidiagonal value
1369  for (an = 0, i = 0; i < N; i++)
1370  an = MAX (an, fabs (S_(i)) + fabs (E_(i)));
1371 
1372  // diagonalize the bidiagonal matrix (stored as super-diagonal
1373  // vector E and diagonal vector S)
1374  for (k = N - 1; k >= 0; k--) {
1375  // loop over singular values
1376  for (its = 0; its <= MaxIters; its++) {
1377  split = true;
1378  // check for a zero entry along the super-diagonal E, if there
1379  // is one, it is possible to QR iterate on two separate matrices
1380  // above and below it
1381  for (n = 0, l = k; l >= 1; l--) {
1382  // note that E_(0) is always zero
1383  n = l - 1;
1384  if (fabs (E_(l)) + an == an) { split = false; break; }
1385  if (fabs (S_(n)) + an == an) break;
1386  }
1387  // if there is a zero on the diagonal S, it is possible to zero
1388  // out the corresponding super-diagonal E entry to its right
1389  if (split) {
1390  // cancellation of E_(l), if l > 0
1391  c = 0.0;
1392  s = 1.0;
1393  for (i = l; i <= k; i++) {
1394  f = -s * E_(i);
1395  E_(i) *= c;
1396  if (fabs (f) + an == an) break;
1397  g = S_(i);
1398  S_(i) = givens (f, g, c, s);
1399  // apply inverse rotation to U
1400  givens_apply_u (n, i, c, s);
1401  }
1402  }
1403 
1404  d = S_(k);
1405  // convergence
1406  if (l == k) {
1407  // singular value is made non-negative
1408  if (d < 0.0) {
1409  S_(k) = -d;
1410  for (j = 0; j < N; j++) V_(k, j) = -V_(k, j);
1411  }
1412  break;
1413  }
1414  if (its == MaxIters) {
1415  logprint (LOG_ERROR, "WARNING: no convergence in %d SVD iterations\n",
1416  MaxIters);
1417  }
1418 
1419  // shift from bottom 2-by-2 minor
1420  a = S_(l);
1421  n = k - 1;
1422  b = S_(n);
1423  g = E_(n);
1424  h = E_(k);
1425 
1426  // compute QR shift value (as close as possible to the largest
1427  // eigenvalue of the 2-by-2 minor matrix)
1428  f = (b - d) * (b + d) + (g - h) * (g + h);
1429  f /= 2.0 * h * b;
1430  f += sign_(f) * xhypot (f, 1.0);
1431  f = ((a - d) * (a + d) + h * (b / f - h)) / a;
1432  // f => (B_{ll}^2 - u) / B_{ll}
1433  // u => eigenvalue of T = B' * B nearer T_{22} (Wilkinson shift)
1434 
1435  // next QR transformation
1436  c = s = 1.0;
1437  for (j = l; j <= n; j++) {
1438  i = j + 1;
1439  g = E_(i);
1440  b = S_(i);
1441  h = s * g; // h => right-hand non-zero to annihilate
1442  g *= c;
1443  E_(j) = givens (f, h, c, s);
1444  // perform the rotation
1445  f = a * c + g * s;
1446  g = g * c - a * s;
1447  h = b * s;
1448  b *= c;
1449  // here: +- -+
1450  // | f g | = B * V'_j (also first V'_1)
1451  // | h b |
1452  // +- -+
1453 
1454  // accumulate the rotation in V'
1455  givens_apply_v (j, i, c, s);
1456  d = S_(j) = xhypot (f, h);
1457  // rotation can be arbitrary if d = 0
1458  if (d != 0.0) {
1459  // d => non-zero result on diagonal
1460  d = 1.0 / d;
1461  // rotation coefficients to annihilate the lower non-zero
1462  c = f * d;
1463  s = h * d;
1464  }
1465  f = c * g + s * b;
1466  a = c * b - s * g;
1467  // here: +- -+
1468  // | d f | => U_j * B
1469  // | 0 a |
1470  // +- -+
1471 
1472  // accumulate rotation into U
1473  givens_apply_u (j, i, c, s);
1474  }
1475  E_(l) = 0;
1476  E_(k) = f;
1477  S_(k) = a;
1478  }
1479  }
1480 }
1481 
1482 #undef V_