ztgsna.c
Go to the documentation of this file.
00001 /* ztgsna.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 static doublecomplex c_b19 = {1.,0.};
00020 static doublecomplex c_b20 = {0.,0.};
00021 static logical c_false = FALSE_;
00022 static integer c__3 = 3;
00023 
00024 /* Subroutine */ int ztgsna_(char *job, char *howmny, logical *select, 
00025         integer *n, doublecomplex *a, integer *lda, doublecomplex *b, integer 
00026         *ldb, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
00027         ldvr, doublereal *s, doublereal *dif, integer *mm, integer *m, 
00028         doublecomplex *work, integer *lwork, integer *iwork, integer *info)
00029 {
00030     /* System generated locals */
00031     integer a_dim1, a_offset, b_dim1, b_offset, vl_dim1, vl_offset, vr_dim1, 
00032             vr_offset, i__1;
00033     doublereal d__1, d__2;
00034     doublecomplex z__1;
00035 
00036     /* Builtin functions */
00037     double z_abs(doublecomplex *);
00038 
00039     /* Local variables */
00040     integer i__, k, n1, n2, ks;
00041     doublereal eps, cond;
00042     integer ierr, ifst;
00043     doublereal lnrm;
00044     doublecomplex yhax, yhbx;
00045     integer ilst;
00046     doublereal rnrm, scale;
00047     extern logical lsame_(char *, char *);
00048     extern /* Double Complex */ VOID zdotc_(doublecomplex *, integer *, 
00049             doublecomplex *, integer *, doublecomplex *, integer *);
00050     integer lwmin;
00051     extern /* Subroutine */ int zgemv_(char *, integer *, integer *, 
00052             doublecomplex *, doublecomplex *, integer *, doublecomplex *, 
00053             integer *, doublecomplex *, doublecomplex *, integer *);
00054     logical wants;
00055     doublecomplex dummy[1];
00056     extern doublereal dlapy2_(doublereal *, doublereal *);
00057     extern /* Subroutine */ int dlabad_(doublereal *, doublereal *);
00058     doublecomplex dummy1[1];
00059     extern doublereal dznrm2_(integer *, doublecomplex *, integer *), dlamch_(
00060             char *);
00061     extern /* Subroutine */ int xerbla_(char *, integer *);
00062     doublereal bignum;
00063     logical wantbh, wantdf, somcon;
00064     extern /* Subroutine */ int zlacpy_(char *, integer *, integer *, 
00065             doublecomplex *, integer *, doublecomplex *, integer *), 
00066             ztgexc_(logical *, logical *, integer *, doublecomplex *, integer 
00067             *, doublecomplex *, integer *, doublecomplex *, integer *, 
00068             doublecomplex *, integer *, integer *, integer *, integer *);
00069     doublereal smlnum;
00070     logical lquery;
00071     extern /* Subroutine */ int ztgsyl_(char *, integer *, integer *, integer 
00072             *, doublecomplex *, integer *, doublecomplex *, integer *, 
00073             doublecomplex *, integer *, doublecomplex *, integer *, 
00074             doublecomplex *, integer *, doublecomplex *, integer *, 
00075             doublereal *, doublereal *, doublecomplex *, integer *, integer *, 
00076              integer *);
00077 
00078 
00079 /*  -- LAPACK routine (version 3.2) -- */
00080 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00081 /*     November 2006 */
00082 
00083 /*     .. Scalar Arguments .. */
00084 /*     .. */
00085 /*     .. Array Arguments .. */
00086 /*     .. */
00087 
00088 /*  Purpose */
00089 /*  ======= */
00090 
00091 /*  ZTGSNA estimates reciprocal condition numbers for specified */
00092 /*  eigenvalues and/or eigenvectors of a matrix pair (A, B). */
00093 
00094 /*  (A, B) must be in generalized Schur canonical form, that is, A and */
00095 /*  B are both upper triangular. */
00096 
00097 /*  Arguments */
00098 /*  ========= */
00099 
00100 /*  JOB     (input) CHARACTER*1 */
00101 /*          Specifies whether condition numbers are required for */
00102 /*          eigenvalues (S) or eigenvectors (DIF): */
00103 /*          = 'E': for eigenvalues only (S); */
00104 /*          = 'V': for eigenvectors only (DIF); */
00105 /*          = 'B': for both eigenvalues and eigenvectors (S and DIF). */
00106 
00107 /*  HOWMNY  (input) CHARACTER*1 */
00108 /*          = 'A': compute condition numbers for all eigenpairs; */
00109 /*          = 'S': compute condition numbers for selected eigenpairs */
00110 /*                 specified by the array SELECT. */
00111 
00112 /*  SELECT  (input) LOGICAL array, dimension (N) */
00113 /*          If HOWMNY = 'S', SELECT specifies the eigenpairs for which */
00114 /*          condition numbers are required. To select condition numbers */
00115 /*          for the corresponding j-th eigenvalue and/or eigenvector, */
00116 /*          SELECT(j) must be set to .TRUE.. */
00117 /*          If HOWMNY = 'A', SELECT is not referenced. */
00118 
00119 /*  N       (input) INTEGER */
00120 /*          The order of the square matrix pair (A, B). N >= 0. */
00121 
00122 /*  A       (input) COMPLEX*16 array, dimension (LDA,N) */
00123 /*          The upper triangular matrix A in the pair (A,B). */
00124 
00125 /*  LDA     (input) INTEGER */
00126 /*          The leading dimension of the array A. LDA >= max(1,N). */
00127 
00128 /*  B       (input) COMPLEX*16 array, dimension (LDB,N) */
00129 /*          The upper triangular matrix B in the pair (A, B). */
00130 
00131 /*  LDB     (input) INTEGER */
00132 /*          The leading dimension of the array B. LDB >= max(1,N). */
00133 
00134 /*  VL      (input) COMPLEX*16 array, dimension (LDVL,M) */
00135 /*          IF JOB = 'E' or 'B', VL must contain left eigenvectors of */
00136 /*          (A, B), corresponding to the eigenpairs specified by HOWMNY */
00137 /*          and SELECT.  The eigenvectors must be stored in consecutive */
00138 /*          columns of VL, as returned by ZTGEVC. */
00139 /*          If JOB = 'V', VL is not referenced. */
00140 
00141 /*  LDVL    (input) INTEGER */
00142 /*          The leading dimension of the array VL. LDVL >= 1; and */
00143 /*          If JOB = 'E' or 'B', LDVL >= N. */
00144 
00145 /*  VR      (input) COMPLEX*16 array, dimension (LDVR,M) */
00146 /*          IF JOB = 'E' or 'B', VR must contain right eigenvectors of */
00147 /*          (A, B), corresponding to the eigenpairs specified by HOWMNY */
00148 /*          and SELECT.  The eigenvectors must be stored in consecutive */
00149 /*          columns of VR, as returned by ZTGEVC. */
00150 /*          If JOB = 'V', VR is not referenced. */
00151 
00152 /*  LDVR    (input) INTEGER */
00153 /*          The leading dimension of the array VR. LDVR >= 1; */
00154 /*          If JOB = 'E' or 'B', LDVR >= N. */
00155 
00156 /*  S       (output) DOUBLE PRECISION array, dimension (MM) */
00157 /*          If JOB = 'E' or 'B', the reciprocal condition numbers of the */
00158 /*          selected eigenvalues, stored in consecutive elements of the */
00159 /*          array. */
00160 /*          If JOB = 'V', S is not referenced. */
00161 
00162 /*  DIF     (output) DOUBLE PRECISION array, dimension (MM) */
00163 /*          If JOB = 'V' or 'B', the estimated reciprocal condition */
00164 /*          numbers of the selected eigenvectors, stored in consecutive */
00165 /*          elements of the array. */
00166 /*          If the eigenvalues cannot be reordered to compute DIF(j), */
00167 /*          DIF(j) is set to 0; this can only occur when the true value */
00168 /*          would be very small anyway. */
00169 /*          For each eigenvalue/vector specified by SELECT, DIF stores */
00170 /*          a Frobenius norm-based estimate of Difl. */
00171 /*          If JOB = 'E', DIF is not referenced. */
00172 
00173 /*  MM      (input) INTEGER */
00174 /*          The number of elements in the arrays S and DIF. MM >= M. */
00175 
00176 /*  M       (output) INTEGER */
00177 /*          The number of elements of the arrays S and DIF used to store */
00178 /*          the specified condition numbers; for each selected eigenvalue */
00179 /*          one element is used. If HOWMNY = 'A', M is set to N. */
00180 
00181 /*  WORK    (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) */
00182 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
00183 
00184 /*  LWORK  (input) INTEGER */
00185 /*          The dimension of the array WORK. LWORK >= max(1,N). */
00186 /*          If JOB = 'V' or 'B', LWORK >= max(1,2*N*N). */
00187 
00188 /*  IWORK   (workspace) INTEGER array, dimension (N+2) */
00189 /*          If JOB = 'E', IWORK is not referenced. */
00190 
00191 /*  INFO    (output) INTEGER */
00192 /*          = 0: Successful exit */
00193 /*          < 0: If INFO = -i, the i-th argument had an illegal value */
00194 
00195 /*  Further Details */
00196 /*  =============== */
00197 
00198 /*  The reciprocal of the condition number of the i-th generalized */
00199 /*  eigenvalue w = (a, b) is defined as */
00200 
00201 /*          S(I) = (|v'Au|**2 + |v'Bu|**2)**(1/2) / (norm(u)*norm(v)) */
00202 
00203 /*  where u and v are the right and left eigenvectors of (A, B) */
00204 /*  corresponding to w; |z| denotes the absolute value of the complex */
00205 /*  number, and norm(u) denotes the 2-norm of the vector u. The pair */
00206 /*  (a, b) corresponds to an eigenvalue w = a/b (= v'Au/v'Bu) of the */
00207 /*  matrix pair (A, B). If both a and b equal zero, then (A,B) is */
00208 /*  singular and S(I) = -1 is returned. */
00209 
00210 /*  An approximate error bound on the chordal distance between the i-th */
00211 /*  computed generalized eigenvalue w and the corresponding exact */
00212 /*  eigenvalue lambda is */
00213 
00214 /*          chord(w, lambda) <=   EPS * norm(A, B) / S(I), */
00215 
00216 /*  where EPS is the machine precision. */
00217 
00218 /*  The reciprocal of the condition number of the right eigenvector u */
00219 /*  and left eigenvector v corresponding to the generalized eigenvalue w */
00220 /*  is defined as follows. Suppose */
00221 
00222 /*                   (A, B) = ( a   *  ) ( b  *  )  1 */
00223 /*                            ( 0  A22 ),( 0 B22 )  n-1 */
00224 /*                              1  n-1     1 n-1 */
00225 
00226 /*  Then the reciprocal condition number DIF(I) is */
00227 
00228 /*          Difl[(a, b), (A22, B22)]  = sigma-min( Zl ) */
00229 
00230 /*  where sigma-min(Zl) denotes the smallest singular value of */
00231 
00232 /*         Zl = [ kron(a, In-1) -kron(1, A22) ] */
00233 /*              [ kron(b, In-1) -kron(1, B22) ]. */
00234 
00235 /*  Here In-1 is the identity matrix of size n-1 and X' is the conjugate */
00236 /*  transpose of X. kron(X, Y) is the Kronecker product between the */
00237 /*  matrices X and Y. */
00238 
00239 /*  We approximate the smallest singular value of Zl with an upper */
00240 /*  bound. This is done by ZLATDF. */
00241 
00242 /*  An approximate error bound for a computed eigenvector VL(i) or */
00243 /*  VR(i) is given by */
00244 
00245 /*                      EPS * norm(A, B) / DIF(i). */
00246 
00247 /*  See ref. [2-3] for more details and further references. */
00248 
00249 /*  Based on contributions by */
00250 /*     Bo Kagstrom and Peter Poromaa, Department of Computing Science, */
00251 /*     Umea University, S-901 87 Umea, Sweden. */
00252 
00253 /*  References */
00254 /*  ========== */
00255 
00256 /*  [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the */
00257 /*      Generalized Real Schur Form of a Regular Matrix Pair (A, B), in */
00258 /*      M.S. Moonen et al (eds), Linear Algebra for Large Scale and */
00259 /*      Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218. */
00260 
00261 /*  [2] B. Kagstrom and P. Poromaa; Computing Eigenspaces with Specified */
00262 /*      Eigenvalues of a Regular Matrix Pair (A, B) and Condition */
00263 /*      Estimation: Theory, Algorithms and Software, Report */
00264 /*      UMINF - 94.04, Department of Computing Science, Umea University, */
00265 /*      S-901 87 Umea, Sweden, 1994. Also as LAPACK Working Note 87. */
00266 /*      To appear in Numerical Algorithms, 1996. */
00267 
00268 /*  [3] B. Kagstrom and P. Poromaa, LAPACK-Style Algorithms and Software */
00269 /*      for Solving the Generalized Sylvester Equation and Estimating the */
00270 /*      Separation between Regular Matrix Pairs, Report UMINF - 93.23, */
00271 /*      Department of Computing Science, Umea University, S-901 87 Umea, */
00272 /*      Sweden, December 1993, Revised April 1994, Also as LAPACK Working */
00273 /*      Note 75. */
00274 /*      To appear in ACM Trans. on Math. Software, Vol 22, No 1, 1996. */
00275 
00276 /*  ===================================================================== */
00277 
00278 /*     .. Parameters .. */
00279 /*     .. */
00280 /*     .. Local Scalars .. */
00281 /*     .. */
00282 /*     .. Local Arrays .. */
00283 /*     .. */
00284 /*     .. External Functions .. */
00285 /*     .. */
00286 /*     .. External Subroutines .. */
00287 /*     .. */
00288 /*     .. Intrinsic Functions .. */
00289 /*     .. */
00290 /*     .. Executable Statements .. */
00291 
00292 /*     Decode and test the input parameters */
00293 
00294     /* Parameter adjustments */
00295     --select;
00296     a_dim1 = *lda;
00297     a_offset = 1 + a_dim1;
00298     a -= a_offset;
00299     b_dim1 = *ldb;
00300     b_offset = 1 + b_dim1;
00301     b -= b_offset;
00302     vl_dim1 = *ldvl;
00303     vl_offset = 1 + vl_dim1;
00304     vl -= vl_offset;
00305     vr_dim1 = *ldvr;
00306     vr_offset = 1 + vr_dim1;
00307     vr -= vr_offset;
00308     --s;
00309     --dif;
00310     --work;
00311     --iwork;
00312 
00313     /* Function Body */
00314     wantbh = lsame_(job, "B");
00315     wants = lsame_(job, "E") || wantbh;
00316     wantdf = lsame_(job, "V") || wantbh;
00317 
00318     somcon = lsame_(howmny, "S");
00319 
00320     *info = 0;
00321     lquery = *lwork == -1;
00322 
00323     if (! wants && ! wantdf) {
00324         *info = -1;
00325     } else if (! lsame_(howmny, "A") && ! somcon) {
00326         *info = -2;
00327     } else if (*n < 0) {
00328         *info = -4;
00329     } else if (*lda < max(1,*n)) {
00330         *info = -6;
00331     } else if (*ldb < max(1,*n)) {
00332         *info = -8;
00333     } else if (wants && *ldvl < *n) {
00334         *info = -10;
00335     } else if (wants && *ldvr < *n) {
00336         *info = -12;
00337     } else {
00338 
00339 /*        Set M to the number of eigenpairs for which condition numbers */
00340 /*        are required, and test MM. */
00341 
00342         if (somcon) {
00343             *m = 0;
00344             i__1 = *n;
00345             for (k = 1; k <= i__1; ++k) {
00346                 if (select[k]) {
00347                     ++(*m);
00348                 }
00349 /* L10: */
00350             }
00351         } else {
00352             *m = *n;
00353         }
00354 
00355         if (*n == 0) {
00356             lwmin = 1;
00357         } else if (lsame_(job, "V") || lsame_(job, 
00358                 "B")) {
00359             lwmin = (*n << 1) * *n;
00360         } else {
00361             lwmin = *n;
00362         }
00363         work[1].r = (doublereal) lwmin, work[1].i = 0.;
00364 
00365         if (*mm < *m) {
00366             *info = -15;
00367         } else if (*lwork < lwmin && ! lquery) {
00368             *info = -18;
00369         }
00370     }
00371 
00372     if (*info != 0) {
00373         i__1 = -(*info);
00374         xerbla_("ZTGSNA", &i__1);
00375         return 0;
00376     } else if (lquery) {
00377         return 0;
00378     }
00379 
00380 /*     Quick return if possible */
00381 
00382     if (*n == 0) {
00383         return 0;
00384     }
00385 
00386 /*     Get machine constants */
00387 
00388     eps = dlamch_("P");
00389     smlnum = dlamch_("S") / eps;
00390     bignum = 1. / smlnum;
00391     dlabad_(&smlnum, &bignum);
00392     ks = 0;
00393     i__1 = *n;
00394     for (k = 1; k <= i__1; ++k) {
00395 
00396 /*        Determine whether condition numbers are required for the k-th */
00397 /*        eigenpair. */
00398 
00399         if (somcon) {
00400             if (! select[k]) {
00401                 goto L20;
00402             }
00403         }
00404 
00405         ++ks;
00406 
00407         if (wants) {
00408 
00409 /*           Compute the reciprocal condition number of the k-th */
00410 /*           eigenvalue. */
00411 
00412             rnrm = dznrm2_(n, &vr[ks * vr_dim1 + 1], &c__1);
00413             lnrm = dznrm2_(n, &vl[ks * vl_dim1 + 1], &c__1);
00414             zgemv_("N", n, n, &c_b19, &a[a_offset], lda, &vr[ks * vr_dim1 + 1]
00415 , &c__1, &c_b20, &work[1], &c__1);
00416             zdotc_(&z__1, n, &work[1], &c__1, &vl[ks * vl_dim1 + 1], &c__1);
00417             yhax.r = z__1.r, yhax.i = z__1.i;
00418             zgemv_("N", n, n, &c_b19, &b[b_offset], ldb, &vr[ks * vr_dim1 + 1]
00419 , &c__1, &c_b20, &work[1], &c__1);
00420             zdotc_(&z__1, n, &work[1], &c__1, &vl[ks * vl_dim1 + 1], &c__1);
00421             yhbx.r = z__1.r, yhbx.i = z__1.i;
00422             d__1 = z_abs(&yhax);
00423             d__2 = z_abs(&yhbx);
00424             cond = dlapy2_(&d__1, &d__2);
00425             if (cond == 0.) {
00426                 s[ks] = -1.;
00427             } else {
00428                 s[ks] = cond / (rnrm * lnrm);
00429             }
00430         }
00431 
00432         if (wantdf) {
00433             if (*n == 1) {
00434                 d__1 = z_abs(&a[a_dim1 + 1]);
00435                 d__2 = z_abs(&b[b_dim1 + 1]);
00436                 dif[ks] = dlapy2_(&d__1, &d__2);
00437             } else {
00438 
00439 /*              Estimate the reciprocal condition number of the k-th */
00440 /*              eigenvectors. */
00441 
00442 /*              Copy the matrix (A, B) to the array WORK and move the */
00443 /*              (k,k)th pair to the (1,1) position. */
00444 
00445                 zlacpy_("Full", n, n, &a[a_offset], lda, &work[1], n);
00446                 zlacpy_("Full", n, n, &b[b_offset], ldb, &work[*n * *n + 1], 
00447                         n);
00448                 ifst = k;
00449                 ilst = 1;
00450 
00451                 ztgexc_(&c_false, &c_false, n, &work[1], n, &work[*n * *n + 1]
00452 , n, dummy, &c__1, dummy1, &c__1, &ifst, &ilst, &ierr)
00453                         ;
00454 
00455                 if (ierr > 0) {
00456 
00457 /*                 Ill-conditioned problem - swap rejected. */
00458 
00459                     dif[ks] = 0.;
00460                 } else {
00461 
00462 /*                 Reordering successful, solve generalized Sylvester */
00463 /*                 equation for R and L, */
00464 /*                            A22 * R - L * A11 = A12 */
00465 /*                            B22 * R - L * B11 = B12, */
00466 /*                 and compute estimate of Difl[(A11,B11), (A22, B22)]. */
00467 
00468                     n1 = 1;
00469                     n2 = *n - n1;
00470                     i__ = *n * *n + 1;
00471                     ztgsyl_("N", &c__3, &n2, &n1, &work[*n * n1 + n1 + 1], n, 
00472                             &work[1], n, &work[n1 + 1], n, &work[*n * n1 + n1 
00473                             + i__], n, &work[i__], n, &work[n1 + i__], n, &
00474                             scale, &dif[ks], dummy, &c__1, &iwork[1], &ierr);
00475                 }
00476             }
00477         }
00478 
00479 L20:
00480         ;
00481     }
00482     work[1].r = (doublereal) lwmin, work[1].i = 0.;
00483     return 0;
00484 
00485 /*     End of ZTGSNA */
00486 
00487 } /* ztgsna_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:43