ctrsna.c
Go to the documentation of this file.
00001 /* ctrsna.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 integer c__1 = 1;
00019 
00020 /* Subroutine */ int ctrsna_(char *job, char *howmny, logical *select, 
00021         integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl, 
00022         complex *vr, integer *ldvr, real *s, real *sep, integer *mm, integer *
00023         m, complex *work, integer *ldwork, real *rwork, integer *info)
00024 {
00025     /* System generated locals */
00026     integer t_dim1, t_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, 
00027             work_dim1, work_offset, i__1, i__2, i__3, i__4, i__5;
00028     real r__1, r__2;
00029     complex q__1;
00030 
00031     /* Builtin functions */
00032     double c_abs(complex *), r_imag(complex *);
00033 
00034     /* Local variables */
00035     integer i__, j, k, ks, ix;
00036     real eps, est;
00037     integer kase, ierr;
00038     complex prod;
00039     real lnrm, rnrm, scale;
00040     extern /* Complex */ VOID cdotc_(complex *, integer *, complex *, integer 
00041             *, complex *, integer *);
00042     extern logical lsame_(char *, char *);
00043     integer isave[3];
00044     complex dummy[1];
00045     logical wants;
00046     extern /* Subroutine */ int clacn2_(integer *, complex *, complex *, real 
00047             *, integer *, integer *);
00048     real xnorm;
00049     extern doublereal scnrm2_(integer *, complex *, integer *);
00050     extern /* Subroutine */ int slabad_(real *, real *);
00051     extern integer icamax_(integer *, complex *, integer *);
00052     extern doublereal slamch_(char *);
00053     extern /* Subroutine */ int clacpy_(char *, integer *, integer *, complex 
00054             *, integer *, complex *, integer *), xerbla_(char *, 
00055             integer *);
00056     real bignum;
00057     logical wantbh;
00058     extern /* Subroutine */ int clatrs_(char *, char *, char *, char *, 
00059             integer *, complex *, integer *, complex *, real *, real *, 
00060             integer *), csrscl_(integer *, 
00061             real *, complex *, integer *), ctrexc_(char *, integer *, complex 
00062             *, integer *, complex *, integer *, integer *, integer *, integer 
00063             *);
00064     logical somcon;
00065     char normin[1];
00066     real smlnum;
00067     logical wantsp;
00068 
00069 
00070 /*  -- LAPACK routine (version 3.2) -- */
00071 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00072 /*     November 2006 */
00073 
00074 /*     Modified to call CLACN2 in place of CLACON, 10 Feb 03, SJH. */
00075 
00076 /*     .. Scalar Arguments .. */
00077 /*     .. */
00078 /*     .. Array Arguments .. */
00079 /*     .. */
00080 
00081 /*  Purpose */
00082 /*  ======= */
00083 
00084 /*  CTRSNA estimates reciprocal condition numbers for specified */
00085 /*  eigenvalues and/or right eigenvectors of a complex upper triangular */
00086 /*  matrix T (or of any matrix Q*T*Q**H with Q unitary). */
00087 
00088 /*  Arguments */
00089 /*  ========= */
00090 
00091 /*  JOB     (input) CHARACTER*1 */
00092 /*          Specifies whether condition numbers are required for */
00093 /*          eigenvalues (S) or eigenvectors (SEP): */
00094 /*          = 'E': for eigenvalues only (S); */
00095 /*          = 'V': for eigenvectors only (SEP); */
00096 /*          = 'B': for both eigenvalues and eigenvectors (S and SEP). */
00097 
00098 /*  HOWMNY  (input) CHARACTER*1 */
00099 /*          = 'A': compute condition numbers for all eigenpairs; */
00100 /*          = 'S': compute condition numbers for selected eigenpairs */
00101 /*                 specified by the array SELECT. */
00102 
00103 /*  SELECT  (input) LOGICAL array, dimension (N) */
00104 /*          If HOWMNY = 'S', SELECT specifies the eigenpairs for which */
00105 /*          condition numbers are required. To select condition numbers */
00106 /*          for the j-th eigenpair, SELECT(j) must be set to .TRUE.. */
00107 /*          If HOWMNY = 'A', SELECT is not referenced. */
00108 
00109 /*  N       (input) INTEGER */
00110 /*          The order of the matrix T. N >= 0. */
00111 
00112 /*  T       (input) COMPLEX array, dimension (LDT,N) */
00113 /*          The upper triangular matrix T. */
00114 
00115 /*  LDT     (input) INTEGER */
00116 /*          The leading dimension of the array T. LDT >= max(1,N). */
00117 
00118 /*  VL      (input) COMPLEX array, dimension (LDVL,M) */
00119 /*          If JOB = 'E' or 'B', VL must contain left eigenvectors of T */
00120 /*          (or of any Q*T*Q**H with Q unitary), corresponding to the */
00121 /*          eigenpairs specified by HOWMNY and SELECT. The eigenvectors */
00122 /*          must be stored in consecutive columns of VL, as returned by */
00123 /*          CHSEIN or CTREVC. */
00124 /*          If JOB = 'V', VL is not referenced. */
00125 
00126 /*  LDVL    (input) INTEGER */
00127 /*          The leading dimension of the array VL. */
00128 /*          LDVL >= 1; and if JOB = 'E' or 'B', LDVL >= N. */
00129 
00130 /*  VR      (input) COMPLEX array, dimension (LDVR,M) */
00131 /*          If JOB = 'E' or 'B', VR must contain right eigenvectors of T */
00132 /*          (or of any Q*T*Q**H with Q unitary), corresponding to the */
00133 /*          eigenpairs specified by HOWMNY and SELECT. The eigenvectors */
00134 /*          must be stored in consecutive columns of VR, as returned by */
00135 /*          CHSEIN or CTREVC. */
00136 /*          If JOB = 'V', VR is not referenced. */
00137 
00138 /*  LDVR    (input) INTEGER */
00139 /*          The leading dimension of the array VR. */
00140 /*          LDVR >= 1; and if JOB = 'E' or 'B', LDVR >= N. */
00141 
00142 /*  S       (output) REAL array, dimension (MM) */
00143 /*          If JOB = 'E' or 'B', the reciprocal condition numbers of the */
00144 /*          selected eigenvalues, stored in consecutive elements of the */
00145 /*          array. Thus S(j), SEP(j), and the j-th columns of VL and VR */
00146 /*          all correspond to the same eigenpair (but not in general the */
00147 /*          j-th eigenpair, unless all eigenpairs are selected). */
00148 /*          If JOB = 'V', S is not referenced. */
00149 
00150 /*  SEP     (output) REAL array, dimension (MM) */
00151 /*          If JOB = 'V' or 'B', the estimated reciprocal condition */
00152 /*          numbers of the selected eigenvectors, stored in consecutive */
00153 /*          elements of the array. */
00154 /*          If JOB = 'E', SEP is not referenced. */
00155 
00156 /*  MM      (input) INTEGER */
00157 /*          The number of elements in the arrays S (if JOB = 'E' or 'B') */
00158 /*           and/or SEP (if JOB = 'V' or 'B'). MM >= M. */
00159 
00160 /*  M       (output) INTEGER */
00161 /*          The number of elements of the arrays S and/or SEP actually */
00162 /*          used to store the estimated condition numbers. */
00163 /*          If HOWMNY = 'A', M is set to N. */
00164 
00165 /*  WORK    (workspace) COMPLEX array, dimension (LDWORK,N+6) */
00166 /*          If JOB = 'E', WORK is not referenced. */
00167 
00168 /*  LDWORK  (input) INTEGER */
00169 /*          The leading dimension of the array WORK. */
00170 /*          LDWORK >= 1; and if JOB = 'V' or 'B', LDWORK >= N. */
00171 
00172 /*  RWORK   (workspace) REAL array, dimension (N) */
00173 /*          If JOB = 'E', RWORK is not referenced. */
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 reciprocal of the condition number of an eigenvalue lambda is */
00183 /*  defined as */
00184 
00185 /*          S(lambda) = |v'*u| / (norm(u)*norm(v)) */
00186 
00187 /*  where u and v are the right and left eigenvectors of T corresponding */
00188 /*  to lambda; v' denotes the conjugate transpose of v, and norm(u) */
00189 /*  denotes the Euclidean norm. These reciprocal condition numbers always */
00190 /*  lie between zero (very badly conditioned) and one (very well */
00191 /*  conditioned). If n = 1, S(lambda) is defined to be 1. */
00192 
00193 /*  An approximate error bound for a computed eigenvalue W(i) is given by */
00194 
00195 /*                      EPS * norm(T) / S(i) */
00196 
00197 /*  where EPS is the machine precision. */
00198 
00199 /*  The reciprocal of the condition number of the right eigenvector u */
00200 /*  corresponding to lambda is defined as follows. Suppose */
00201 
00202 /*              T = ( lambda  c  ) */
00203 /*                  (   0    T22 ) */
00204 
00205 /*  Then the reciprocal condition number is */
00206 
00207 /*          SEP( lambda, T22 ) = sigma-min( T22 - lambda*I ) */
00208 
00209 /*  where sigma-min denotes the smallest singular value. We approximate */
00210 /*  the smallest singular value by the reciprocal of an estimate of the */
00211 /*  one-norm of the inverse of T22 - lambda*I. If n = 1, SEP(1) is */
00212 /*  defined to be abs(T(1,1)). */
00213 
00214 /*  An approximate error bound for a computed right eigenvector VR(i) */
00215 /*  is given by */
00216 
00217 /*                      EPS * norm(T) / SEP(i) */
00218 
00219 /*  ===================================================================== */
00220 
00221 /*     .. Parameters .. */
00222 /*     .. */
00223 /*     .. Local Scalars .. */
00224 /*     .. */
00225 /*     .. Local Arrays .. */
00226 /*     .. */
00227 /*     .. External Functions .. */
00228 /*     .. */
00229 /*     .. External Subroutines .. */
00230 /*     .. */
00231 /*     .. Intrinsic Functions .. */
00232 /*     .. */
00233 /*     .. Statement Functions .. */
00234 /*     .. */
00235 /*     .. Statement Function definitions .. */
00236 /*     .. */
00237 /*     .. Executable Statements .. */
00238 
00239 /*     Decode and test the input parameters */
00240 
00241     /* Parameter adjustments */
00242     --select;
00243     t_dim1 = *ldt;
00244     t_offset = 1 + t_dim1;
00245     t -= t_offset;
00246     vl_dim1 = *ldvl;
00247     vl_offset = 1 + vl_dim1;
00248     vl -= vl_offset;
00249     vr_dim1 = *ldvr;
00250     vr_offset = 1 + vr_dim1;
00251     vr -= vr_offset;
00252     --s;
00253     --sep;
00254     work_dim1 = *ldwork;
00255     work_offset = 1 + work_dim1;
00256     work -= work_offset;
00257     --rwork;
00258 
00259     /* Function Body */
00260     wantbh = lsame_(job, "B");
00261     wants = lsame_(job, "E") || wantbh;
00262     wantsp = lsame_(job, "V") || wantbh;
00263 
00264     somcon = lsame_(howmny, "S");
00265 
00266 /*     Set M to the number of eigenpairs for which condition numbers are */
00267 /*     to be computed. */
00268 
00269     if (somcon) {
00270         *m = 0;
00271         i__1 = *n;
00272         for (j = 1; j <= i__1; ++j) {
00273             if (select[j]) {
00274                 ++(*m);
00275             }
00276 /* L10: */
00277         }
00278     } else {
00279         *m = *n;
00280     }
00281 
00282     *info = 0;
00283     if (! wants && ! wantsp) {
00284         *info = -1;
00285     } else if (! lsame_(howmny, "A") && ! somcon) {
00286         *info = -2;
00287     } else if (*n < 0) {
00288         *info = -4;
00289     } else if (*ldt < max(1,*n)) {
00290         *info = -6;
00291     } else if (*ldvl < 1 || wants && *ldvl < *n) {
00292         *info = -8;
00293     } else if (*ldvr < 1 || wants && *ldvr < *n) {
00294         *info = -10;
00295     } else if (*mm < *m) {
00296         *info = -13;
00297     } else if (*ldwork < 1 || wantsp && *ldwork < *n) {
00298         *info = -16;
00299     }
00300     if (*info != 0) {
00301         i__1 = -(*info);
00302         xerbla_("CTRSNA", &i__1);
00303         return 0;
00304     }
00305 
00306 /*     Quick return if possible */
00307 
00308     if (*n == 0) {
00309         return 0;
00310     }
00311 
00312     if (*n == 1) {
00313         if (somcon) {
00314             if (! select[1]) {
00315                 return 0;
00316             }
00317         }
00318         if (wants) {
00319             s[1] = 1.f;
00320         }
00321         if (wantsp) {
00322             sep[1] = c_abs(&t[t_dim1 + 1]);
00323         }
00324         return 0;
00325     }
00326 
00327 /*     Get machine constants */
00328 
00329     eps = slamch_("P");
00330     smlnum = slamch_("S") / eps;
00331     bignum = 1.f / smlnum;
00332     slabad_(&smlnum, &bignum);
00333 
00334     ks = 1;
00335     i__1 = *n;
00336     for (k = 1; k <= i__1; ++k) {
00337 
00338         if (somcon) {
00339             if (! select[k]) {
00340                 goto L50;
00341             }
00342         }
00343 
00344         if (wants) {
00345 
00346 /*           Compute the reciprocal condition number of the k-th */
00347 /*           eigenvalue. */
00348 
00349             cdotc_(&q__1, n, &vr[ks * vr_dim1 + 1], &c__1, &vl[ks * vl_dim1 + 
00350                     1], &c__1);
00351             prod.r = q__1.r, prod.i = q__1.i;
00352             rnrm = scnrm2_(n, &vr[ks * vr_dim1 + 1], &c__1);
00353             lnrm = scnrm2_(n, &vl[ks * vl_dim1 + 1], &c__1);
00354             s[ks] = c_abs(&prod) / (rnrm * lnrm);
00355 
00356         }
00357 
00358         if (wantsp) {
00359 
00360 /*           Estimate the reciprocal condition number of the k-th */
00361 /*           eigenvector. */
00362 
00363 /*           Copy the matrix T to the array WORK and swap the k-th */
00364 /*           diagonal element to the (1,1) position. */
00365 
00366             clacpy_("Full", n, n, &t[t_offset], ldt, &work[work_offset], 
00367                     ldwork);
00368             ctrexc_("No Q", n, &work[work_offset], ldwork, dummy, &c__1, &k, &
00369                     c__1, &ierr);
00370 
00371 /*           Form  C = T22 - lambda*I in WORK(2:N,2:N). */
00372 
00373             i__2 = *n;
00374             for (i__ = 2; i__ <= i__2; ++i__) {
00375                 i__3 = i__ + i__ * work_dim1;
00376                 i__4 = i__ + i__ * work_dim1;
00377                 i__5 = work_dim1 + 1;
00378                 q__1.r = work[i__4].r - work[i__5].r, q__1.i = work[i__4].i - 
00379                         work[i__5].i;
00380                 work[i__3].r = q__1.r, work[i__3].i = q__1.i;
00381 /* L20: */
00382             }
00383 
00384 /*           Estimate a lower bound for the 1-norm of inv(C'). The 1st */
00385 /*           and (N+1)th columns of WORK are used to store work vectors. */
00386 
00387             sep[ks] = 0.f;
00388             est = 0.f;
00389             kase = 0;
00390             *(unsigned char *)normin = 'N';
00391 L30:
00392             i__2 = *n - 1;
00393             clacn2_(&i__2, &work[(*n + 1) * work_dim1 + 1], &work[work_offset]
00394 , &est, &kase, isave);
00395 
00396             if (kase != 0) {
00397                 if (kase == 1) {
00398 
00399 /*                 Solve C'*x = scale*b */
00400 
00401                     i__2 = *n - 1;
00402                     clatrs_("Upper", "Conjugate transpose", "Nonunit", normin, 
00403                              &i__2, &work[(work_dim1 << 1) + 2], ldwork, &
00404                             work[work_offset], &scale, &rwork[1], &ierr);
00405                 } else {
00406 
00407 /*                 Solve C*x = scale*b */
00408 
00409                     i__2 = *n - 1;
00410                     clatrs_("Upper", "No transpose", "Nonunit", normin, &i__2, 
00411                              &work[(work_dim1 << 1) + 2], ldwork, &work[
00412                             work_offset], &scale, &rwork[1], &ierr);
00413                 }
00414                 *(unsigned char *)normin = 'Y';
00415                 if (scale != 1.f) {
00416 
00417 /*                 Multiply by 1/SCALE if doing so will not cause */
00418 /*                 overflow. */
00419 
00420                     i__2 = *n - 1;
00421                     ix = icamax_(&i__2, &work[work_offset], &c__1);
00422                     i__2 = ix + work_dim1;
00423                     xnorm = (r__1 = work[i__2].r, dabs(r__1)) + (r__2 = 
00424                             r_imag(&work[ix + work_dim1]), dabs(r__2));
00425                     if (scale < xnorm * smlnum || scale == 0.f) {
00426                         goto L40;
00427                     }
00428                     csrscl_(n, &scale, &work[work_offset], &c__1);
00429                 }
00430                 goto L30;
00431             }
00432 
00433             sep[ks] = 1.f / dmax(est,smlnum);
00434         }
00435 
00436 L40:
00437         ++ks;
00438 L50:
00439         ;
00440     }
00441     return 0;
00442 
00443 /*     End of CTRSNA */
00444 
00445 } /* ctrsna_ */


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