Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

eis_tsturm.c File Reference

#include "f2c.h"

Go to the source code of this file.


Functions

int tsturm_ (integer *nm, integer *n, doublereal *eps1, doublereal *d__, doublereal *e, doublereal *e2, doublereal *lb, doublereal *ub, integer *mm, integer *m, doublereal *w, doublereal *z__, integer *ierr, doublereal *rv1, doublereal *rv2, doublereal *rv3, doublereal *rv4, doublereal *rv5, doublereal *rv6)

Variables

doublereal c_b26 = 1.

Function Documentation

int tsturm_ integer   nm,
integer   n,
doublereal   eps1,
doublereal   d__,
doublereal   e,
doublereal   e2,
doublereal   lb,
doublereal   ub,
integer   mm,
integer   m,
doublereal   w,
doublereal   z__,
integer   ierr,
doublereal   rv1,
doublereal   rv2,
doublereal   rv3,
doublereal   rv4,
doublereal   rv5,
doublereal   rv6
 

Definition at line 12 of file eis_tsturm.c.

References abs, c_b26, epslon_(), m1, m2, max, min, p, pythag_(), q, v, and x0.

00017 {
00018     /* System generated locals */
00019     integer z_dim1, z_offset, i__1, i__2, i__3;
00020     doublereal d__1, d__2, d__3, d__4;
00021 
00022     /* Builtin functions */
00023     double sqrt(doublereal);
00024 
00025     /* Local variables */
00026     static doublereal norm;
00027     static integer i__, j, k, p, q, r__, s;
00028     static doublereal u, v;
00029     static integer group, m1, m2;
00030     static doublereal t1, t2, x0, x1;
00031     static integer ii, jj, ip;
00032     static doublereal uk, xu;
00033     extern doublereal pythag_(doublereal *, doublereal *), epslon_(doublereal 
00034             *);
00035     static integer isturm, its;
00036     static doublereal eps2, eps3, eps4, tst1, tst2;
00037 
00038 
00039 
00040 /*     THIS SUBROUTINE IS A TRANSLATION OF THE ALGOL PROCEDURE TRISTURM */
00041 /*     BY PETERS AND WILKINSON. */
00042 /*     HANDBOOK FOR AUTO. COMP., VOL.II-LINEAR ALGEBRA, 418-439(1971). */
00043 
00044 /*     THIS SUBROUTINE FINDS THOSE EIGENVALUES OF A TRIDIAGONAL */
00045 /*     SYMMETRIC MATRIX WHICH LIE IN A SPECIFIED INTERVAL AND THEIR */
00046 /*     ASSOCIATED EIGENVECTORS, USING BISECTION AND INVERSE ITERATION. */
00047 
00048 /*     ON INPUT */
00049 
00050 /*        NM MUST BE SET TO THE ROW DIMENSION OF TWO-DIMENSIONAL */
00051 /*          ARRAY PARAMETERS AS DECLARED IN THE CALLING PROGRAM */
00052 /*          DIMENSION STATEMENT. */
00053 
00054 /*        N IS THE ORDER OF THE MATRIX. */
00055 
00056 /*        EPS1 IS AN ABSOLUTE ERROR TOLERANCE FOR THE COMPUTED */
00057 /*          EIGENVALUES.  IT SHOULD BE CHOSEN COMMENSURATE WITH */
00058 /*          RELATIVE PERTURBATIONS IN THE MATRIX ELEMENTS OF THE */
00059 /*          ORDER OF THE RELATIVE MACHINE PRECISION.  IF THE */
00060 /*          INPUT EPS1 IS NON-POSITIVE, IT IS RESET FOR EACH */
00061 /*          SUBMATRIX TO A DEFAULT VALUE, NAMELY, MINUS THE */
00062 /*          PRODUCT OF THE RELATIVE MACHINE PRECISION AND THE */
00063 /*          1-NORM OF THE SUBMATRIX. */
00064 
00065 /*        D CONTAINS THE DIAGONAL ELEMENTS OF THE INPUT MATRIX. */
00066 
00067 /*        E CONTAINS THE SUBDIAGONAL ELEMENTS OF THE INPUT MATRIX */
00068 /*          IN ITS LAST N-1 POSITIONS.  E(1) IS ARBITRARY. */
00069 
00070 /*        E2 CONTAINS THE SQUARES OF THE CORRESPONDING ELEMENTS OF E. */
00071 /*          E2(1) IS ARBITRARY. */
00072 
00073 /*        LB AND UB DEFINE THE INTERVAL TO BE SEARCHED FOR EIGENVALUES. */
00074 /*          IF LB IS NOT LESS THAN UB, NO EIGENVALUES WILL BE FOUND. */
00075 
00076 /*        MM SHOULD BE SET TO AN UPPER BOUND FOR THE NUMBER OF */
00077 /*          EIGENVALUES IN THE INTERVAL.  WARNING. IF MORE THAN */
00078 /*          MM EIGENVALUES ARE DETERMINED TO LIE IN THE INTERVAL, */
00079 /*          AN ERROR RETURN IS MADE WITH NO VALUES OR VECTORS FOUND. */
00080 
00081 /*     ON OUTPUT */
00082 
00083 /*        EPS1 IS UNALTERED UNLESS IT HAS BEEN RESET TO ITS */
00084 /*          (LAST) DEFAULT VALUE. */
00085 
00086 /*        D AND E ARE UNALTERED. */
00087 
00088 /*        ELEMENTS OF E2, CORRESPONDING TO ELEMENTS OF E REGARDED */
00089 /*          AS NEGLIGIBLE, HAVE BEEN REPLACED BY ZERO CAUSING THE */
00090 /*          MATRIX TO SPLIT INTO A DIRECT SUM OF SUBMATRICES. */
00091 /*          E2(1) IS ALSO SET TO ZERO. */
00092 
00093 /*        M IS THE NUMBER OF EIGENVALUES DETERMINED TO LIE IN (LB,UB). */
00094 
00095 /*        W CONTAINS THE M EIGENVALUES IN ASCENDING ORDER IF THE MATRIX */
00096 /*          DOES NOT SPLIT.  IF THE MATRIX SPLITS, THE EIGENVALUES ARE */
00097 /*          IN ASCENDING ORDER FOR EACH SUBMATRIX.  IF A VECTOR ERROR */
00098 /*          EXIT IS MADE, W CONTAINS THOSE VALUES ALREADY FOUND. */
00099 
00100 /*        Z CONTAINS THE ASSOCIATED SET OF ORTHONORMAL EIGENVECTORS. */
00101 /*          IF AN ERROR EXIT IS MADE, Z CONTAINS THOSE VECTORS */
00102 /*          ALREADY FOUND. */
00103 
00104 /*        IERR IS SET TO */
00105 /*          ZERO       FOR NORMAL RETURN, */
00106 /*          3*N+1      IF M EXCEEDS MM. */
00107 /*          4*N+R      IF THE EIGENVECTOR CORRESPONDING TO THE R-TH */
00108 /*                     EIGENVALUE FAILS TO CONVERGE IN 5 ITERATIONS. */
00109 
00110 /*        RV1, RV2, RV3, RV4, RV5, AND RV6 ARE TEMPORARY STORAGE ARRAYS. 
00111 */
00112 
00113 /*     THE ALGOL PROCEDURE STURMCNT CONTAINED IN TRISTURM */
00114 /*     APPEARS IN TSTURM IN-LINE. */
00115 
00116 /*     CALLS PYTHAG FOR  DSQRT(A*A + B*B) . */
00117 
00118 /*     QUESTIONS AND COMMENTS SHOULD BE DIRECTED TO BURTON S. GARBOW, */
00119 /*     MATHEMATICS AND COMPUTER SCIENCE DIV, ARGONNE NATIONAL LABORATORY 
00120 */
00121 
00122 /*     THIS VERSION DATED AUGUST 1983. */
00123 
00124 /*     ------------------------------------------------------------------ 
00125 */
00126 
00127     /* Parameter adjustments */
00128     --rv6;
00129     --rv5;
00130     --rv4;
00131     --rv3;
00132     --rv2;
00133     --rv1;
00134     --e2;
00135     --e;
00136     --d__;
00137     z_dim1 = *nm;
00138     z_offset = z_dim1 + 1;
00139     z__ -= z_offset;
00140     --w;
00141 
00142     /* Function Body */
00143     *ierr = 0;
00144     t1 = *lb;
00145     t2 = *ub;
00146 /*     .......... LOOK FOR SMALL SUB-DIAGONAL ENTRIES .......... */
00147     i__1 = *n;
00148     for (i__ = 1; i__ <= i__1; ++i__) {
00149         if (i__ == 1) {
00150             goto L20;
00151         }
00152         tst1 = (d__1 = d__[i__], abs(d__1)) + (d__2 = d__[i__ - 1], abs(d__2))
00153                 ;
00154         tst2 = tst1 + (d__1 = e[i__], abs(d__1));
00155         if (tst2 > tst1) {
00156             goto L40;
00157         }
00158 L20:
00159         e2[i__] = 0.;
00160 L40:
00161         ;
00162     }
00163 /*     .......... DETERMINE THE NUMBER OF EIGENVALUES */
00164 /*                IN THE INTERVAL .......... */
00165     p = 1;
00166     q = *n;
00167     x1 = *ub;
00168     isturm = 1;
00169     goto L320;
00170 L60:
00171     *m = s;
00172     x1 = *lb;
00173     isturm = 2;
00174     goto L320;
00175 L80:
00176     *m -= s;
00177     if (*m > *mm) {
00178         goto L980;
00179     }
00180     q = 0;
00181     r__ = 0;
00182 /*     .......... ESTABLISH AND PROCESS NEXT SUBMATRIX, REFINING */
00183 /*                INTERVAL BY THE GERSCHGORIN BOUNDS .......... */
00184 L100:
00185     if (r__ == *m) {
00186         goto L1001;
00187     }
00188     p = q + 1;
00189     xu = d__[p];
00190     x0 = d__[p];
00191     u = 0.;
00192 
00193     i__1 = *n;
00194     for (q = p; q <= i__1; ++q) {
00195         x1 = u;
00196         u = 0.;
00197         v = 0.;
00198         if (q == *n) {
00199             goto L110;
00200         }
00201         u = (d__1 = e[q + 1], abs(d__1));
00202         v = e2[q + 1];
00203 L110:
00204 /* Computing MIN */
00205         d__1 = d__[q] - (x1 + u);
00206         xu = min(d__1,xu);
00207 /* Computing MAX */
00208         d__1 = d__[q] + (x1 + u);
00209         x0 = max(d__1,x0);
00210         if (v == 0.) {
00211             goto L140;
00212         }
00213 /* L120: */
00214     }
00215 
00216 L140:
00217 /* Computing MAX */
00218     d__2 = abs(xu), d__3 = abs(x0);
00219     d__1 = max(d__2,d__3);
00220     x1 = epslon_(&d__1);
00221     if (*eps1 <= 0.) {
00222         *eps1 = -x1;
00223     }
00224     if (p != q) {
00225         goto L180;
00226     }
00227 /*     .......... CHECK FOR ISOLATED ROOT WITHIN INTERVAL .......... */
00228     if (t1 > d__[p] || d__[p] >= t2) {
00229         goto L940;
00230     }
00231     ++r__;
00232 
00233     i__1 = *n;
00234     for (i__ = 1; i__ <= i__1; ++i__) {
00235 /* L160: */
00236         z__[i__ + r__ * z_dim1] = 0.;
00237     }
00238 
00239     w[r__] = d__[p];
00240     z__[p + r__ * z_dim1] = 1.;
00241     goto L940;
00242 L180:
00243     u = (doublereal) (q - p + 1);
00244     x1 = u * x1;
00245 /* Computing MAX */
00246     d__1 = t1, d__2 = xu - x1;
00247     *lb = max(d__1,d__2);
00248 /* Computing MIN */
00249     d__1 = t2, d__2 = x0 + x1;
00250     *ub = min(d__1,d__2);
00251     x1 = *lb;
00252     isturm = 3;
00253     goto L320;
00254 L200:
00255     m1 = s + 1;
00256     x1 = *ub;
00257     isturm = 4;
00258     goto L320;
00259 L220:
00260     m2 = s;
00261     if (m1 > m2) {
00262         goto L940;
00263     }
00264 /*     .......... FIND ROOTS BY BISECTION .......... */
00265     x0 = *ub;
00266     isturm = 5;
00267 
00268     i__1 = m2;
00269     for (i__ = m1; i__ <= i__1; ++i__) {
00270         rv5[i__] = *ub;
00271         rv4[i__] = *lb;
00272 /* L240: */
00273     }
00274 /*     .......... LOOP FOR K-TH EIGENVALUE */
00275 /*                FOR K=M2 STEP -1 UNTIL M1 DO -- */
00276 /*                (-DO- NOT USED TO LEGALIZE -COMPUTED GO TO-) .......... 
00277 */
00278     k = m2;
00279 L250:
00280     xu = *lb;
00281 /*     .......... FOR I=K STEP -1 UNTIL M1 DO -- .......... */
00282     i__1 = k;
00283     for (ii = m1; ii <= i__1; ++ii) {
00284         i__ = m1 + k - ii;
00285         if (xu >= rv4[i__]) {
00286             goto L260;
00287         }
00288         xu = rv4[i__];
00289         goto L280;
00290 L260:
00291         ;
00292     }
00293 
00294 L280:
00295     if (x0 > rv5[k]) {
00296         x0 = rv5[k];
00297     }
00298 /*     .......... NEXT BISECTION STEP .......... */
00299 L300:
00300     x1 = (xu + x0) * .5;
00301     if (x0 - xu <= abs(*eps1)) {
00302         goto L420;
00303     }
00304     tst1 = (abs(xu) + abs(x0)) * 2.;
00305     tst2 = tst1 + (x0 - xu);
00306     if (tst2 == tst1) {
00307         goto L420;
00308     }
00309 /*     .......... IN-LINE PROCEDURE FOR STURM SEQUENCE .......... */
00310 L320:
00311     s = p - 1;
00312     u = 1.;
00313 
00314     i__1 = q;
00315     for (i__ = p; i__ <= i__1; ++i__) {
00316         if (u != 0.) {
00317             goto L325;
00318         }
00319         v = (d__1 = e[i__], abs(d__1)) / epslon_(&c_b26);
00320         if (e2[i__] == 0.) {
00321             v = 0.;
00322         }
00323         goto L330;
00324 L325:
00325         v = e2[i__] / u;
00326 L330:
00327         u = d__[i__] - x1 - v;
00328         if (u < 0.) {
00329             ++s;
00330         }
00331 /* L340: */
00332     }
00333 
00334     switch (isturm) {
00335         case 1:  goto L60;
00336         case 2:  goto L80;
00337         case 3:  goto L200;
00338         case 4:  goto L220;
00339         case 5:  goto L360;
00340     }
00341 /*     .......... REFINE INTERVALS .......... */
00342 L360:
00343     if (s >= k) {
00344         goto L400;
00345     }
00346     xu = x1;
00347     if (s >= m1) {
00348         goto L380;
00349     }
00350     rv4[m1] = x1;
00351     goto L300;
00352 L380:
00353     rv4[s + 1] = x1;
00354     if (rv5[s] > x1) {
00355         rv5[s] = x1;
00356     }
00357     goto L300;
00358 L400:
00359     x0 = x1;
00360     goto L300;
00361 /*     .......... K-TH EIGENVALUE FOUND .......... */
00362 L420:
00363     rv5[k] = x1;
00364     --k;
00365     if (k >= m1) {
00366         goto L250;
00367     }
00368 /*     .......... FIND VECTORS BY INVERSE ITERATION .......... */
00369     norm = (d__1 = d__[p], abs(d__1));
00370     ip = p + 1;
00371 
00372     i__1 = q;
00373     for (i__ = ip; i__ <= i__1; ++i__) {
00374 /* L500: */
00375 /* Computing MAX */
00376         d__3 = norm, d__4 = (d__1 = d__[i__], abs(d__1)) + (d__2 = e[i__], 
00377                 abs(d__2));
00378         norm = max(d__3,d__4);
00379     }
00380 /*     .......... EPS2 IS THE CRITERION FOR GROUPING, */
00381 /*                EPS3 REPLACES ZERO PIVOTS AND EQUAL */
00382 /*                ROOTS ARE MODIFIED BY EPS3, */
00383 /*                EPS4 IS TAKEN VERY SMALL TO AVOID OVERFLOW .......... */
00384     eps2 = norm * .001;
00385     eps3 = epslon_(&norm);
00386     uk = (doublereal) (q - p + 1);
00387     eps4 = uk * eps3;
00388     uk = eps4 / sqrt(uk);
00389     group = 0;
00390     s = p;
00391 
00392     i__1 = m2;
00393     for (k = m1; k <= i__1; ++k) {
00394         ++r__;
00395         its = 1;
00396         w[r__] = rv5[k];
00397         x1 = rv5[k];
00398 /*     .......... LOOK FOR CLOSE OR COINCIDENT ROOTS .......... */
00399         if (k == m1) {
00400             goto L520;
00401         }
00402         if (x1 - x0 >= eps2) {
00403             group = -1;
00404         }
00405         ++group;
00406         if (x1 <= x0) {
00407             x1 = x0 + eps3;
00408         }
00409 /*     .......... ELIMINATION WITH INTERCHANGES AND */
00410 /*                INITIALIZATION OF VECTOR .......... */
00411 L520:
00412         v = 0.;
00413 
00414         i__2 = q;
00415         for (i__ = p; i__ <= i__2; ++i__) {
00416             rv6[i__] = uk;
00417             if (i__ == p) {
00418                 goto L560;
00419             }
00420             if ((d__1 = e[i__], abs(d__1)) < abs(u)) {
00421                 goto L540;
00422             }
00423             xu = u / e[i__];
00424             rv4[i__] = xu;
00425             rv1[i__ - 1] = e[i__];
00426             rv2[i__ - 1] = d__[i__] - x1;
00427             rv3[i__ - 1] = 0.;
00428             if (i__ != q) {
00429                 rv3[i__ - 1] = e[i__ + 1];
00430             }
00431             u = v - xu * rv2[i__ - 1];
00432             v = -xu * rv3[i__ - 1];
00433             goto L580;
00434 L540:
00435             xu = e[i__] / u;
00436             rv4[i__] = xu;
00437             rv1[i__ - 1] = u;
00438             rv2[i__ - 1] = v;
00439             rv3[i__ - 1] = 0.;
00440 L560:
00441             u = d__[i__] - x1 - xu * v;
00442             if (i__ != q) {
00443                 v = e[i__ + 1];
00444             }
00445 L580:
00446             ;
00447         }
00448 
00449         if (u == 0.) {
00450             u = eps3;
00451         }
00452         rv1[q] = u;
00453         rv2[q] = 0.;
00454         rv3[q] = 0.;
00455 /*     .......... BACK SUBSTITUTION */
00456 /*                FOR I=Q STEP -1 UNTIL P DO -- .......... */
00457 L600:
00458         i__2 = q;
00459         for (ii = p; ii <= i__2; ++ii) {
00460             i__ = p + q - ii;
00461             rv6[i__] = (rv6[i__] - u * rv2[i__] - v * rv3[i__]) / rv1[i__];
00462             v = u;
00463             u = rv6[i__];
00464 /* L620: */
00465         }
00466 /*     .......... ORTHOGONALIZE WITH RESPECT TO PREVIOUS */
00467 /*                MEMBERS OF GROUP .......... */
00468         if (group == 0) {
00469             goto L700;
00470         }
00471 
00472         i__2 = group;
00473         for (jj = 1; jj <= i__2; ++jj) {
00474             j = r__ - group - 1 + jj;
00475             xu = 0.;
00476 
00477             i__3 = q;
00478             for (i__ = p; i__ <= i__3; ++i__) {
00479 /* L640: */
00480                 xu += rv6[i__] * z__[i__ + j * z_dim1];
00481             }
00482 
00483             i__3 = q;
00484             for (i__ = p; i__ <= i__3; ++i__) {
00485 /* L660: */
00486                 rv6[i__] -= xu * z__[i__ + j * z_dim1];
00487             }
00488 
00489 /* L680: */
00490         }
00491 
00492 L700:
00493         norm = 0.;
00494 
00495         i__2 = q;
00496         for (i__ = p; i__ <= i__2; ++i__) {
00497 /* L720: */
00498             norm += (d__1 = rv6[i__], abs(d__1));
00499         }
00500 
00501         if (norm >= 1.) {
00502             goto L840;
00503         }
00504 /*     .......... FORWARD SUBSTITUTION .......... */
00505         if (its == 5) {
00506             goto L960;
00507         }
00508         if (norm != 0.) {
00509             goto L740;
00510         }
00511         rv6[s] = eps4;
00512         ++s;
00513         if (s > q) {
00514             s = p;
00515         }
00516         goto L780;
00517 L740:
00518         xu = eps4 / norm;
00519 
00520         i__2 = q;
00521         for (i__ = p; i__ <= i__2; ++i__) {
00522 /* L760: */
00523             rv6[i__] *= xu;
00524         }
00525 /*     .......... ELIMINATION OPERATIONS ON NEXT VECTOR */
00526 /*                ITERATE .......... */
00527 L780:
00528         i__2 = q;
00529         for (i__ = ip; i__ <= i__2; ++i__) {
00530             u = rv6[i__];
00531 /*     .......... IF RV1(I-1) .EQ. E(I), A ROW INTERCHANGE */
00532 /*                WAS PERFORMED EARLIER IN THE */
00533 /*                TRIANGULARIZATION PROCESS .......... */
00534             if (rv1[i__ - 1] != e[i__]) {
00535                 goto L800;
00536             }
00537             u = rv6[i__ - 1];
00538             rv6[i__ - 1] = rv6[i__];
00539 L800:
00540             rv6[i__] = u - rv4[i__] * rv6[i__ - 1];
00541 /* L820: */
00542         }
00543 
00544         ++its;
00545         goto L600;
00546 /*     .......... NORMALIZE SO THAT SUM OF SQUARES IS */
00547 /*                1 AND EXPAND TO FULL ORDER .......... */
00548 L840:
00549         u = 0.;
00550 
00551         i__2 = q;
00552         for (i__ = p; i__ <= i__2; ++i__) {
00553 /* L860: */
00554             u = pythag_(&u, &rv6[i__]);
00555         }
00556 
00557         xu = 1. / u;
00558 
00559         i__2 = *n;
00560         for (i__ = 1; i__ <= i__2; ++i__) {
00561 /* L880: */
00562             z__[i__ + r__ * z_dim1] = 0.;
00563         }
00564 
00565         i__2 = q;
00566         for (i__ = p; i__ <= i__2; ++i__) {
00567 /* L900: */
00568             z__[i__ + r__ * z_dim1] = rv6[i__] * xu;
00569         }
00570 
00571         x0 = x1;
00572 /* L920: */
00573     }
00574 
00575 L940:
00576     if (q < *n) {
00577         goto L100;
00578     }
00579     goto L1001;
00580 /*     .......... SET ERROR -- NON-CONVERGED EIGENVECTOR .......... */
00581 L960:
00582     *ierr = (*n << 2) + r__;
00583     goto L1001;
00584 /*     .......... SET ERROR -- UNDERESTIMATE OF NUMBER OF */
00585 /*                EIGENVALUES IN INTERVAL .......... */
00586 L980:
00587     *ierr = *n * 3 + 1;
00588 L1001:
00589     *lb = t1;
00590     *ub = t2;
00591     return 0;
00592 } /* tsturm_ */

Variable Documentation

doublereal c_b26 = 1. [static]
 

Definition at line 10 of file eis_tsturm.c.

Referenced by tsturm_().

 

Powered by Plone

This site conforms to the following standards: