dtgex2.c
Go to the documentation of this file.
00001 /* dtgex2.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__4 = 4;
00019 static doublereal c_b5 = 0.;
00020 static integer c__1 = 1;
00021 static integer c__2 = 2;
00022 static doublereal c_b42 = 1.;
00023 static doublereal c_b48 = -1.;
00024 static integer c__0 = 0;
00025 
00026 /* Subroutine */ int dtgex2_(logical *wantq, logical *wantz, integer *n, 
00027         doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
00028         q, integer *ldq, doublereal *z__, integer *ldz, integer *j1, integer *
00029         n1, integer *n2, doublereal *work, integer *lwork, integer *info)
00030 {
00031     /* System generated locals */
00032     integer a_dim1, a_offset, b_dim1, b_offset, q_dim1, q_offset, z_dim1, 
00033             z_offset, i__1, i__2;
00034     doublereal d__1;
00035 
00036     /* Builtin functions */
00037     double sqrt(doublereal);
00038 
00039     /* Local variables */
00040     doublereal f, g;
00041     integer i__, m;
00042     doublereal s[16]    /* was [4][4] */, t[16] /* was [4][4] */, be[2], ai[2]
00043             , ar[2], sa, sb, li[16]     /* was [4][4] */, ir[16]        /* 
00044             was [4][4] */, ss, ws, eps;
00045     logical weak;
00046     doublereal ddum;
00047     integer idum;
00048     doublereal taul[4], dsum;
00049     extern /* Subroutine */ int drot_(integer *, doublereal *, integer *, 
00050             doublereal *, integer *, doublereal *, doublereal *);
00051     doublereal taur[4], scpy[16]        /* was [4][4] */, tcpy[16]      /* 
00052             was [4][4] */;
00053     extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *, 
00054             integer *);
00055     doublereal scale, bqra21, brqa21;
00056     extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *, 
00057             integer *, doublereal *, doublereal *, integer *, doublereal *, 
00058             integer *, doublereal *, doublereal *, integer *);
00059     doublereal licop[16]        /* was [4][4] */;
00060     integer linfo;
00061     doublereal ircop[16]        /* was [4][4] */, dnorm;
00062     integer iwork[4];
00063     extern /* Subroutine */ int dlagv2_(doublereal *, integer *, doublereal *, 
00064              integer *, doublereal *, doublereal *, doublereal *, doublereal *
00065 , doublereal *, doublereal *, doublereal *), dgeqr2_(integer *, 
00066             integer *, doublereal *, integer *, doublereal *, doublereal *, 
00067             integer *), dgerq2_(integer *, integer *, doublereal *, integer *, 
00068              doublereal *, doublereal *, integer *), dorg2r_(integer *, 
00069             integer *, integer *, doublereal *, integer *, doublereal *, 
00070             doublereal *, integer *), dorgr2_(integer *, integer *, integer *, 
00071              doublereal *, integer *, doublereal *, doublereal *, integer *), 
00072             dorm2r_(char *, char *, integer *, integer *, integer *, 
00073             doublereal *, integer *, doublereal *, doublereal *, integer *, 
00074             doublereal *, integer *), dormr2_(char *, char *, 
00075             integer *, integer *, integer *, doublereal *, integer *, 
00076             doublereal *, doublereal *, integer *, doublereal *, integer *), dtgsy2_(char *, integer *, integer *, integer *, 
00077             doublereal *, integer *, doublereal *, integer *, doublereal *, 
00078             integer *, doublereal *, integer *, doublereal *, integer *, 
00079             doublereal *, integer *, doublereal *, doublereal *, doublereal *, 
00080              integer *, integer *, integer *);
00081     extern doublereal dlamch_(char *);
00082     doublereal dscale;
00083     extern /* Subroutine */ int dlacpy_(char *, integer *, integer *, 
00084             doublereal *, integer *, doublereal *, integer *), 
00085             dlartg_(doublereal *, doublereal *, doublereal *, doublereal *, 
00086             doublereal *), dlaset_(char *, integer *, integer *, doublereal *, 
00087              doublereal *, doublereal *, integer *), dlassq_(integer *
00088 , doublereal *, integer *, doublereal *, doublereal *);
00089     logical dtrong;
00090     doublereal thresh, smlnum;
00091 
00092 
00093 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00094 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00095 /*     November 2006 */
00096 
00097 /*     .. Scalar Arguments .. */
00098 /*     .. */
00099 /*     .. Array Arguments .. */
00100 /*     .. */
00101 
00102 /*  Purpose */
00103 /*  ======= */
00104 
00105 /*  DTGEX2 swaps adjacent diagonal blocks (A11, B11) and (A22, B22) */
00106 /*  of size 1-by-1 or 2-by-2 in an upper (quasi) triangular matrix pair */
00107 /*  (A, B) by an orthogonal equivalence transformation. */
00108 
00109 /*  (A, B) must be in generalized real Schur canonical form (as returned */
00110 /*  by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2 */
00111 /*  diagonal blocks. B is upper triangular. */
00112 
00113 /*  Optionally, the matrices Q and Z of generalized Schur vectors are */
00114 /*  updated. */
00115 
00116 /*         Q(in) * A(in) * Z(in)' = Q(out) * A(out) * Z(out)' */
00117 /*         Q(in) * B(in) * Z(in)' = Q(out) * B(out) * Z(out)' */
00118 
00119 
00120 /*  Arguments */
00121 /*  ========= */
00122 
00123 /*  WANTQ   (input) LOGICAL */
00124 /*          .TRUE. : update the left transformation matrix Q; */
00125 /*          .FALSE.: do not update Q. */
00126 
00127 /*  WANTZ   (input) LOGICAL */
00128 /*          .TRUE. : update the right transformation matrix Z; */
00129 /*          .FALSE.: do not update Z. */
00130 
00131 /*  N       (input) INTEGER */
00132 /*          The order of the matrices A and B. N >= 0. */
00133 
00134 /*  A      (input/output) DOUBLE PRECISION arrays, dimensions (LDA,N) */
00135 /*          On entry, the matrix A in the pair (A, B). */
00136 /*          On exit, the updated matrix A. */
00137 
00138 /*  LDA     (input)  INTEGER */
00139 /*          The leading dimension of the array A. LDA >= max(1,N). */
00140 
00141 /*  B      (input/output) DOUBLE PRECISION arrays, dimensions (LDB,N) */
00142 /*          On entry, the matrix B in the pair (A, B). */
00143 /*          On exit, the updated matrix B. */
00144 
00145 /*  LDB     (input)  INTEGER */
00146 /*          The leading dimension of the array B. LDB >= max(1,N). */
00147 
00148 /*  Q       (input/output) DOUBLE PRECISION array, dimension (LDZ,N) */
00149 /*          On entry, if WANTQ = .TRUE., the orthogonal matrix Q. */
00150 /*          On exit, the updated matrix Q. */
00151 /*          Not referenced if WANTQ = .FALSE.. */
00152 
00153 /*  LDQ     (input) INTEGER */
00154 /*          The leading dimension of the array Q. LDQ >= 1. */
00155 /*          If WANTQ = .TRUE., LDQ >= N. */
00156 
00157 /*  Z       (input/output) DOUBLE PRECISION array, dimension (LDZ,N) */
00158 /*          On entry, if WANTZ =.TRUE., the orthogonal matrix Z. */
00159 /*          On exit, the updated matrix Z. */
00160 /*          Not referenced if WANTZ = .FALSE.. */
00161 
00162 /*  LDZ     (input) INTEGER */
00163 /*          The leading dimension of the array Z. LDZ >= 1. */
00164 /*          If WANTZ = .TRUE., LDZ >= N. */
00165 
00166 /*  J1      (input) INTEGER */
00167 /*          The index to the first block (A11, B11). 1 <= J1 <= N. */
00168 
00169 /*  N1      (input) INTEGER */
00170 /*          The order of the first block (A11, B11). N1 = 0, 1 or 2. */
00171 
00172 /*  N2      (input) INTEGER */
00173 /*          The order of the second block (A22, B22). N2 = 0, 1 or 2. */
00174 
00175 /*  WORK    (workspace) DOUBLE PRECISION array, dimension (MAX(1,LWORK)). */
00176 
00177 /*  LWORK   (input) INTEGER */
00178 /*          The dimension of the array WORK. */
00179 /*          LWORK >=  MAX( 1, N*(N2+N1), (N2+N1)*(N2+N1)*2 ) */
00180 
00181 /*  INFO    (output) INTEGER */
00182 /*            =0: Successful exit */
00183 /*            >0: If INFO = 1, the transformed matrix (A, B) would be */
00184 /*                too far from generalized Schur form; the blocks are */
00185 /*                not swapped and (A, B) and (Q, Z) are unchanged. */
00186 /*                The problem of swapping is too ill-conditioned. */
00187 /*            <0: If INFO = -16: LWORK is too small. Appropriate value */
00188 /*                for LWORK is returned in WORK(1). */
00189 
00190 /*  Further Details */
00191 /*  =============== */
00192 
00193 /*  Based on contributions by */
00194 /*     Bo Kagstrom and Peter Poromaa, Department of Computing Science, */
00195 /*     Umea University, S-901 87 Umea, Sweden. */
00196 
00197 /*  In the current code both weak and strong stability tests are */
00198 /*  performed. The user can omit the strong stability test by changing */
00199 /*  the internal logical parameter WANDS to .FALSE.. See ref. [2] for */
00200 /*  details. */
00201 
00202 /*  [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the */
00203 /*      Generalized Real Schur Form of a Regular Matrix Pair (A, B), in */
00204 /*      M.S. Moonen et al (eds), Linear Algebra for Large Scale and */
00205 /*      Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218. */
00206 
00207 /*  [2] B. Kagstrom and P. Poromaa; Computing Eigenspaces with Specified */
00208 /*      Eigenvalues of a Regular Matrix Pair (A, B) and Condition */
00209 /*      Estimation: Theory, Algorithms and Software, */
00210 /*      Report UMINF - 94.04, Department of Computing Science, Umea */
00211 /*      University, S-901 87 Umea, Sweden, 1994. Also as LAPACK Working */
00212 /*      Note 87. To appear in Numerical Algorithms, 1996. */
00213 
00214 /*  ===================================================================== */
00215 /*  Replaced various illegal calls to DCOPY by calls to DLASET, or by DO */
00216 /*  loops. Sven Hammarling, 1/5/02. */
00217 
00218 /*     .. Parameters .. */
00219 /*     .. */
00220 /*     .. Local Scalars .. */
00221 /*     .. */
00222 /*     .. Local Arrays .. */
00223 /*     .. */
00224 /*     .. External Functions .. */
00225 /*     .. */
00226 /*     .. External Subroutines .. */
00227 /*     .. */
00228 /*     .. Intrinsic Functions .. */
00229 /*     .. */
00230 /*     .. Executable Statements .. */
00231 
00232     /* Parameter adjustments */
00233     a_dim1 = *lda;
00234     a_offset = 1 + a_dim1;
00235     a -= a_offset;
00236     b_dim1 = *ldb;
00237     b_offset = 1 + b_dim1;
00238     b -= b_offset;
00239     q_dim1 = *ldq;
00240     q_offset = 1 + q_dim1;
00241     q -= q_offset;
00242     z_dim1 = *ldz;
00243     z_offset = 1 + z_dim1;
00244     z__ -= z_offset;
00245     --work;
00246 
00247     /* Function Body */
00248     *info = 0;
00249 
00250 /*     Quick return if possible */
00251 
00252     if (*n <= 1 || *n1 <= 0 || *n2 <= 0) {
00253         return 0;
00254     }
00255     if (*n1 > *n || *j1 + *n1 > *n) {
00256         return 0;
00257     }
00258     m = *n1 + *n2;
00259 /* Computing MAX */
00260     i__1 = 1, i__2 = *n * m, i__1 = max(i__1,i__2), i__2 = m * m << 1;
00261     if (*lwork < max(i__1,i__2)) {
00262         *info = -16;
00263 /* Computing MAX */
00264         i__1 = 1, i__2 = *n * m, i__1 = max(i__1,i__2), i__2 = m * m << 1;
00265         work[1] = (doublereal) max(i__1,i__2);
00266         return 0;
00267     }
00268 
00269     weak = FALSE_;
00270     dtrong = FALSE_;
00271 
00272 /*     Make a local copy of selected block */
00273 
00274     dlaset_("Full", &c__4, &c__4, &c_b5, &c_b5, li, &c__4);
00275     dlaset_("Full", &c__4, &c__4, &c_b5, &c_b5, ir, &c__4);
00276     dlacpy_("Full", &m, &m, &a[*j1 + *j1 * a_dim1], lda, s, &c__4);
00277     dlacpy_("Full", &m, &m, &b[*j1 + *j1 * b_dim1], ldb, t, &c__4);
00278 
00279 /*     Compute threshold for testing acceptance of swapping. */
00280 
00281     eps = dlamch_("P");
00282     smlnum = dlamch_("S") / eps;
00283     dscale = 0.;
00284     dsum = 1.;
00285     dlacpy_("Full", &m, &m, s, &c__4, &work[1], &m);
00286     i__1 = m * m;
00287     dlassq_(&i__1, &work[1], &c__1, &dscale, &dsum);
00288     dlacpy_("Full", &m, &m, t, &c__4, &work[1], &m);
00289     i__1 = m * m;
00290     dlassq_(&i__1, &work[1], &c__1, &dscale, &dsum);
00291     dnorm = dscale * sqrt(dsum);
00292 /* Computing MAX */
00293     d__1 = eps * 10. * dnorm;
00294     thresh = max(d__1,smlnum);
00295 
00296     if (m == 2) {
00297 
00298 /*        CASE 1: Swap 1-by-1 and 1-by-1 blocks. */
00299 
00300 /*        Compute orthogonal QL and RQ that swap 1-by-1 and 1-by-1 blocks */
00301 /*        using Givens rotations and perform the swap tentatively. */
00302 
00303         f = s[5] * t[0] - t[5] * s[0];
00304         g = s[5] * t[4] - t[5] * s[4];
00305         sb = abs(t[5]);
00306         sa = abs(s[5]);
00307         dlartg_(&f, &g, &ir[4], ir, &ddum);
00308         ir[1] = -ir[4];
00309         ir[5] = ir[0];
00310         drot_(&c__2, s, &c__1, &s[4], &c__1, ir, &ir[1]);
00311         drot_(&c__2, t, &c__1, &t[4], &c__1, ir, &ir[1]);
00312         if (sa >= sb) {
00313             dlartg_(s, &s[1], li, &li[1], &ddum);
00314         } else {
00315             dlartg_(t, &t[1], li, &li[1], &ddum);
00316         }
00317         drot_(&c__2, s, &c__4, &s[1], &c__4, li, &li[1]);
00318         drot_(&c__2, t, &c__4, &t[1], &c__4, li, &li[1]);
00319         li[5] = li[0];
00320         li[4] = -li[1];
00321 
00322 /*        Weak stability test: */
00323 /*           |S21| + |T21| <= O(EPS * F-norm((S, T))) */
00324 
00325         ws = abs(s[1]) + abs(t[1]);
00326         weak = ws <= thresh;
00327         if (! weak) {
00328             goto L70;
00329         }
00330 
00331         if (TRUE_) {
00332 
00333 /*           Strong stability test: */
00334 /*             F-norm((A-QL'*S*QR, B-QL'*T*QR)) <= O(EPS*F-norm((A,B))) */
00335 
00336             dlacpy_("Full", &m, &m, &a[*j1 + *j1 * a_dim1], lda, &work[m * m 
00337                     + 1], &m);
00338             dgemm_("N", "N", &m, &m, &m, &c_b42, li, &c__4, s, &c__4, &c_b5, &
00339                     work[1], &m);
00340             dgemm_("N", "T", &m, &m, &m, &c_b48, &work[1], &m, ir, &c__4, &
00341                     c_b42, &work[m * m + 1], &m);
00342             dscale = 0.;
00343             dsum = 1.;
00344             i__1 = m * m;
00345             dlassq_(&i__1, &work[m * m + 1], &c__1, &dscale, &dsum);
00346 
00347             dlacpy_("Full", &m, &m, &b[*j1 + *j1 * b_dim1], ldb, &work[m * m 
00348                     + 1], &m);
00349             dgemm_("N", "N", &m, &m, &m, &c_b42, li, &c__4, t, &c__4, &c_b5, &
00350                     work[1], &m);
00351             dgemm_("N", "T", &m, &m, &m, &c_b48, &work[1], &m, ir, &c__4, &
00352                     c_b42, &work[m * m + 1], &m);
00353             i__1 = m * m;
00354             dlassq_(&i__1, &work[m * m + 1], &c__1, &dscale, &dsum);
00355             ss = dscale * sqrt(dsum);
00356             dtrong = ss <= thresh;
00357             if (! dtrong) {
00358                 goto L70;
00359             }
00360         }
00361 
00362 /*        Update (A(J1:J1+M-1, M+J1:N), B(J1:J1+M-1, M+J1:N)) and */
00363 /*               (A(1:J1-1, J1:J1+M), B(1:J1-1, J1:J1+M)). */
00364 
00365         i__1 = *j1 + 1;
00366         drot_(&i__1, &a[*j1 * a_dim1 + 1], &c__1, &a[(*j1 + 1) * a_dim1 + 1], 
00367                 &c__1, ir, &ir[1]);
00368         i__1 = *j1 + 1;
00369         drot_(&i__1, &b[*j1 * b_dim1 + 1], &c__1, &b[(*j1 + 1) * b_dim1 + 1], 
00370                 &c__1, ir, &ir[1]);
00371         i__1 = *n - *j1 + 1;
00372         drot_(&i__1, &a[*j1 + *j1 * a_dim1], lda, &a[*j1 + 1 + *j1 * a_dim1], 
00373                 lda, li, &li[1]);
00374         i__1 = *n - *j1 + 1;
00375         drot_(&i__1, &b[*j1 + *j1 * b_dim1], ldb, &b[*j1 + 1 + *j1 * b_dim1], 
00376                 ldb, li, &li[1]);
00377 
00378 /*        Set  N1-by-N2 (2,1) - blocks to ZERO. */
00379 
00380         a[*j1 + 1 + *j1 * a_dim1] = 0.;
00381         b[*j1 + 1 + *j1 * b_dim1] = 0.;
00382 
00383 /*        Accumulate transformations into Q and Z if requested. */
00384 
00385         if (*wantz) {
00386             drot_(n, &z__[*j1 * z_dim1 + 1], &c__1, &z__[(*j1 + 1) * z_dim1 + 
00387                     1], &c__1, ir, &ir[1]);
00388         }
00389         if (*wantq) {
00390             drot_(n, &q[*j1 * q_dim1 + 1], &c__1, &q[(*j1 + 1) * q_dim1 + 1], 
00391                     &c__1, li, &li[1]);
00392         }
00393 
00394 /*        Exit with INFO = 0 if swap was successfully performed. */
00395 
00396         return 0;
00397 
00398     } else {
00399 
00400 /*        CASE 2: Swap 1-by-1 and 2-by-2 blocks, or 2-by-2 */
00401 /*                and 2-by-2 blocks. */
00402 
00403 /*        Solve the generalized Sylvester equation */
00404 /*                 S11 * R - L * S22 = SCALE * S12 */
00405 /*                 T11 * R - L * T22 = SCALE * T12 */
00406 /*        for R and L. Solutions in LI and IR. */
00407 
00408         dlacpy_("Full", n1, n2, &t[(*n1 + 1 << 2) - 4], &c__4, li, &c__4);
00409         dlacpy_("Full", n1, n2, &s[(*n1 + 1 << 2) - 4], &c__4, &ir[*n2 + 1 + (
00410                 *n1 + 1 << 2) - 5], &c__4);
00411         dtgsy2_("N", &c__0, n1, n2, s, &c__4, &s[*n1 + 1 + (*n1 + 1 << 2) - 5]
00412 , &c__4, &ir[*n2 + 1 + (*n1 + 1 << 2) - 5], &c__4, t, &c__4, &
00413                 t[*n1 + 1 + (*n1 + 1 << 2) - 5], &c__4, li, &c__4, &scale, &
00414                 dsum, &dscale, iwork, &idum, &linfo);
00415 
00416 /*        Compute orthogonal matrix QL: */
00417 
00418 /*                    QL' * LI = [ TL ] */
00419 /*                               [ 0  ] */
00420 /*        where */
00421 /*                    LI =  [      -L              ] */
00422 /*                          [ SCALE * identity(N2) ] */
00423 
00424         i__1 = *n2;
00425         for (i__ = 1; i__ <= i__1; ++i__) {
00426             dscal_(n1, &c_b48, &li[(i__ << 2) - 4], &c__1);
00427             li[*n1 + i__ + (i__ << 2) - 5] = scale;
00428 /* L10: */
00429         }
00430         dgeqr2_(&m, n2, li, &c__4, taul, &work[1], &linfo);
00431         if (linfo != 0) {
00432             goto L70;
00433         }
00434         dorg2r_(&m, &m, n2, li, &c__4, taul, &work[1], &linfo);
00435         if (linfo != 0) {
00436             goto L70;
00437         }
00438 
00439 /*        Compute orthogonal matrix RQ: */
00440 
00441 /*                    IR * RQ' =   [ 0  TR], */
00442 
00443 /*         where IR = [ SCALE * identity(N1), R ] */
00444 
00445         i__1 = *n1;
00446         for (i__ = 1; i__ <= i__1; ++i__) {
00447             ir[*n2 + i__ + (i__ << 2) - 5] = scale;
00448 /* L20: */
00449         }
00450         dgerq2_(n1, &m, &ir[*n2], &c__4, taur, &work[1], &linfo);
00451         if (linfo != 0) {
00452             goto L70;
00453         }
00454         dorgr2_(&m, &m, n1, ir, &c__4, taur, &work[1], &linfo);
00455         if (linfo != 0) {
00456             goto L70;
00457         }
00458 
00459 /*        Perform the swapping tentatively: */
00460 
00461         dgemm_("T", "N", &m, &m, &m, &c_b42, li, &c__4, s, &c__4, &c_b5, &
00462                 work[1], &m);
00463         dgemm_("N", "T", &m, &m, &m, &c_b42, &work[1], &m, ir, &c__4, &c_b5, 
00464                 s, &c__4);
00465         dgemm_("T", "N", &m, &m, &m, &c_b42, li, &c__4, t, &c__4, &c_b5, &
00466                 work[1], &m);
00467         dgemm_("N", "T", &m, &m, &m, &c_b42, &work[1], &m, ir, &c__4, &c_b5, 
00468                 t, &c__4);
00469         dlacpy_("F", &m, &m, s, &c__4, scpy, &c__4);
00470         dlacpy_("F", &m, &m, t, &c__4, tcpy, &c__4);
00471         dlacpy_("F", &m, &m, ir, &c__4, ircop, &c__4);
00472         dlacpy_("F", &m, &m, li, &c__4, licop, &c__4);
00473 
00474 /*        Triangularize the B-part by an RQ factorization. */
00475 /*        Apply transformation (from left) to A-part, giving S. */
00476 
00477         dgerq2_(&m, &m, t, &c__4, taur, &work[1], &linfo);
00478         if (linfo != 0) {
00479             goto L70;
00480         }
00481         dormr2_("R", "T", &m, &m, &m, t, &c__4, taur, s, &c__4, &work[1], &
00482                 linfo);
00483         if (linfo != 0) {
00484             goto L70;
00485         }
00486         dormr2_("L", "N", &m, &m, &m, t, &c__4, taur, ir, &c__4, &work[1], &
00487                 linfo);
00488         if (linfo != 0) {
00489             goto L70;
00490         }
00491 
00492 /*        Compute F-norm(S21) in BRQA21. (T21 is 0.) */
00493 
00494         dscale = 0.;
00495         dsum = 1.;
00496         i__1 = *n2;
00497         for (i__ = 1; i__ <= i__1; ++i__) {
00498             dlassq_(n1, &s[*n2 + 1 + (i__ << 2) - 5], &c__1, &dscale, &dsum);
00499 /* L30: */
00500         }
00501         brqa21 = dscale * sqrt(dsum);
00502 
00503 /*        Triangularize the B-part by a QR factorization. */
00504 /*        Apply transformation (from right) to A-part, giving S. */
00505 
00506         dgeqr2_(&m, &m, tcpy, &c__4, taul, &work[1], &linfo);
00507         if (linfo != 0) {
00508             goto L70;
00509         }
00510         dorm2r_("L", "T", &m, &m, &m, tcpy, &c__4, taul, scpy, &c__4, &work[1]
00511 , info);
00512         dorm2r_("R", "N", &m, &m, &m, tcpy, &c__4, taul, licop, &c__4, &work[
00513                 1], info);
00514         if (linfo != 0) {
00515             goto L70;
00516         }
00517 
00518 /*        Compute F-norm(S21) in BQRA21. (T21 is 0.) */
00519 
00520         dscale = 0.;
00521         dsum = 1.;
00522         i__1 = *n2;
00523         for (i__ = 1; i__ <= i__1; ++i__) {
00524             dlassq_(n1, &scpy[*n2 + 1 + (i__ << 2) - 5], &c__1, &dscale, &
00525                     dsum);
00526 /* L40: */
00527         }
00528         bqra21 = dscale * sqrt(dsum);
00529 
00530 /*        Decide which method to use. */
00531 /*          Weak stability test: */
00532 /*             F-norm(S21) <= O(EPS * F-norm((S, T))) */
00533 
00534         if (bqra21 <= brqa21 && bqra21 <= thresh) {
00535             dlacpy_("F", &m, &m, scpy, &c__4, s, &c__4);
00536             dlacpy_("F", &m, &m, tcpy, &c__4, t, &c__4);
00537             dlacpy_("F", &m, &m, ircop, &c__4, ir, &c__4);
00538             dlacpy_("F", &m, &m, licop, &c__4, li, &c__4);
00539         } else if (brqa21 >= thresh) {
00540             goto L70;
00541         }
00542 
00543 /*        Set lower triangle of B-part to zero */
00544 
00545         i__1 = m - 1;
00546         i__2 = m - 1;
00547         dlaset_("Lower", &i__1, &i__2, &c_b5, &c_b5, &t[1], &c__4);
00548 
00549         if (TRUE_) {
00550 
00551 /*           Strong stability test: */
00552 /*              F-norm((A-QL*S*QR', B-QL*T*QR')) <= O(EPS*F-norm((A,B))) */
00553 
00554             dlacpy_("Full", &m, &m, &a[*j1 + *j1 * a_dim1], lda, &work[m * m 
00555                     + 1], &m);
00556             dgemm_("N", "N", &m, &m, &m, &c_b42, li, &c__4, s, &c__4, &c_b5, &
00557                     work[1], &m);
00558             dgemm_("N", "N", &m, &m, &m, &c_b48, &work[1], &m, ir, &c__4, &
00559                     c_b42, &work[m * m + 1], &m);
00560             dscale = 0.;
00561             dsum = 1.;
00562             i__1 = m * m;
00563             dlassq_(&i__1, &work[m * m + 1], &c__1, &dscale, &dsum);
00564 
00565             dlacpy_("Full", &m, &m, &b[*j1 + *j1 * b_dim1], ldb, &work[m * m 
00566                     + 1], &m);
00567             dgemm_("N", "N", &m, &m, &m, &c_b42, li, &c__4, t, &c__4, &c_b5, &
00568                     work[1], &m);
00569             dgemm_("N", "N", &m, &m, &m, &c_b48, &work[1], &m, ir, &c__4, &
00570                     c_b42, &work[m * m + 1], &m);
00571             i__1 = m * m;
00572             dlassq_(&i__1, &work[m * m + 1], &c__1, &dscale, &dsum);
00573             ss = dscale * sqrt(dsum);
00574             dtrong = ss <= thresh;
00575             if (! dtrong) {
00576                 goto L70;
00577             }
00578 
00579         }
00580 
00581 /*        If the swap is accepted ("weakly" and "strongly"), apply the */
00582 /*        transformations and set N1-by-N2 (2,1)-block to zero. */
00583 
00584         dlaset_("Full", n1, n2, &c_b5, &c_b5, &s[*n2], &c__4);
00585 
00586 /*        copy back M-by-M diagonal block starting at index J1 of (A, B) */
00587 
00588         dlacpy_("F", &m, &m, s, &c__4, &a[*j1 + *j1 * a_dim1], lda)
00589                 ;
00590         dlacpy_("F", &m, &m, t, &c__4, &b[*j1 + *j1 * b_dim1], ldb)
00591                 ;
00592         dlaset_("Full", &c__4, &c__4, &c_b5, &c_b5, t, &c__4);
00593 
00594 /*        Standardize existing 2-by-2 blocks. */
00595 
00596         i__1 = m * m;
00597         for (i__ = 1; i__ <= i__1; ++i__) {
00598             work[i__] = 0.;
00599 /* L50: */
00600         }
00601         work[1] = 1.;
00602         t[0] = 1.;
00603         idum = *lwork - m * m - 2;
00604         if (*n2 > 1) {
00605             dlagv2_(&a[*j1 + *j1 * a_dim1], lda, &b[*j1 + *j1 * b_dim1], ldb, 
00606                     ar, ai, be, &work[1], &work[2], t, &t[1]);
00607             work[m + 1] = -work[2];
00608             work[m + 2] = work[1];
00609             t[*n2 + (*n2 << 2) - 5] = t[0];
00610             t[4] = -t[1];
00611         }
00612         work[m * m] = 1.;
00613         t[m + (m << 2) - 5] = 1.;
00614 
00615         if (*n1 > 1) {
00616             dlagv2_(&a[*j1 + *n2 + (*j1 + *n2) * a_dim1], lda, &b[*j1 + *n2 + 
00617                     (*j1 + *n2) * b_dim1], ldb, taur, taul, &work[m * m + 1], 
00618                     &work[*n2 * m + *n2 + 1], &work[*n2 * m + *n2 + 2], &t[*
00619                     n2 + 1 + (*n2 + 1 << 2) - 5], &t[m + (m - 1 << 2) - 5]);
00620             work[m * m] = work[*n2 * m + *n2 + 1];
00621             work[m * m - 1] = -work[*n2 * m + *n2 + 2];
00622             t[m + (m << 2) - 5] = t[*n2 + 1 + (*n2 + 1 << 2) - 5];
00623             t[m - 1 + (m << 2) - 5] = -t[m + (m - 1 << 2) - 5];
00624         }
00625         dgemm_("T", "N", n2, n1, n2, &c_b42, &work[1], &m, &a[*j1 + (*j1 + *
00626                 n2) * a_dim1], lda, &c_b5, &work[m * m + 1], n2);
00627         dlacpy_("Full", n2, n1, &work[m * m + 1], n2, &a[*j1 + (*j1 + *n2) * 
00628                 a_dim1], lda);
00629         dgemm_("T", "N", n2, n1, n2, &c_b42, &work[1], &m, &b[*j1 + (*j1 + *
00630                 n2) * b_dim1], ldb, &c_b5, &work[m * m + 1], n2);
00631         dlacpy_("Full", n2, n1, &work[m * m + 1], n2, &b[*j1 + (*j1 + *n2) * 
00632                 b_dim1], ldb);
00633         dgemm_("N", "N", &m, &m, &m, &c_b42, li, &c__4, &work[1], &m, &c_b5, &
00634                 work[m * m + 1], &m);
00635         dlacpy_("Full", &m, &m, &work[m * m + 1], &m, li, &c__4);
00636         dgemm_("N", "N", n2, n1, n1, &c_b42, &a[*j1 + (*j1 + *n2) * a_dim1], 
00637                 lda, &t[*n2 + 1 + (*n2 + 1 << 2) - 5], &c__4, &c_b5, &work[1], 
00638                  n2);
00639         dlacpy_("Full", n2, n1, &work[1], n2, &a[*j1 + (*j1 + *n2) * a_dim1], 
00640                 lda);
00641         dgemm_("N", "N", n2, n1, n1, &c_b42, &b[*j1 + (*j1 + *n2) * b_dim1], 
00642                 ldb, &t[*n2 + 1 + (*n2 + 1 << 2) - 5], &c__4, &c_b5, &work[1], 
00643                  n2);
00644         dlacpy_("Full", n2, n1, &work[1], n2, &b[*j1 + (*j1 + *n2) * b_dim1], 
00645                 ldb);
00646         dgemm_("T", "N", &m, &m, &m, &c_b42, ir, &c__4, t, &c__4, &c_b5, &
00647                 work[1], &m);
00648         dlacpy_("Full", &m, &m, &work[1], &m, ir, &c__4);
00649 
00650 /*        Accumulate transformations into Q and Z if requested. */
00651 
00652         if (*wantq) {
00653             dgemm_("N", "N", n, &m, &m, &c_b42, &q[*j1 * q_dim1 + 1], ldq, li, 
00654                      &c__4, &c_b5, &work[1], n);
00655             dlacpy_("Full", n, &m, &work[1], n, &q[*j1 * q_dim1 + 1], ldq);
00656 
00657         }
00658 
00659         if (*wantz) {
00660             dgemm_("N", "N", n, &m, &m, &c_b42, &z__[*j1 * z_dim1 + 1], ldz, 
00661                     ir, &c__4, &c_b5, &work[1], n);
00662             dlacpy_("Full", n, &m, &work[1], n, &z__[*j1 * z_dim1 + 1], ldz);
00663 
00664         }
00665 
00666 /*        Update (A(J1:J1+M-1, M+J1:N), B(J1:J1+M-1, M+J1:N)) and */
00667 /*                (A(1:J1-1, J1:J1+M), B(1:J1-1, J1:J1+M)). */
00668 
00669         i__ = *j1 + m;
00670         if (i__ <= *n) {
00671             i__1 = *n - i__ + 1;
00672             dgemm_("T", "N", &m, &i__1, &m, &c_b42, li, &c__4, &a[*j1 + i__ * 
00673                     a_dim1], lda, &c_b5, &work[1], &m);
00674             i__1 = *n - i__ + 1;
00675             dlacpy_("Full", &m, &i__1, &work[1], &m, &a[*j1 + i__ * a_dim1], 
00676                     lda);
00677             i__1 = *n - i__ + 1;
00678             dgemm_("T", "N", &m, &i__1, &m, &c_b42, li, &c__4, &b[*j1 + i__ * 
00679                     b_dim1], lda, &c_b5, &work[1], &m);
00680             i__1 = *n - i__ + 1;
00681             dlacpy_("Full", &m, &i__1, &work[1], &m, &b[*j1 + i__ * b_dim1], 
00682                     ldb);
00683         }
00684         i__ = *j1 - 1;
00685         if (i__ > 0) {
00686             dgemm_("N", "N", &i__, &m, &m, &c_b42, &a[*j1 * a_dim1 + 1], lda, 
00687                     ir, &c__4, &c_b5, &work[1], &i__);
00688             dlacpy_("Full", &i__, &m, &work[1], &i__, &a[*j1 * a_dim1 + 1], 
00689                     lda);
00690             dgemm_("N", "N", &i__, &m, &m, &c_b42, &b[*j1 * b_dim1 + 1], ldb, 
00691                     ir, &c__4, &c_b5, &work[1], &i__);
00692             dlacpy_("Full", &i__, &m, &work[1], &i__, &b[*j1 * b_dim1 + 1], 
00693                     ldb);
00694         }
00695 
00696 /*        Exit with INFO = 0 if swap was successfully performed. */
00697 
00698         return 0;
00699 
00700     }
00701 
00702 /*     Exit with INFO = 1 if swap was rejected. */
00703 
00704 L70:
00705 
00706     *info = 1;
00707     return 0;
00708 
00709 /*     End of DTGEX2 */
00710 
00711 } /* dtgex2_ */


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