ctrevc.c
Go to the documentation of this file.
00001 /* ctrevc.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static complex c_b2 = {1.f,0.f};
00019 static integer c__1 = 1;
00020 
00021 /* Subroutine */ int ctrevc_(char *side, char *howmny, logical *select, 
00022         integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl, 
00023         complex *vr, integer *ldvr, integer *mm, integer *m, complex *work, 
00024         real *rwork, integer *info)
00025 {
00026     /* System generated locals */
00027     integer t_dim1, t_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, i__1, 
00028             i__2, i__3, i__4, i__5;
00029     real r__1, r__2, r__3;
00030     complex q__1, q__2;
00031 
00032     /* Builtin functions */
00033     double r_imag(complex *);
00034     void r_cnjg(complex *, complex *);
00035 
00036     /* Local variables */
00037     integer i__, j, k, ii, ki, is;
00038     real ulp;
00039     logical allv;
00040     real unfl, ovfl, smin;
00041     logical over;
00042     real scale;
00043     extern logical lsame_(char *, char *);
00044     extern /* Subroutine */ int cgemv_(char *, integer *, integer *, complex *
00045 , complex *, integer *, complex *, integer *, complex *, complex *
00046 , integer *);
00047     real remax;
00048     extern /* Subroutine */ int ccopy_(integer *, complex *, integer *, 
00049             complex *, integer *);
00050     logical leftv, bothv, somev;
00051     extern /* Subroutine */ int slabad_(real *, real *);
00052     extern integer icamax_(integer *, complex *, integer *);
00053     extern doublereal slamch_(char *);
00054     extern /* Subroutine */ int csscal_(integer *, real *, complex *, integer 
00055             *), xerbla_(char *, integer *), clatrs_(char *, char *, 
00056             char *, char *, integer *, complex *, integer *, complex *, real *
00057 , real *, integer *);
00058     extern doublereal scasum_(integer *, complex *, integer *);
00059     logical rightv;
00060     real smlnum;
00061 
00062 
00063 /*  -- LAPACK routine (version 3.2) -- */
00064 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00065 /*     November 2006 */
00066 
00067 /*     .. Scalar Arguments .. */
00068 /*     .. */
00069 /*     .. Array Arguments .. */
00070 /*     .. */
00071 
00072 /*  Purpose */
00073 /*  ======= */
00074 
00075 /*  CTREVC computes some or all of the right and/or left eigenvectors of */
00076 /*  a complex upper triangular matrix T. */
00077 /*  Matrices of this type are produced by the Schur factorization of */
00078 /*  a complex general matrix:  A = Q*T*Q**H, as computed by CHSEQR. */
00079 
00080 /*  The right eigenvector x and the left eigenvector y of T corresponding */
00081 /*  to an eigenvalue w are defined by: */
00082 
00083 /*               T*x = w*x,     (y**H)*T = w*(y**H) */
00084 
00085 /*  where y**H denotes the conjugate transpose of the vector y. */
00086 /*  The eigenvalues are not input to this routine, but are read directly */
00087 /*  from the diagonal of T. */
00088 
00089 /*  This routine returns the matrices X and/or Y of right and left */
00090 /*  eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an */
00091 /*  input matrix.  If Q is the unitary factor that reduces a matrix A to */
00092 /*  Schur form T, then Q*X and Q*Y are the matrices of right and left */
00093 /*  eigenvectors of A. */
00094 
00095 /*  Arguments */
00096 /*  ========= */
00097 
00098 /*  SIDE    (input) CHARACTER*1 */
00099 /*          = 'R':  compute right eigenvectors only; */
00100 /*          = 'L':  compute left eigenvectors only; */
00101 /*          = 'B':  compute both right and left eigenvectors. */
00102 
00103 /*  HOWMNY  (input) CHARACTER*1 */
00104 /*          = 'A':  compute all right and/or left eigenvectors; */
00105 /*          = 'B':  compute all right and/or left eigenvectors, */
00106 /*                  backtransformed using the matrices supplied in */
00107 /*                  VR and/or VL; */
00108 /*          = 'S':  compute selected right and/or left eigenvectors, */
00109 /*                  as indicated by the logical array SELECT. */
00110 
00111 /*  SELECT  (input) LOGICAL array, dimension (N) */
00112 /*          If HOWMNY = 'S', SELECT specifies the eigenvectors to be */
00113 /*          computed. */
00114 /*          The eigenvector corresponding to the j-th eigenvalue is */
00115 /*          computed if SELECT(j) = .TRUE.. */
00116 /*          Not referenced if HOWMNY = 'A' or 'B'. */
00117 
00118 /*  N       (input) INTEGER */
00119 /*          The order of the matrix T. N >= 0. */
00120 
00121 /*  T       (input/output) COMPLEX array, dimension (LDT,N) */
00122 /*          The upper triangular matrix T.  T is modified, but restored */
00123 /*          on exit. */
00124 
00125 /*  LDT     (input) INTEGER */
00126 /*          The leading dimension of the array T. LDT >= max(1,N). */
00127 
00128 /*  VL      (input/output) COMPLEX array, dimension (LDVL,MM) */
00129 /*          On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must */
00130 /*          contain an N-by-N matrix Q (usually the unitary matrix Q of */
00131 /*          Schur vectors returned by CHSEQR). */
00132 /*          On exit, if SIDE = 'L' or 'B', VL contains: */
00133 /*          if HOWMNY = 'A', the matrix Y of left eigenvectors of T; */
00134 /*          if HOWMNY = 'B', the matrix Q*Y; */
00135 /*          if HOWMNY = 'S', the left eigenvectors of T specified by */
00136 /*                           SELECT, stored consecutively in the columns */
00137 /*                           of VL, in the same order as their */
00138 /*                           eigenvalues. */
00139 /*          Not referenced if SIDE = 'R'. */
00140 
00141 /*  LDVL    (input) INTEGER */
00142 /*          The leading dimension of the array VL.  LDVL >= 1, and if */
00143 /*          SIDE = 'L' or 'B', LDVL >= N. */
00144 
00145 /*  VR      (input/output) COMPLEX array, dimension (LDVR,MM) */
00146 /*          On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must */
00147 /*          contain an N-by-N matrix Q (usually the unitary matrix Q of */
00148 /*          Schur vectors returned by CHSEQR). */
00149 /*          On exit, if SIDE = 'R' or 'B', VR contains: */
00150 /*          if HOWMNY = 'A', the matrix X of right eigenvectors of T; */
00151 /*          if HOWMNY = 'B', the matrix Q*X; */
00152 /*          if HOWMNY = 'S', the right eigenvectors of T specified by */
00153 /*                           SELECT, stored consecutively in the columns */
00154 /*                           of VR, in the same order as their */
00155 /*                           eigenvalues. */
00156 /*          Not referenced if SIDE = 'L'. */
00157 
00158 /*  LDVR    (input) INTEGER */
00159 /*          The leading dimension of the array VR.  LDVR >= 1, and if */
00160 /*          SIDE = 'R' or 'B'; LDVR >= N. */
00161 
00162 /*  MM      (input) INTEGER */
00163 /*          The number of columns in the arrays VL and/or VR. MM >= M. */
00164 
00165 /*  M       (output) INTEGER */
00166 /*          The number of columns in the arrays VL and/or VR actually */
00167 /*          used to store the eigenvectors.  If HOWMNY = 'A' or 'B', M */
00168 /*          is set to N.  Each selected eigenvector occupies one */
00169 /*          column. */
00170 
00171 /*  WORK    (workspace) COMPLEX array, dimension (2*N) */
00172 
00173 /*  RWORK   (workspace) REAL array, dimension (N) */
00174 
00175 /*  INFO    (output) INTEGER */
00176 /*          = 0:  successful exit */
00177 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00178 
00179 /*  Further Details */
00180 /*  =============== */
00181 
00182 /*  The algorithm used in this program is basically backward (forward) */
00183 /*  substitution, with scaling to make the the code robust against */
00184 /*  possible overflow. */
00185 
00186 /*  Each eigenvector is normalized so that the element of largest */
00187 /*  magnitude has magnitude 1; here the magnitude of a complex number */
00188 /*  (x,y) is taken to be |x| + |y|. */
00189 
00190 /*  ===================================================================== */
00191 
00192 /*     .. Parameters .. */
00193 /*     .. */
00194 /*     .. Local Scalars .. */
00195 /*     .. */
00196 /*     .. External Functions .. */
00197 /*     .. */
00198 /*     .. External Subroutines .. */
00199 /*     .. */
00200 /*     .. Intrinsic Functions .. */
00201 /*     .. */
00202 /*     .. Statement Functions .. */
00203 /*     .. */
00204 /*     .. Statement Function definitions .. */
00205 /*     .. */
00206 /*     .. Executable Statements .. */
00207 
00208 /*     Decode and test the input parameters */
00209 
00210     /* Parameter adjustments */
00211     --select;
00212     t_dim1 = *ldt;
00213     t_offset = 1 + t_dim1;
00214     t -= t_offset;
00215     vl_dim1 = *ldvl;
00216     vl_offset = 1 + vl_dim1;
00217     vl -= vl_offset;
00218     vr_dim1 = *ldvr;
00219     vr_offset = 1 + vr_dim1;
00220     vr -= vr_offset;
00221     --work;
00222     --rwork;
00223 
00224     /* Function Body */
00225     bothv = lsame_(side, "B");
00226     rightv = lsame_(side, "R") || bothv;
00227     leftv = lsame_(side, "L") || bothv;
00228 
00229     allv = lsame_(howmny, "A");
00230     over = lsame_(howmny, "B");
00231     somev = lsame_(howmny, "S");
00232 
00233 /*     Set M to the number of columns required to store the selected */
00234 /*     eigenvectors. */
00235 
00236     if (somev) {
00237         *m = 0;
00238         i__1 = *n;
00239         for (j = 1; j <= i__1; ++j) {
00240             if (select[j]) {
00241                 ++(*m);
00242             }
00243 /* L10: */
00244         }
00245     } else {
00246         *m = *n;
00247     }
00248 
00249     *info = 0;
00250     if (! rightv && ! leftv) {
00251         *info = -1;
00252     } else if (! allv && ! over && ! somev) {
00253         *info = -2;
00254     } else if (*n < 0) {
00255         *info = -4;
00256     } else if (*ldt < max(1,*n)) {
00257         *info = -6;
00258     } else if (*ldvl < 1 || leftv && *ldvl < *n) {
00259         *info = -8;
00260     } else if (*ldvr < 1 || rightv && *ldvr < *n) {
00261         *info = -10;
00262     } else if (*mm < *m) {
00263         *info = -11;
00264     }
00265     if (*info != 0) {
00266         i__1 = -(*info);
00267         xerbla_("CTREVC", &i__1);
00268         return 0;
00269     }
00270 
00271 /*     Quick return if possible. */
00272 
00273     if (*n == 0) {
00274         return 0;
00275     }
00276 
00277 /*     Set the constants to control overflow. */
00278 
00279     unfl = slamch_("Safe minimum");
00280     ovfl = 1.f / unfl;
00281     slabad_(&unfl, &ovfl);
00282     ulp = slamch_("Precision");
00283     smlnum = unfl * (*n / ulp);
00284 
00285 /*     Store the diagonal elements of T in working array WORK. */
00286 
00287     i__1 = *n;
00288     for (i__ = 1; i__ <= i__1; ++i__) {
00289         i__2 = i__ + *n;
00290         i__3 = i__ + i__ * t_dim1;
00291         work[i__2].r = t[i__3].r, work[i__2].i = t[i__3].i;
00292 /* L20: */
00293     }
00294 
00295 /*     Compute 1-norm of each column of strictly upper triangular */
00296 /*     part of T to control overflow in triangular solver. */
00297 
00298     rwork[1] = 0.f;
00299     i__1 = *n;
00300     for (j = 2; j <= i__1; ++j) {
00301         i__2 = j - 1;
00302         rwork[j] = scasum_(&i__2, &t[j * t_dim1 + 1], &c__1);
00303 /* L30: */
00304     }
00305 
00306     if (rightv) {
00307 
00308 /*        Compute right eigenvectors. */
00309 
00310         is = *m;
00311         for (ki = *n; ki >= 1; --ki) {
00312 
00313             if (somev) {
00314                 if (! select[ki]) {
00315                     goto L80;
00316                 }
00317             }
00318 /* Computing MAX */
00319             i__1 = ki + ki * t_dim1;
00320             r__3 = ulp * ((r__1 = t[i__1].r, dabs(r__1)) + (r__2 = r_imag(&t[
00321                     ki + ki * t_dim1]), dabs(r__2)));
00322             smin = dmax(r__3,smlnum);
00323 
00324             work[1].r = 1.f, work[1].i = 0.f;
00325 
00326 /*           Form right-hand side. */
00327 
00328             i__1 = ki - 1;
00329             for (k = 1; k <= i__1; ++k) {
00330                 i__2 = k;
00331                 i__3 = k + ki * t_dim1;
00332                 q__1.r = -t[i__3].r, q__1.i = -t[i__3].i;
00333                 work[i__2].r = q__1.r, work[i__2].i = q__1.i;
00334 /* L40: */
00335             }
00336 
00337 /*           Solve the triangular system: */
00338 /*              (T(1:KI-1,1:KI-1) - T(KI,KI))*X = SCALE*WORK. */
00339 
00340             i__1 = ki - 1;
00341             for (k = 1; k <= i__1; ++k) {
00342                 i__2 = k + k * t_dim1;
00343                 i__3 = k + k * t_dim1;
00344                 i__4 = ki + ki * t_dim1;
00345                 q__1.r = t[i__3].r - t[i__4].r, q__1.i = t[i__3].i - t[i__4]
00346                         .i;
00347                 t[i__2].r = q__1.r, t[i__2].i = q__1.i;
00348                 i__2 = k + k * t_dim1;
00349                 if ((r__1 = t[i__2].r, dabs(r__1)) + (r__2 = r_imag(&t[k + k *
00350                          t_dim1]), dabs(r__2)) < smin) {
00351                     i__3 = k + k * t_dim1;
00352                     t[i__3].r = smin, t[i__3].i = 0.f;
00353                 }
00354 /* L50: */
00355             }
00356 
00357             if (ki > 1) {
00358                 i__1 = ki - 1;
00359                 clatrs_("Upper", "No transpose", "Non-unit", "Y", &i__1, &t[
00360                         t_offset], ldt, &work[1], &scale, &rwork[1], info);
00361                 i__1 = ki;
00362                 work[i__1].r = scale, work[i__1].i = 0.f;
00363             }
00364 
00365 /*           Copy the vector x or Q*x to VR and normalize. */
00366 
00367             if (! over) {
00368                 ccopy_(&ki, &work[1], &c__1, &vr[is * vr_dim1 + 1], &c__1);
00369 
00370                 ii = icamax_(&ki, &vr[is * vr_dim1 + 1], &c__1);
00371                 i__1 = ii + is * vr_dim1;
00372                 remax = 1.f / ((r__1 = vr[i__1].r, dabs(r__1)) + (r__2 = 
00373                         r_imag(&vr[ii + is * vr_dim1]), dabs(r__2)));
00374                 csscal_(&ki, &remax, &vr[is * vr_dim1 + 1], &c__1);
00375 
00376                 i__1 = *n;
00377                 for (k = ki + 1; k <= i__1; ++k) {
00378                     i__2 = k + is * vr_dim1;
00379                     vr[i__2].r = 0.f, vr[i__2].i = 0.f;
00380 /* L60: */
00381                 }
00382             } else {
00383                 if (ki > 1) {
00384                     i__1 = ki - 1;
00385                     q__1.r = scale, q__1.i = 0.f;
00386                     cgemv_("N", n, &i__1, &c_b2, &vr[vr_offset], ldvr, &work[
00387                             1], &c__1, &q__1, &vr[ki * vr_dim1 + 1], &c__1);
00388                 }
00389 
00390                 ii = icamax_(n, &vr[ki * vr_dim1 + 1], &c__1);
00391                 i__1 = ii + ki * vr_dim1;
00392                 remax = 1.f / ((r__1 = vr[i__1].r, dabs(r__1)) + (r__2 = 
00393                         r_imag(&vr[ii + ki * vr_dim1]), dabs(r__2)));
00394                 csscal_(n, &remax, &vr[ki * vr_dim1 + 1], &c__1);
00395             }
00396 
00397 /*           Set back the original diagonal elements of T. */
00398 
00399             i__1 = ki - 1;
00400             for (k = 1; k <= i__1; ++k) {
00401                 i__2 = k + k * t_dim1;
00402                 i__3 = k + *n;
00403                 t[i__2].r = work[i__3].r, t[i__2].i = work[i__3].i;
00404 /* L70: */
00405             }
00406 
00407             --is;
00408 L80:
00409             ;
00410         }
00411     }
00412 
00413     if (leftv) {
00414 
00415 /*        Compute left eigenvectors. */
00416 
00417         is = 1;
00418         i__1 = *n;
00419         for (ki = 1; ki <= i__1; ++ki) {
00420 
00421             if (somev) {
00422                 if (! select[ki]) {
00423                     goto L130;
00424                 }
00425             }
00426 /* Computing MAX */
00427             i__2 = ki + ki * t_dim1;
00428             r__3 = ulp * ((r__1 = t[i__2].r, dabs(r__1)) + (r__2 = r_imag(&t[
00429                     ki + ki * t_dim1]), dabs(r__2)));
00430             smin = dmax(r__3,smlnum);
00431 
00432             i__2 = *n;
00433             work[i__2].r = 1.f, work[i__2].i = 0.f;
00434 
00435 /*           Form right-hand side. */
00436 
00437             i__2 = *n;
00438             for (k = ki + 1; k <= i__2; ++k) {
00439                 i__3 = k;
00440                 r_cnjg(&q__2, &t[ki + k * t_dim1]);
00441                 q__1.r = -q__2.r, q__1.i = -q__2.i;
00442                 work[i__3].r = q__1.r, work[i__3].i = q__1.i;
00443 /* L90: */
00444             }
00445 
00446 /*           Solve the triangular system: */
00447 /*              (T(KI+1:N,KI+1:N) - T(KI,KI))'*X = SCALE*WORK. */
00448 
00449             i__2 = *n;
00450             for (k = ki + 1; k <= i__2; ++k) {
00451                 i__3 = k + k * t_dim1;
00452                 i__4 = k + k * t_dim1;
00453                 i__5 = ki + ki * t_dim1;
00454                 q__1.r = t[i__4].r - t[i__5].r, q__1.i = t[i__4].i - t[i__5]
00455                         .i;
00456                 t[i__3].r = q__1.r, t[i__3].i = q__1.i;
00457                 i__3 = k + k * t_dim1;
00458                 if ((r__1 = t[i__3].r, dabs(r__1)) + (r__2 = r_imag(&t[k + k *
00459                          t_dim1]), dabs(r__2)) < smin) {
00460                     i__4 = k + k * t_dim1;
00461                     t[i__4].r = smin, t[i__4].i = 0.f;
00462                 }
00463 /* L100: */
00464             }
00465 
00466             if (ki < *n) {
00467                 i__2 = *n - ki;
00468                 clatrs_("Upper", "Conjugate transpose", "Non-unit", "Y", &
00469                         i__2, &t[ki + 1 + (ki + 1) * t_dim1], ldt, &work[ki + 
00470                         1], &scale, &rwork[1], info);
00471                 i__2 = ki;
00472                 work[i__2].r = scale, work[i__2].i = 0.f;
00473             }
00474 
00475 /*           Copy the vector x or Q*x to VL and normalize. */
00476 
00477             if (! over) {
00478                 i__2 = *n - ki + 1;
00479                 ccopy_(&i__2, &work[ki], &c__1, &vl[ki + is * vl_dim1], &c__1)
00480                         ;
00481 
00482                 i__2 = *n - ki + 1;
00483                 ii = icamax_(&i__2, &vl[ki + is * vl_dim1], &c__1) + ki - 1;
00484                 i__2 = ii + is * vl_dim1;
00485                 remax = 1.f / ((r__1 = vl[i__2].r, dabs(r__1)) + (r__2 = 
00486                         r_imag(&vl[ii + is * vl_dim1]), dabs(r__2)));
00487                 i__2 = *n - ki + 1;
00488                 csscal_(&i__2, &remax, &vl[ki + is * vl_dim1], &c__1);
00489 
00490                 i__2 = ki - 1;
00491                 for (k = 1; k <= i__2; ++k) {
00492                     i__3 = k + is * vl_dim1;
00493                     vl[i__3].r = 0.f, vl[i__3].i = 0.f;
00494 /* L110: */
00495                 }
00496             } else {
00497                 if (ki < *n) {
00498                     i__2 = *n - ki;
00499                     q__1.r = scale, q__1.i = 0.f;
00500                     cgemv_("N", n, &i__2, &c_b2, &vl[(ki + 1) * vl_dim1 + 1], 
00501                             ldvl, &work[ki + 1], &c__1, &q__1, &vl[ki * 
00502                             vl_dim1 + 1], &c__1);
00503                 }
00504 
00505                 ii = icamax_(n, &vl[ki * vl_dim1 + 1], &c__1);
00506                 i__2 = ii + ki * vl_dim1;
00507                 remax = 1.f / ((r__1 = vl[i__2].r, dabs(r__1)) + (r__2 = 
00508                         r_imag(&vl[ii + ki * vl_dim1]), dabs(r__2)));
00509                 csscal_(n, &remax, &vl[ki * vl_dim1 + 1], &c__1);
00510             }
00511 
00512 /*           Set back the original diagonal elements of T. */
00513 
00514             i__2 = *n;
00515             for (k = ki + 1; k <= i__2; ++k) {
00516                 i__3 = k + k * t_dim1;
00517                 i__4 = k + *n;
00518                 t[i__3].r = work[i__4].r, t[i__3].i = work[i__4].i;
00519 /* L120: */
00520             }
00521 
00522             ++is;
00523 L130:
00524             ;
00525         }
00526     }
00527 
00528     return 0;
00529 
00530 /*     End of CTREVC */
00531 
00532 } /* ctrevc_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:34