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


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