/* Subroutine */ int strsen_(char *job, char *compq, logical *select, integer *n, real *t, integer *ldt, real *q, integer *ldq, real *wr, real *wi, integer *m, real *s, real *sep, real *work, integer *lwork, integer * iwork, integer *liwork, integer *info, ftnlen job_len, ftnlen compq_len) { /* System generated locals */ integer q_dim1, q_offset, t_dim1, t_offset, i__1, i__2; real r__1, r__2; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ static integer k, n1, n2, kk, nn, ks; static real est; static integer kase; static logical pair; static integer ierr; static logical swap; static real scale; extern logical lsame_(char *, char *, ftnlen, ftnlen); static integer lwmin; static logical wantq, wants; static real rnorm; extern doublereal slange_(char *, integer *, integer *, real *, integer *, real *, ftnlen); extern /* Subroutine */ int xerbla_(char *, integer *, ftnlen), slacon_( integer *, real *, real *, integer *, real *, integer *); static logical wantbh; extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *, ftnlen); static integer liwmin; extern /* Subroutine */ int strexc_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, integer *, ftnlen); static logical wantsp, lquery; extern /* Subroutine */ int strsyl_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *, ftnlen, ftnlen); /* -- LAPACK routine (version 3.0) -- */ /* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., */ /* Courant Institute, Argonne National Lab, and Rice University */ /* June 30, 1999 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* STRSEN reorders the real Schur factorization of a real matrix */ /* A = Q*T*Q**T, so that a selected cluster of eigenvalues appears in */ /* the leading diagonal blocks of the upper quasi-triangular matrix T, */ /* and the leading columns of Q form an orthonormal basis of the */ /* corresponding right invariant subspace. */ /* Optionally the routine computes the reciprocal condition numbers of */ /* the cluster of eigenvalues and/or the invariant subspace. */ /* T must be in Schur canonical form (as returned by SHSEQR), that is, */ /* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each */ /* 2-by-2 diagonal block has its diagonal elemnts equal and its */ /* off-diagonal elements of opposite sign. */ /* Arguments */ /* ========= */ /* JOB (input) CHARACTER*1 */ /* Specifies whether condition numbers are required for the */ /* cluster of eigenvalues (S) or the invariant subspace (SEP): */ /* = 'N': none; */ /* = 'E': for eigenvalues only (S); */ /* = 'V': for invariant subspace only (SEP); */ /* = 'B': for both eigenvalues and invariant subspace (S and */ /* SEP). */ /* COMPQ (input) CHARACTER*1 */ /* = 'V': update the matrix Q of Schur vectors; */ /* = 'N': do not update Q. */ /* SELECT (input) LOGICAL array, dimension (N) */ /* SELECT specifies the eigenvalues in the selected cluster. To */ /* select a real eigenvalue w(j), SELECT(j) must be set to */ /* .TRUE.. To select a complex conjugate pair of eigenvalues */ /* w(j) and w(j+1), corresponding to a 2-by-2 diagonal block, */ /* either SELECT(j) or SELECT(j+1) or both must be set to */ /* .TRUE.; a complex conjugate pair of eigenvalues must be */ /* either both included in the cluster or both excluded. */ /* N (input) INTEGER */ /* The order of the matrix T. N >= 0. */ /* T (input/output) REAL array, dimension (LDT,N) */ /* On entry, the upper quasi-triangular matrix T, in Schur */ /* canonical form. */ /* On exit, T is overwritten by the reordered matrix T, again in */ /* Schur canonical form, with the selected eigenvalues in the */ /* leading diagonal blocks. */ /* LDT (input) INTEGER */ /* The leading dimension of the array T. LDT >= max(1,N). */ /* Q (input/output) REAL array, dimension (LDQ,N) */ /* On entry, if COMPQ = 'V', the matrix Q of Schur vectors. */ /* On exit, if COMPQ = 'V', Q has been postmultiplied by the */ /* orthogonal transformation matrix which reorders T; the */ /* leading M columns of Q form an orthonormal basis for the */ /* specified invariant subspace. */ /* If COMPQ = 'N', Q is not referenced. */ /* LDQ (input) INTEGER */ /* The leading dimension of the array Q. */ /* LDQ >= 1; and if COMPQ = 'V', LDQ >= N. */ /* WR (output) REAL array, dimension (N) */ /* WI (output) REAL array, dimension (N) */ /* The real and imaginary parts, respectively, of the reordered */ /* eigenvalues of T. The eigenvalues are stored in the same */ /* order as on the diagonal of T, with WR(i) = T(i,i) and, if */ /* T(i:i+1,i:i+1) is a 2-by-2 diagonal block, WI(i) > 0 and */ /* WI(i+1) = -WI(i). Note that if a complex eigenvalue is */ /* sufficiently ill-conditioned, then its value may differ */ /* significantly from its value before reordering. */ /* M (output) INTEGER */ /* The dimension of the specified invariant subspace. */ /* 0 < = M <= N. */ /* S (output) REAL */ /* If JOB = 'E' or 'B', S is a lower bound on the reciprocal */ /* condition number for the selected cluster of eigenvalues. */ /* S cannot underestimate the true reciprocal condition number */ /* by more than a factor of sqrt(N). If M = 0 or N, S = 1. */ /* If JOB = 'N' or 'V', S is not referenced. */ /* SEP (output) REAL */ /* If JOB = 'V' or 'B', SEP is the estimated reciprocal */ /* condition number of the specified invariant subspace. If */ /* M = 0 or N, SEP = norm(T). */ /* If JOB = 'N' or 'E', SEP is not referenced. */ /* WORK (workspace/output) REAL array, dimension (LWORK) */ /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */ /* LWORK (input) INTEGER */ /* The dimension of the array WORK. */ /* If JOB = 'N', LWORK >= max(1,N); */ /* if JOB = 'E', LWORK >= M*(N-M); */ /* if JOB = 'V' or 'B', LWORK >= 2*M*(N-M). */ /* If LWORK = -1, then a workspace query is assumed; the routine */ /* only calculates the optimal size of the WORK array, returns */ /* this value as the first entry of the WORK array, and no error */ /* message related to LWORK is issued by XERBLA. */ /* IWORK (workspace) INTEGER array, dimension (LIWORK) */ /* IF JOB = 'N' or 'E', IWORK is not referenced. */ /* LIWORK (input) INTEGER */ /* The dimension of the array IWORK. */ /* If JOB = 'N' or 'E', LIWORK >= 1; */ /* if JOB = 'V' or 'B', LIWORK >= M*(N-M). */ /* If LIWORK = -1, then a workspace query is assumed; the */ /* routine only calculates the optimal size of the IWORK array, */ /* returns this value as the first entry of the IWORK array, and */ /* no error message related to LIWORK is issued by XERBLA. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* = 1: reordering of T failed because some eigenvalues are too */ /* close to separate (the problem is very ill-conditioned); */ /* T may have been partially reordered, and WR and WI */ /* contain the eigenvalues in the same order as in T; S and */ /* SEP (if requested) are set to zero. */ /* Further Details */ /* =============== */ /* STRSEN first collects the selected eigenvalues by computing an */ /* orthogonal transformation Z to move them to the top left corner of T. */ /* In other words, the selected eigenvalues are the eigenvalues of T11 */ /* in: */ /* Z'*T*Z = ( T11 T12 ) n1 */ /* ( 0 T22 ) n2 */ /* n1 n2 */ /* where N = n1+n2 and Z' means the transpose of Z. The first n1 columns */ /* of Z span the specified invariant subspace of T. */ /* If T has been obtained from the real Schur factorization of a matrix */ /* A = Q*T*Q', then the reordered real Schur factorization of A is given */ /* by A = (Q*Z)*(Z'*T*Z)*(Q*Z)', and the first n1 columns of Q*Z span */ /* the corresponding invariant subspace of A. */ /* The reciprocal condition number of the average of the eigenvalues of */ /* T11 may be returned in S. S lies between 0 (very badly conditioned) */ /* and 1 (very well conditioned). It is computed as follows. First we */ /* compute R so that */ /* P = ( I R ) n1 */ /* ( 0 0 ) n2 */ /* n1 n2 */ /* is the projector on the invariant subspace associated with T11. */ /* R is the solution of the Sylvester equation: */ /* T11*R - R*T22 = T12. */ /* Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote */ /* the two-norm of M. Then S is computed as the lower bound */ /* (1 + F-norm(R)**2)**(-1/2) */ /* on the reciprocal of 2-norm(P), the true reciprocal condition number. */ /* S cannot underestimate 1 / 2-norm(P) by more than a factor of */ /* sqrt(N). */ /* An approximate error bound for the computed average of the */ /* eigenvalues of T11 is */ /* EPS * norm(T) / S */ /* where EPS is the machine precision. */ /* The reciprocal condition number of the right invariant subspace */ /* spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP. */ /* SEP is defined as the separation of T11 and T22: */ /* sep( T11, T22 ) = sigma-min( C ) */ /* where sigma-min(C) is the smallest singular value of the */ /* n1*n2-by-n1*n2 matrix */ /* C = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) ) */ /* I(m) is an m by m identity matrix, and kprod denotes the Kronecker */ /* product. We estimate sigma-min(C) by the reciprocal of an estimate of */ /* the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C) */ /* cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2). */ /* When SEP is small, small changes in T can cause large changes in */ /* the invariant subspace. An approximate bound on the maximum angular */ /* error in the computed right invariant subspace is */ /* EPS * norm(T) / SEP */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Decode and test the input parameters */ /* Parameter adjustments */ --select; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; q_dim1 = *ldq; q_offset = 1 + q_dim1; q -= q_offset; --wr; --wi; --work; --iwork; /* Function Body */ wantbh = lsame_(job, "B", (ftnlen)1, (ftnlen)1); wants = lsame_(job, "E", (ftnlen)1, (ftnlen)1) || wantbh; wantsp = lsame_(job, "V", (ftnlen)1, (ftnlen)1) || wantbh; wantq = lsame_(compq, "V", (ftnlen)1, (ftnlen)1); *info = 0; lquery = *lwork == -1; if (! lsame_(job, "N", (ftnlen)1, (ftnlen)1) && ! wants && ! wantsp) { *info = -1; } else if (! lsame_(compq, "N", (ftnlen)1, (ftnlen)1) && ! wantq) { *info = -2; } else if (*n < 0) { *info = -4; } else if (*ldt < max(1,*n)) { *info = -6; } else if (*ldq < 1 || wantq && *ldq < *n) { *info = -8; } else { /* Set M to the dimension of the specified invariant subspace, */ /* and test LWORK and LIWORK. */ *m = 0; pair = FALSE_; i__1 = *n; for (k = 1; k <= i__1; ++k) { if (pair) { pair = FALSE_; } else { if (k < *n) { if (t[k + 1 + k * t_dim1] == 0.f) { if (select[k]) { ++(*m); } } else { pair = TRUE_; if (select[k] || select[k + 1]) { *m += 2; } } } else { if (select[*n]) { ++(*m); } } } /* L10: */ } n1 = *m; n2 = *n - *m; nn = n1 * n2; if (wantsp) { /* Computing MAX */ i__1 = 1, i__2 = nn << 1; lwmin = max(i__1,i__2); liwmin = max(1,nn); } else if (lsame_(job, "N", (ftnlen)1, (ftnlen)1)) { lwmin = max(1,*n); liwmin = 1; } else if (lsame_(job, "E", (ftnlen)1, (ftnlen)1)) { lwmin = max(1,nn); liwmin = 1; } if (*lwork < lwmin && ! lquery) { *info = -15; } else if (*liwork < liwmin && ! lquery) { *info = -17; } } if (*info == 0) { work[1] = (real) lwmin; iwork[1] = liwmin; } if (*info != 0) { i__1 = -(*info); xerbla_("STRSEN", &i__1, (ftnlen)6); return 0; } else if (lquery) { return 0; } /* Quick return if possible. */ if (*m == *n || *m == 0) { if (wants) { *s = 1.f; } if (wantsp) { *sep = slange_("1", n, n, &t[t_offset], ldt, &work[1], (ftnlen)1); } goto L40; } /* Collect the selected blocks at the top-left corner of T. */ ks = 0; pair = FALSE_; i__1 = *n; for (k = 1; k <= i__1; ++k) { if (pair) { pair = FALSE_; } else { swap = select[k]; if (k < *n) { if (t[k + 1 + k * t_dim1] != 0.f) { pair = TRUE_; swap = swap || select[k + 1]; } } if (swap) { ++ks; /* Swap the K-th block to position KS. */ ierr = 0; kk = k; if (k != ks) { strexc_(compq, n, &t[t_offset], ldt, &q[q_offset], ldq, & kk, &ks, &work[1], &ierr, (ftnlen)1); } if (ierr == 1 || ierr == 2) { /* Blocks too close to swap: exit. */ *info = 1; if (wants) { *s = 0.f; } if (wantsp) { *sep = 0.f; } goto L40; } if (pair) { ++ks; } } } /* L20: */ } if (wants) { /* Solve Sylvester equation for R: */ /* T11*R - R*T22 = scale*T12 */ slacpy_("F", &n1, &n2, &t[(n1 + 1) * t_dim1 + 1], ldt, &work[1], &n1, (ftnlen)1); strsyl_("N", "N", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, &ierr, (ftnlen)1, (ftnlen)1); /* Estimate the reciprocal of the condition number of the cluster */ /* of eigenvalues. */ rnorm = slange_("F", &n1, &n2, &work[1], &n1, &work[1], (ftnlen)1); if (rnorm == 0.f) { *s = 1.f; } else { *s = scale / (sqrt(scale * scale / rnorm + rnorm) * sqrt(rnorm)); } } if (wantsp) { /* Estimate sep(T11,T22). */ est = 0.f; kase = 0; L30: slacon_(&nn, &work[nn + 1], &work[1], &iwork[1], &est, &kase); if (kase != 0) { if (kase == 1) { /* Solve T11*R - R*T22 = scale*X. */ strsyl_("N", "N", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, & ierr, (ftnlen)1, (ftnlen)1); } else { /* Solve T11'*R - R*T22' = scale*X. */ strsyl_("T", "T", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, & ierr, (ftnlen)1, (ftnlen)1); } goto L30; } *sep = scale / est; } L40: /* Store the output eigenvalues in WR and WI. */ i__1 = *n; for (k = 1; k <= i__1; ++k) { wr[k] = t[k + k * t_dim1]; wi[k] = 0.f; /* L50: */ } i__1 = *n - 1; for (k = 1; k <= i__1; ++k) { if (t[k + 1 + k * t_dim1] != 0.f) { wi[k] = sqrt((r__1 = t[k + (k + 1) * t_dim1], dabs(r__1))) * sqrt( (r__2 = t[k + 1 + k * t_dim1], dabs(r__2))); wi[k + 1] = -wi[k]; } /* L60: */ } work[1] = (real) lwmin; iwork[1] = liwmin; return 0; /* End of STRSEN */ } /* strsen_ */
/* Subroutine */ int serrec_(char *path, integer *nunit) { /* Format strings */ static char fmt_9999[] = "(1x,a3,\002 routines passed the tests of the e" "rror exits (\002,i3,\002 tests done)\002)"; static char fmt_9998[] = "(\002 *** \002,a3,\002 routines failed the tes" "ts of the error ex\002,\002its ***\002)"; /* Builtin functions */ /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ real a[16] /* was [4][4] */, b[16] /* was [4][4] */, c__[16] /* was [4][4] */; integer i__, j, m; real s[4], wi[4]; integer nt; real wr[4]; logical sel[4]; real sep[4]; integer info, ifst, ilst; real work[4], scale; integer iwork[4]; extern /* Subroutine */ int chkxer_(char *, integer *, integer *, logical *, logical *), strexc_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, integer *), strsna_(char *, char *, logical *, integer *, real *, integer *, real *, integer *, real *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *, integer *), strsen_(char *, char *, logical *, integer *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, integer *, integer *, integer *, integer * ), strsyl_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *); /* Fortran I/O blocks */ static cilist io___19 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___20 = { 0, 0, 0, fmt_9998, 0 }; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SERREC tests the error exits for the routines for eigen- condition */ /* estimation for REAL matrices: */ /* STRSYL, STREXC, STRSNA and STRSEN. */ /* Arguments */ /* ========= */ /* PATH (input) CHARACTER*3 */ /* The LAPACK path name for the routines to be tested. */ /* NUNIT (input) INTEGER */ /* The unit number for output. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Scalars in Common .. */ /* .. */ /* .. Common blocks .. */ /* .. */ /* .. Executable Statements .. */ infoc_1.nout = *nunit; infoc_1.ok = TRUE_; nt = 0; /* Initialize A, B and SEL */ for (j = 1; j <= 4; ++j) { for (i__ = 1; i__ <= 4; ++i__) { a[i__ + (j << 2) - 5] = 0.f; b[i__ + (j << 2) - 5] = 0.f; /* L10: */ } /* L20: */ } for (i__ = 1; i__ <= 4; ++i__) { a[i__ + (i__ << 2) - 5] = 1.f; sel[i__ - 1] = TRUE_; /* L30: */ } /* Test STRSYL */ s_copy(srnamc_1.srnamt, "STRSYL", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; strsyl_("X", "N", &c__1, &c__0, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; strsyl_("N", "X", &c__1, &c__0, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; strsyl_("N", "N", &c__0, &c__0, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; strsyl_("N", "N", &c__1, &c_n1, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; strsyl_("N", "N", &c__1, &c__0, &c_n1, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; strsyl_("N", "N", &c__1, &c__2, &c__0, a, &c__1, b, &c__1, c__, &c__2, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 9; strsyl_("N", "N", &c__1, &c__0, &c__2, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 11; strsyl_("N", "N", &c__1, &c__2, &c__0, a, &c__2, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 8; /* Test STREXC */ s_copy(srnamc_1.srnamt, "STREXC", (ftnlen)32, (ftnlen)6); ifst = 1; ilst = 1; infoc_1.infot = 1; strexc_("X", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; strexc_("N", &c__0, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; ilst = 2; strexc_("N", &c__2, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 6; strexc_("V", &c__2, a, &c__2, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; ifst = 0; ilst = 1; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; ifst = 2; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; ifst = 1; ilst = 0; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; ilst = 2; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 8; /* Test STRSNA */ s_copy(srnamc_1.srnamt, "STRSNA", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; strsna_("X", "A", sel, &c__0, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__1, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; strsna_("B", "X", sel, &c__0, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__1, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; strsna_("B", "A", sel, &c_n1, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__1, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 6; strsna_("V", "A", sel, &c__2, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__2, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; strsna_("B", "A", sel, &c__2, a, &c__2, b, &c__1, c__, &c__2, s, sep, & c__2, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; strsna_("B", "A", sel, &c__2, a, &c__2, b, &c__2, c__, &c__1, s, sep, & c__2, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 13; strsna_("B", "A", sel, &c__1, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__0, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 13; strsna_("B", "S", sel, &c__2, a, &c__2, b, &c__2, c__, &c__2, s, sep, & c__1, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 16; strsna_("B", "A", sel, &c__2, a, &c__2, b, &c__2, c__, &c__2, s, sep, & c__2, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 9; /* Test STRSEN */ sel[0] = FALSE_; s_copy(srnamc_1.srnamt, "STRSEN", (ftnlen)32, (ftnlen)6); infoc_1.infot = 1; strsen_("X", "N", sel, &c__0, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; strsen_("N", "X", sel, &c__0, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; strsen_("N", "N", sel, &c_n1, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 6; strsen_("N", "N", sel, &c__2, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__2, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; strsen_("N", "V", sel, &c__2, a, &c__2, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 15; strsen_("N", "V", sel, &c__2, a, &c__2, b, &c__2, wr, wi, &m, s, sep, work, &c__0, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 15; strsen_("E", "V", sel, &c__3, a, &c__3, b, &c__3, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 15; strsen_("V", "V", sel, &c__3, a, &c__3, b, &c__3, wr, wi, &m, s, sep, work, &c__3, iwork, &c__2, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 17; strsen_("E", "V", sel, &c__2, a, &c__2, b, &c__2, wr, wi, &m, s, sep, work, &c__1, iwork, &c__0, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 17; strsen_("V", "V", sel, &c__3, a, &c__3, b, &c__3, wr, wi, &m, s, sep, work, &c__4, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 10; /* Print a summary line. */ if (infoc_1.ok) { io___19.ciunit = infoc_1.nout; s_wsfe(&io___19); do_fio(&c__1, path, (ftnlen)3); do_fio(&c__1, (char *)&nt, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___20.ciunit = infoc_1.nout; s_wsfe(&io___20); do_fio(&c__1, path, (ftnlen)3); e_wsfe(); } return 0; /* End of SERREC */ } /* serrec_ */
/* Subroutine */ int slaqr2_(logical *wantt, logical *wantz, integer *n, integer *ktop, integer *kbot, integer *nw, real *h__, integer *ldh, integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *ns, integer *nd, real *sr, real *si, real *v, integer *ldv, integer *nh, real *t, integer *ldt, integer *nv, real *wv, integer *ldwv, real * work, integer *lwork) { /* System generated locals */ integer h_dim1, h_offset, t_dim1, t_offset, v_dim1, v_offset, wv_dim1, wv_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4; real r__1, r__2, r__3, r__4, r__5, r__6; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ integer i__, j, k; real s, aa, bb, cc, dd, cs, sn; integer jw; real evi, evk, foo; integer kln; real tau, ulp; integer lwk1, lwk2; real beta; integer kend, kcol, info, ifst, ilst, ltop, krow; logical bulge; extern /* Subroutine */ int slarf_(char *, integer *, integer *, real *, integer *, real *, real *, integer *, real *), sgemm_( char *, char *, integer *, integer *, integer *, real *, real *, integer *, real *, integer *, real *, real *, integer *); integer infqr; extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, integer *); integer kwtop; extern /* Subroutine */ int slanv2_(real *, real *, real *, real *, real * , real *, real *, real *, real *, real *), slabad_(real *, real *) ; extern real slamch_(char *); extern /* Subroutine */ int sgehrd_(integer *, integer *, integer *, real *, integer *, real *, real *, integer *, integer *); real safmin; extern /* Subroutine */ int slarfg_(integer *, real *, real *, integer *, real *); real safmax; extern /* Subroutine */ int slahqr_(logical *, logical *, integer *, integer *, integer *, real *, integer *, real *, real *, integer * , integer *, real *, integer *, integer *), slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *); logical sorted; extern /* Subroutine */ int strexc_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, integer *), sormhr_(char *, char *, integer *, integer *, integer *, integer *, real *, integer *, real *, real *, integer *, real *, integer *, integer *); real smlnum; integer lwkopt; /* -- LAPACK auxiliary routine (version 3.4.2) -- */ /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */ /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */ /* September 2012 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* ================================================================ */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* ==== Estimate optimal workspace. ==== */ /* Parameter adjustments */ h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --sr; --si; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; wv_dim1 = *ldwv; wv_offset = 1 + wv_dim1; wv -= wv_offset; --work; /* Function Body */ /* Computing MIN */ i__1 = *nw; i__2 = *kbot - *ktop + 1; // , expr subst jw = min(i__1,i__2); if (jw <= 2) { lwkopt = 1; } else { /* ==== Workspace query call to SGEHRD ==== */ i__1 = jw - 1; sgehrd_(&jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &work[1], & c_n1, &info); lwk1 = (integer) work[1]; /* ==== Workspace query call to SORMHR ==== */ i__1 = jw - 1; sormhr_("R", "N", &jw, &jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[1], &c_n1, &info); lwk2 = (integer) work[1]; /* ==== Optimal workspace ==== */ lwkopt = jw + max(lwk1,lwk2); } /* ==== Quick return in case of workspace query. ==== */ if (*lwork == -1) { work[1] = (real) lwkopt; return 0; } /* ==== Nothing to do ... */ /* ... for an empty active block ... ==== */ *ns = 0; *nd = 0; work[1] = 1.f; if (*ktop > *kbot) { return 0; } /* ... nor for an empty deflation window. ==== */ if (*nw < 1) { return 0; } /* ==== Machine constants ==== */ safmin = slamch_("SAFE MINIMUM"); safmax = 1.f / safmin; slabad_(&safmin, &safmax); ulp = slamch_("PRECISION"); smlnum = safmin * ((real) (*n) / ulp); /* ==== Setup deflation window ==== */ /* Computing MIN */ i__1 = *nw; i__2 = *kbot - *ktop + 1; // , expr subst jw = min(i__1,i__2); kwtop = *kbot - jw + 1; if (kwtop == *ktop) { s = 0.f; } else { s = h__[kwtop + (kwtop - 1) * h_dim1]; } if (*kbot == kwtop) { /* ==== 1-by-1 deflation window: not much to do ==== */ sr[kwtop] = h__[kwtop + kwtop * h_dim1]; si[kwtop] = 0.f; *ns = 1; *nd = 0; /* Computing MAX */ r__2 = smlnum; r__3 = ulp * (r__1 = h__[kwtop + kwtop * h_dim1], abs( r__1)); // , expr subst if (abs(s) <= max(r__2,r__3)) { *ns = 0; *nd = 1; if (kwtop > *ktop) { h__[kwtop + (kwtop - 1) * h_dim1] = 0.f; } } work[1] = 1.f; return 0; } /* ==== Convert to spike-triangular form. (In case of a */ /* . rare QR failure, this routine continues to do */ /* . aggressive early deflation using that part of */ /* . the deflation window that converged using INFQR */ /* . here and there to keep track.) ==== */ slacpy_("U", &jw, &jw, &h__[kwtop + kwtop * h_dim1], ldh, &t[t_offset], ldt); i__1 = jw - 1; i__2 = *ldh + 1; i__3 = *ldt + 1; scopy_(&i__1, &h__[kwtop + 1 + kwtop * h_dim1], &i__2, &t[t_dim1 + 2], & i__3); slaset_("A", &jw, &jw, &c_b12, &c_b13, &v[v_offset], ldv); slahqr_(&c_true, &c_true, &jw, &c__1, &jw, &t[t_offset], ldt, &sr[kwtop], &si[kwtop], &c__1, &jw, &v[v_offset], ldv, &infqr); /* ==== STREXC needs a clean margin near the diagonal ==== */ i__1 = jw - 3; for (j = 1; j <= i__1; ++j) { t[j + 2 + j * t_dim1] = 0.f; t[j + 3 + j * t_dim1] = 0.f; /* L10: */ } if (jw > 2) { t[jw + (jw - 2) * t_dim1] = 0.f; } /* ==== Deflation detection loop ==== */ *ns = jw; ilst = infqr + 1; L20: if (ilst <= *ns) { if (*ns == 1) { bulge = FALSE_; } else { bulge = t[*ns + (*ns - 1) * t_dim1] != 0.f; } /* ==== Small spike tip test for deflation ==== */ if (! bulge) { /* ==== Real eigenvalue ==== */ foo = (r__1 = t[*ns + *ns * t_dim1], abs(r__1)); if (foo == 0.f) { foo = abs(s); } /* Computing MAX */ r__2 = smlnum; r__3 = ulp * foo; // , expr subst if ((r__1 = s * v[*ns * v_dim1 + 1], abs(r__1)) <= max(r__2,r__3)) { /* ==== Deflatable ==== */ --(*ns); } else { /* ==== Undeflatable. Move it up out of the way. */ /* . (STREXC can not fail in this case.) ==== */ ifst = *ns; strexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ++ilst; } } else { /* ==== Complex conjugate pair ==== */ foo = (r__3 = t[*ns + *ns * t_dim1], abs(r__3)) + sqrt((r__1 = t[* ns + (*ns - 1) * t_dim1], abs(r__1))) * sqrt((r__2 = t[* ns - 1 + *ns * t_dim1], abs(r__2))); if (foo == 0.f) { foo = abs(s); } /* Computing MAX */ r__3 = (r__1 = s * v[*ns * v_dim1 + 1], abs(r__1)); r__4 = (r__2 = s * v[(*ns - 1) * v_dim1 + 1], abs(r__2)); // , expr subst /* Computing MAX */ r__5 = smlnum; r__6 = ulp * foo; // , expr subst if (max(r__3,r__4) <= max(r__5,r__6)) { /* ==== Deflatable ==== */ *ns += -2; } else { /* ==== Undeflatable. Move them up out of the way. */ /* . Fortunately, STREXC does the right thing with */ /* . ILST in case of a rare exchange failure. ==== */ ifst = *ns; strexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ilst += 2; } } /* ==== End deflation detection loop ==== */ goto L20; } /* ==== Return to Hessenberg form ==== */ if (*ns == 0) { s = 0.f; } if (*ns < jw) { /* ==== sorting diagonal blocks of T improves accuracy for */ /* . graded matrices. Bubble sort deals well with */ /* . exchange failures. ==== */ sorted = FALSE_; i__ = *ns + 1; L30: if (sorted) { goto L50; } sorted = TRUE_; kend = i__ - 1; i__ = infqr + 1; if (i__ == *ns) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.f) { k = i__ + 1; } else { k = i__ + 2; } L40: if (k <= kend) { if (k == i__ + 1) { evi = (r__1 = t[i__ + i__ * t_dim1], abs(r__1)); } else { evi = (r__3 = t[i__ + i__ * t_dim1], abs(r__3)) + sqrt((r__1 = t[i__ + 1 + i__ * t_dim1], abs(r__1))) * sqrt((r__2 = t[i__ + (i__ + 1) * t_dim1], abs(r__2))); } if (k == kend) { evk = (r__1 = t[k + k * t_dim1], abs(r__1)); } else if (t[k + 1 + k * t_dim1] == 0.f) { evk = (r__1 = t[k + k * t_dim1], abs(r__1)); } else { evk = (r__3 = t[k + k * t_dim1], abs(r__3)) + sqrt((r__1 = t[ k + 1 + k * t_dim1], abs(r__1))) * sqrt((r__2 = t[k + (k + 1) * t_dim1], abs(r__2))); } if (evi >= evk) { i__ = k; } else { sorted = FALSE_; ifst = i__; ilst = k; strexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); if (info == 0) { i__ = ilst; } else { i__ = k; } } if (i__ == kend) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.f) { k = i__ + 1; } else { k = i__ + 2; } goto L40; } goto L30; L50: ; } /* ==== Restore shift/eigenvalue array from T ==== */ i__ = jw; L60: if (i__ >= infqr + 1) { if (i__ == infqr + 1) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.f; --i__; } else if (t[i__ + (i__ - 1) * t_dim1] == 0.f) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.f; --i__; } else { aa = t[i__ - 1 + (i__ - 1) * t_dim1]; cc = t[i__ + (i__ - 1) * t_dim1]; bb = t[i__ - 1 + i__ * t_dim1]; dd = t[i__ + i__ * t_dim1]; slanv2_(&aa, &bb, &cc, &dd, &sr[kwtop + i__ - 2], &si[kwtop + i__ - 2], &sr[kwtop + i__ - 1], &si[kwtop + i__ - 1], &cs, & sn); i__ += -2; } goto L60; } if (*ns < jw || s == 0.f) { if (*ns > 1 && s != 0.f) { /* ==== Reflect spike back into lower triangle ==== */ scopy_(ns, &v[v_offset], ldv, &work[1], &c__1); beta = work[1]; slarfg_(ns, &beta, &work[2], &c__1, &tau); work[1] = 1.f; i__1 = jw - 2; i__2 = jw - 2; slaset_("L", &i__1, &i__2, &c_b12, &c_b12, &t[t_dim1 + 3], ldt); slarf_("L", ns, &jw, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); slarf_("R", ns, ns, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); slarf_("R", &jw, ns, &work[1], &c__1, &tau, &v[v_offset], ldv, & work[jw + 1]); i__1 = *lwork - jw; sgehrd_(&jw, &c__1, ns, &t[t_offset], ldt, &work[1], &work[jw + 1] , &i__1, &info); } /* ==== Copy updated reduced window into place ==== */ if (kwtop > 1) { h__[kwtop + (kwtop - 1) * h_dim1] = s * v[v_dim1 + 1]; } slacpy_("U", &jw, &jw, &t[t_offset], ldt, &h__[kwtop + kwtop * h_dim1] , ldh); i__1 = jw - 1; i__2 = *ldt + 1; i__3 = *ldh + 1; scopy_(&i__1, &t[t_dim1 + 2], &i__2, &h__[kwtop + 1 + kwtop * h_dim1], &i__3); /* ==== Accumulate orthogonal matrix in order update */ /* . H and Z, if requested. ==== */ if (*ns > 1 && s != 0.f) { i__1 = *lwork - jw; sormhr_("R", "N", &jw, ns, &c__1, ns, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[jw + 1], &i__1, &info); } /* ==== Update vertical slab in H ==== */ if (*wantt) { ltop = 1; } else { ltop = *ktop; } i__1 = kwtop - 1; i__2 = *nv; for (krow = ltop; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { /* Computing MIN */ i__3 = *nv; i__4 = kwtop - krow; // , expr subst kln = min(i__3,i__4); sgemm_("N", "N", &kln, &jw, &jw, &c_b13, &h__[krow + kwtop * h_dim1], ldh, &v[v_offset], ldv, &c_b12, &wv[wv_offset], ldwv); slacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &h__[krow + kwtop * h_dim1], ldh); /* L70: */ } /* ==== Update horizontal slab in H ==== */ if (*wantt) { i__2 = *n; i__1 = *nh; for (kcol = *kbot + 1; i__1 < 0 ? kcol >= i__2 : kcol <= i__2; kcol += i__1) { /* Computing MIN */ i__3 = *nh; i__4 = *n - kcol + 1; // , expr subst kln = min(i__3,i__4); sgemm_("C", "N", &jw, &kln, &jw, &c_b13, &v[v_offset], ldv, & h__[kwtop + kcol * h_dim1], ldh, &c_b12, &t[t_offset], ldt); slacpy_("A", &jw, &kln, &t[t_offset], ldt, &h__[kwtop + kcol * h_dim1], ldh); /* L80: */ } } /* ==== Update vertical slab in Z ==== */ if (*wantz) { i__1 = *ihiz; i__2 = *nv; for (krow = *iloz; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { /* Computing MIN */ i__3 = *nv; i__4 = *ihiz - krow + 1; // , expr subst kln = min(i__3,i__4); sgemm_("N", "N", &kln, &jw, &jw, &c_b13, &z__[krow + kwtop * z_dim1], ldz, &v[v_offset], ldv, &c_b12, &wv[ wv_offset], ldwv); slacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &z__[krow + kwtop * z_dim1], ldz); /* L90: */ } } } /* ==== Return the number of deflations ... ==== */ *nd = jw - *ns; /* ==== ... and the number of shifts. (Subtracting */ /* . INFQR from the spike length takes care */ /* . of the case of a rare QR failure while */ /* . calculating eigenvalues of the deflation */ /* . window.) ==== */ *ns -= infqr; /* ==== Return optimal workspace. ==== */ work[1] = (real) lwkopt; /* ==== End of SLAQR2 ==== */ return 0; }
/* Subroutine */ int slaqr2_(logical *wantt, logical *wantz, integer *n, integer *ktop, integer *kbot, integer *nw, real *h__, integer *ldh, integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *ns, integer *nd, real *sr, real *si, real *v, integer *ldv, integer *nh, real *t, integer *ldt, integer *nv, real *wv, integer *ldwv, real * work, integer *lwork) { /* System generated locals */ integer h_dim1, h_offset, t_dim1, t_offset, v_dim1, v_offset, wv_dim1, wv_offset, z_dim1, z_offset, i__1, i__2, i__3, i__4; real r__1, r__2, r__3, r__4, r__5, r__6; /* Local variables */ integer i__, j, k; real s, aa, bb, cc, dd, cs, sn; integer jw; real evi, evk, foo; integer kln; real tau, ulp; integer lwk1, lwk2; real beta; integer kend, kcol, info, ifst, ilst, ltop, krow; logical bulge; integer infqr; integer kwtop; real safmin; real safmax; logical sorted; real smlnum; integer lwkopt; /* -- LAPACK auxiliary routine (version 3.2.1) -- */ /* -- April 2009 -- */ /* This subroutine is identical to SLAQR3 except that it avoids */ /* recursion by calling SLAHQR instead of SLAQR4. */ /* ****************************************************************** */ /* Aggressive early deflation: */ /* This subroutine accepts as input an upper Hessenberg matrix */ /* H and performs an orthogonal similarity transformation */ /* designed to detect and deflate fully converged eigenvalues from */ /* a trailing principal submatrix. On output H has been over- */ /* written by a new Hessenberg matrix that is a perturbation of */ /* an orthogonal similarity transformation of H. It is to be */ /* hoped that the final version of H has many zero subdiagonal */ /* entries. */ /* ****************************************************************** */ /* WANTT (input) LOGICAL */ /* If .TRUE., then the Hessenberg matrix H is fully updated */ /* so that the quasi-triangular Schur factor may be */ /* computed (in cooperation with the calling subroutine). */ /* If .FALSE., then only enough of H is updated to preserve */ /* the eigenvalues. */ /* WANTZ (input) LOGICAL */ /* If .TRUE., then the orthogonal matrix Z is updated so */ /* so that the orthogonal Schur factor may be computed */ /* (in cooperation with the calling subroutine). */ /* If .FALSE., then Z is not referenced. */ /* N (input) INTEGER */ /* The order of the matrix H and (if WANTZ is .TRUE.) the */ /* order of the orthogonal matrix Z. */ /* KTOP (input) INTEGER */ /* It is assumed that either KTOP = 1 or H(KTOP,KTOP-1)=0. */ /* KBOT and KTOP together determine an isolated block */ /* along the diagonal of the Hessenberg matrix. */ /* KBOT (input) INTEGER */ /* It is assumed without a check that either */ /* KBOT = N or H(KBOT+1,KBOT)=0. KBOT and KTOP together */ /* determine an isolated block along the diagonal of the */ /* Hessenberg matrix. */ /* NW (input) INTEGER */ /* Deflation window size. 1 .LE. NW .LE. (KBOT-KTOP+1). */ /* H (input/output) REAL array, dimension (LDH,N) */ /* On input the initial N-by-N section of H stores the */ /* Hessenberg matrix undergoing aggressive early deflation. */ /* On output H has been transformed by an orthogonal */ /* similarity transformation, perturbed, and the returned */ /* to Hessenberg form that (it is to be hoped) has some */ /* zero subdiagonal entries. */ /* LDH (input) integer */ /* Leading dimension of H just as declared in the calling */ /* subroutine. N .LE. LDH */ /* ILOZ (input) INTEGER */ /* IHIZ (input) INTEGER */ /* Specify the rows of Z to which transformations must be */ /* Z (input/output) REAL array, dimension (LDZ,N) */ /* IF WANTZ is .TRUE., then on output, the orthogonal */ /* similarity transformation mentioned above has been */ /* accumulated into Z(ILOZ:IHIZ,ILO:IHI) from the right. */ /* If WANTZ is .FALSE., then Z is unreferenced. */ /* LDZ (input) integer */ /* The leading dimension of Z just as declared in the */ /* calling subroutine. 1 .LE. LDZ. */ /* NS (output) integer */ /* The number of unconverged (ie approximate) eigenvalues */ /* returned in SR and SI that may be used as shifts by the */ /* calling subroutine. */ /* ND (output) integer */ /* The number of converged eigenvalues uncovered by this */ /* subroutine. */ /* SR (output) REAL array, dimension KBOT */ /* SI (output) REAL array, dimension KBOT */ /* On output, the real and imaginary parts of approximate */ /* eigenvalues that may be used for shifts are stored in */ /* SR(KBOT-ND-NS+1) through SR(KBOT-ND) and */ /* SI(KBOT-ND-NS+1) through SI(KBOT-ND), respectively. */ /* The real and imaginary parts of converged eigenvalues */ /* are stored in SR(KBOT-ND+1) through SR(KBOT) and */ /* SI(KBOT-ND+1) through SI(KBOT), respectively. */ /* V (workspace) REAL array, dimension (LDV,NW) */ /* An NW-by-NW work array. */ /* LDV (input) integer scalar */ /* The leading dimension of V just as declared in the */ /* calling subroutine. NW .LE. LDV */ /* NH (input) integer scalar */ /* The number of columns of T. NH.GE.NW. */ /* T (workspace) REAL array, dimension (LDT,NW) */ /* LDT (input) integer */ /* The leading dimension of T just as declared in the */ /* calling subroutine. NW .LE. LDT */ /* NV (input) integer */ /* The number of rows of work array WV available for */ /* workspace. NV.GE.NW. */ /* WV (workspace) REAL array, dimension (LDWV,NW) */ /* LDWV (input) integer */ /* The leading dimension of W just as declared in the */ /* calling subroutine. NW .LE. LDV */ /* WORK (workspace) REAL array, dimension LWORK. */ /* On exit, WORK(1) is set to an estimate of the optimal value */ /* of LWORK for the given values of N, NW, KTOP and KBOT. */ /* LWORK (input) integer */ /* The dimension of the work array WORK. LWORK = 2*NW */ /* suffices, but greater efficiency may result from larger */ /* values of LWORK. */ /* If LWORK = -1, then a workspace query is assumed; SLAQR2 */ /* only estimates the optimal workspace size for the given */ /* values of N, NW, KTOP and KBOT. The estimate is returned */ /* in WORK(1). No error message related to LWORK is issued */ /* by XERBLA. Neither H nor Z are accessed. */ /* ================================================================ */ /* Based on contributions by */ /* Karen Braman and Ralph Byers, Department of Mathematics, */ /* University of Kansas, USA */ /* ================================================================ */ /* ==== Estimate optimal workspace. ==== */ /* Parameter adjustments */ h_dim1 = *ldh; h_offset = 1 + h_dim1; h__ -= h_offset; z_dim1 = *ldz; z_offset = 1 + z_dim1; z__ -= z_offset; --sr; --si; v_dim1 = *ldv; v_offset = 1 + v_dim1; v -= v_offset; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; wv_dim1 = *ldwv; wv_offset = 1 + wv_dim1; wv -= wv_offset; --work; /* Function Body */ /* Computing MIN */ i__1 = *nw, i__2 = *kbot - *ktop + 1; jw = min(i__1,i__2); if (jw <= 2) { lwkopt = 1; } else { /* ==== Workspace query call to SGEHRD ==== */ i__1 = jw - 1; sgehrd_(&jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &work[1], & c_n1, &info); lwk1 = (integer) work[1]; /* ==== Workspace query call to SORMHR ==== */ i__1 = jw - 1; sormhr_("R", "N", &jw, &jw, &c__1, &i__1, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[1], &c_n1, &info); lwk2 = (integer) work[1]; /* ==== Optimal workspace ==== */ lwkopt = jw + max(lwk1,lwk2); } /* ==== Quick return in case of workspace query. ==== */ if (*lwork == -1) { work[1] = (real) lwkopt; return 0; } *ns = 0; *nd = 0; work[1] = 1.f; if (*ktop > *kbot) { return 0; } if (*nw < 1) { return 0; } /* ==== Machine constants ==== */ safmin = slamch_("SAFE MINIMUM"); safmax = 1.f / safmin; slabad_(&safmin, &safmax); ulp = slamch_("PRECISION"); smlnum = safmin * ((real) (*n) / ulp); /* ==== Setup deflation window ==== */ /* Computing MIN */ i__1 = *nw, i__2 = *kbot - *ktop + 1; jw = min(i__1,i__2); kwtop = *kbot - jw + 1; if (kwtop == *ktop) { s = 0.f; } else { s = h__[kwtop + (kwtop - 1) * h_dim1]; } if (*kbot == kwtop) { /* ==== 1-by-1 deflation window: not much to do ==== */ sr[kwtop] = h__[kwtop + kwtop * h_dim1]; si[kwtop] = 0.f; *ns = 1; *nd = 0; /* Computing MAX */ r__2 = smlnum, r__3 = ulp * (r__1 = h__[kwtop + kwtop * h_dim1], dabs( r__1)); if (dabs(s) <= dmax(r__2,r__3)) { *ns = 0; *nd = 1; if (kwtop > *ktop) { h__[kwtop + (kwtop - 1) * h_dim1] = 0.f; } } work[1] = 1.f; return 0; } /* ==== Convert to spike-triangular form. (In case of a */ /* . rare QR failure, this routine continues to do */ /* . aggressive early deflation using that part of */ /* . the deflation window that converged using INFQR */ /* . here and there to keep track.) ==== */ slacpy_("U", &jw, &jw, &h__[kwtop + kwtop * h_dim1], ldh, &t[t_offset], ldt); i__1 = jw - 1; i__2 = *ldh + 1; i__3 = *ldt + 1; scopy_(&i__1, &h__[kwtop + 1 + kwtop * h_dim1], &i__2, &t[t_dim1 + 2], & i__3); slaset_("A", &jw, &jw, &c_b12, &c_b13, &v[v_offset], ldv); slahqr_(&c_true, &c_true, &jw, &c__1, &jw, &t[t_offset], ldt, &sr[kwtop], &si[kwtop], &c__1, &jw, &v[v_offset], ldv, &infqr); /* ==== STREXC needs a clean margin near the diagonal ==== */ i__1 = jw - 3; for (j = 1; j <= i__1; ++j) { t[j + 2 + j * t_dim1] = 0.f; t[j + 3 + j * t_dim1] = 0.f; } if (jw > 2) { t[jw + (jw - 2) * t_dim1] = 0.f; } /* ==== Deflation detection loop ==== */ *ns = jw; ilst = infqr + 1; L20: if (ilst <= *ns) { if (*ns == 1) { bulge = FALSE_; } else { bulge = t[*ns + (*ns - 1) * t_dim1] != 0.f; } /* ==== Small spike tip test for deflation ==== */ if (! bulge) { /* ==== Real eigenvalue ==== */ foo = (r__1 = t[*ns + *ns * t_dim1], dabs(r__1)); if (foo == 0.f) { foo = dabs(s); } /* Computing MAX */ r__2 = smlnum, r__3 = ulp * foo; if ((r__1 = s * v[*ns * v_dim1 + 1], dabs(r__1)) <= dmax(r__2, r__3)) { /* ==== Deflatable ==== */ --(*ns); } else { /* ==== Undeflatable. Move it up out of the way. */ /* . (STREXC can not fail in this case.) ==== */ ifst = *ns; strexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ++ilst; } } else { /* ==== Complex conjugate pair ==== */ foo = (r__3 = t[*ns + *ns * t_dim1], dabs(r__3)) + sqrt((r__1 = t[ *ns + (*ns - 1) * t_dim1], dabs(r__1))) * sqrt((r__2 = t[* ns - 1 + *ns * t_dim1], dabs(r__2))); if (foo == 0.f) { foo = dabs(s); } /* Computing MAX */ r__3 = (r__1 = s * v[*ns * v_dim1 + 1], dabs(r__1)), r__4 = (r__2 = s * v[(*ns - 1) * v_dim1 + 1], dabs(r__2)); /* Computing MAX */ r__5 = smlnum, r__6 = ulp * foo; if (dmax(r__3,r__4) <= dmax(r__5,r__6)) { /* ==== Deflatable ==== */ *ns += -2; } else { /* ==== Undeflatable. Move them up out of the way. */ /* . Fortunately, STREXC does the right thing with */ /* . ILST in case of a rare exchange failure. ==== */ ifst = *ns; strexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); ilst += 2; } } /* ==== End deflation detection loop ==== */ goto L20; } /* ==== Return to Hessenberg form ==== */ if (*ns == 0) { s = 0.f; } if (*ns < jw) { /* ==== sorting diagonal blocks of T improves accuracy for */ /* . graded matrices. Bubble sort deals well with */ /* . exchange failures. ==== */ sorted = FALSE_; i__ = *ns + 1; L30: if (sorted) { goto L50; } sorted = TRUE_; kend = i__ - 1; i__ = infqr + 1; if (i__ == *ns) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.f) { k = i__ + 1; } else { k = i__ + 2; } L40: if (k <= kend) { if (k == i__ + 1) { evi = (r__1 = t[i__ + i__ * t_dim1], dabs(r__1)); } else { evi = (r__3 = t[i__ + i__ * t_dim1], dabs(r__3)) + sqrt((r__1 = t[i__ + 1 + i__ * t_dim1], dabs(r__1))) * sqrt(( r__2 = t[i__ + (i__ + 1) * t_dim1], dabs(r__2))); } if (k == kend) { evk = (r__1 = t[k + k * t_dim1], dabs(r__1)); } else if (t[k + 1 + k * t_dim1] == 0.f) { evk = (r__1 = t[k + k * t_dim1], dabs(r__1)); } else { evk = (r__3 = t[k + k * t_dim1], dabs(r__3)) + sqrt((r__1 = t[ k + 1 + k * t_dim1], dabs(r__1))) * sqrt((r__2 = t[k + (k + 1) * t_dim1], dabs(r__2))); } if (evi >= evk) { i__ = k; } else { sorted = FALSE_; ifst = i__; ilst = k; strexc_("V", &jw, &t[t_offset], ldt, &v[v_offset], ldv, &ifst, &ilst, &work[1], &info); if (info == 0) { i__ = ilst; } else { i__ = k; } } if (i__ == kend) { k = i__ + 1; } else if (t[i__ + 1 + i__ * t_dim1] == 0.f) { k = i__ + 1; } else { k = i__ + 2; } goto L40; } goto L30; L50: ; } /* ==== Restore shift/eigenvalue array from T ==== */ i__ = jw; L60: if (i__ >= infqr + 1) { if (i__ == infqr + 1) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.f; --i__; } else if (t[i__ + (i__ - 1) * t_dim1] == 0.f) { sr[kwtop + i__ - 1] = t[i__ + i__ * t_dim1]; si[kwtop + i__ - 1] = 0.f; --i__; } else { aa = t[i__ - 1 + (i__ - 1) * t_dim1]; cc = t[i__ + (i__ - 1) * t_dim1]; bb = t[i__ - 1 + i__ * t_dim1]; dd = t[i__ + i__ * t_dim1]; slanv2_(&aa, &bb, &cc, &dd, &sr[kwtop + i__ - 2], &si[kwtop + i__ - 2], &sr[kwtop + i__ - 1], &si[kwtop + i__ - 1], &cs, & sn); i__ += -2; } goto L60; } if (*ns < jw || s == 0.f) { if (*ns > 1 && s != 0.f) { /* ==== Reflect spike back into lower triangle ==== */ scopy_(ns, &v[v_offset], ldv, &work[1], &c__1); beta = work[1]; slarfg_(ns, &beta, &work[2], &c__1, &tau); work[1] = 1.f; i__1 = jw - 2; i__2 = jw - 2; slaset_("L", &i__1, &i__2, &c_b12, &c_b12, &t[t_dim1 + 3], ldt); slarf_("L", ns, &jw, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); slarf_("R", ns, ns, &work[1], &c__1, &tau, &t[t_offset], ldt, & work[jw + 1]); slarf_("R", &jw, ns, &work[1], &c__1, &tau, &v[v_offset], ldv, & work[jw + 1]); i__1 = *lwork - jw; sgehrd_(&jw, &c__1, ns, &t[t_offset], ldt, &work[1], &work[jw + 1] , &i__1, &info); } /* ==== Copy updated reduced window into place ==== */ if (kwtop > 1) { h__[kwtop + (kwtop - 1) * h_dim1] = s * v[v_dim1 + 1]; } slacpy_("U", &jw, &jw, &t[t_offset], ldt, &h__[kwtop + kwtop * h_dim1] , ldh); i__1 = jw - 1; i__2 = *ldt + 1; i__3 = *ldh + 1; scopy_(&i__1, &t[t_dim1 + 2], &i__2, &h__[kwtop + 1 + kwtop * h_dim1], &i__3); /* ==== Accumulate orthogonal matrix in order update */ /* . H and Z, if requested. ==== */ if (*ns > 1 && s != 0.f) { i__1 = *lwork - jw; sormhr_("R", "N", &jw, ns, &c__1, ns, &t[t_offset], ldt, &work[1], &v[v_offset], ldv, &work[jw + 1], &i__1, &info); } /* ==== Update vertical slab in H ==== */ if (*wantt) { ltop = 1; } else { ltop = *ktop; } i__1 = kwtop - 1; i__2 = *nv; for (krow = ltop; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { /* Computing MIN */ i__3 = *nv, i__4 = kwtop - krow; kln = min(i__3,i__4); sgemm_("N", "N", &kln, &jw, &jw, &c_b13, &h__[krow + kwtop * h_dim1], ldh, &v[v_offset], ldv, &c_b12, &wv[wv_offset], ldwv); slacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &h__[krow + kwtop * h_dim1], ldh); } /* ==== Update horizontal slab in H ==== */ if (*wantt) { i__2 = *n; i__1 = *nh; for (kcol = *kbot + 1; i__1 < 0 ? kcol >= i__2 : kcol <= i__2; kcol += i__1) { /* Computing MIN */ i__3 = *nh, i__4 = *n - kcol + 1; kln = min(i__3,i__4); sgemm_("C", "N", &jw, &kln, &jw, &c_b13, &v[v_offset], ldv, & h__[kwtop + kcol * h_dim1], ldh, &c_b12, &t[t_offset], ldt); slacpy_("A", &jw, &kln, &t[t_offset], ldt, &h__[kwtop + kcol * h_dim1], ldh); } } /* ==== Update vertical slab in Z ==== */ if (*wantz) { i__1 = *ihiz; i__2 = *nv; for (krow = *iloz; i__2 < 0 ? krow >= i__1 : krow <= i__1; krow += i__2) { /* Computing MIN */ i__3 = *nv, i__4 = *ihiz - krow + 1; kln = min(i__3,i__4); sgemm_("N", "N", &kln, &jw, &jw, &c_b13, &z__[krow + kwtop * z_dim1], ldz, &v[v_offset], ldv, &c_b12, &wv[ wv_offset], ldwv); slacpy_("A", &kln, &jw, &wv[wv_offset], ldwv, &z__[krow + kwtop * z_dim1], ldz); } } } *nd = jw - *ns; /* . INFQR from the spike length takes care */ /* . of the case of a rare QR failure while */ /* . calculating eigenvalues of the deflation */ /* . window.) ==== */ *ns -= infqr; /* ==== Return optimal workspace. ==== */ work[1] = (real) lwkopt; /* ==== End of SLAQR2 ==== */ return 0; } /* slaqr2_ */
/* Subroutine */ int strsna_(char *job, char *howmny, logical *select, integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr, integer *ldvr, real *s, real *sep, integer *mm, integer *m, real * work, integer *ldwork, integer *iwork, integer *info) { /* System generated locals */ integer t_dim1, t_offset, vl_dim1, vl_offset, vr_dim1, vr_offset, work_dim1, work_offset, i__1, i__2; real r__1, r__2; /* Local variables */ integer i__, j, k, n2; real cs; integer nn, ks; real sn, mu, eps, est; integer kase; real cond; logical pair; integer ierr; real dumm, prod; integer ifst; real lnrm; integer ilst; real rnrm, prod1, prod2; real scale, delta; integer isave[3]; logical wants; real dummy[1]; real bignum; logical wantbh; logical somcon; real smlnum; logical wantsp; /* -- LAPACK routine (version 3.2) -- */ /* November 2006 */ /* Modified to call SLACN2 in place of SLACON, 7 Feb 03, SJH. */ /* Purpose */ /* ======= */ /* STRSNA estimates reciprocal condition numbers for specified */ /* eigenvalues and/or right eigenvectors of a real upper */ /* quasi-triangular matrix T (or of any matrix Q*T*Q**T with Q */ /* orthogonal). */ /* T must be in Schur canonical form (as returned by SHSEQR), that is, */ /* block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each */ /* 2-by-2 diagonal block has its diagonal elements equal and its */ /* off-diagonal elements of opposite sign. */ /* Arguments */ /* ========= */ /* JOB (input) CHARACTER*1 */ /* Specifies whether condition numbers are required for */ /* eigenvalues (S) or eigenvectors (SEP): */ /* = 'E': for eigenvalues only (S); */ /* = 'V': for eigenvectors only (SEP); */ /* = 'B': for both eigenvalues and eigenvectors (S and SEP). */ /* HOWMNY (input) CHARACTER*1 */ /* = 'A': compute condition numbers for all eigenpairs; */ /* = 'S': compute condition numbers for selected eigenpairs */ /* specified by the array SELECT. */ /* SELECT (input) LOGICAL array, dimension (N) */ /* If HOWMNY = 'S', SELECT specifies the eigenpairs for which */ /* condition numbers are required. To select condition numbers */ /* for the eigenpair corresponding to a real eigenvalue w(j), */ /* corresponding to a complex conjugate pair of eigenvalues w(j) */ /* and w(j+1), either SELECT(j) or SELECT(j+1) or both, must be */ /* If HOWMNY = 'A', SELECT is not referenced. */ /* N (input) INTEGER */ /* The order of the matrix T. N >= 0. */ /* T (input) REAL array, dimension (LDT,N) */ /* The upper quasi-triangular matrix T, in Schur canonical form. */ /* LDT (input) INTEGER */ /* The leading dimension of the array T. LDT >= max(1,N). */ /* VL (input) REAL array, dimension (LDVL,M) */ /* If JOB = 'E' or 'B', VL must contain left eigenvectors of T */ /* (or of any Q*T*Q**T with Q orthogonal), corresponding to the */ /* eigenpairs specified by HOWMNY and SELECT. The eigenvectors */ /* must be stored in consecutive columns of VL, as returned by */ /* SHSEIN or STREVC. */ /* If JOB = 'V', VL is not referenced. */ /* LDVL (input) INTEGER */ /* The leading dimension of the array VL. */ /* LDVL >= 1; and if JOB = 'E' or 'B', LDVL >= N. */ /* VR (input) REAL array, dimension (LDVR,M) */ /* If JOB = 'E' or 'B', VR must contain right eigenvectors of T */ /* (or of any Q*T*Q**T with Q orthogonal), corresponding to the */ /* eigenpairs specified by HOWMNY and SELECT. The eigenvectors */ /* must be stored in consecutive columns of VR, as returned by */ /* SHSEIN or STREVC. */ /* If JOB = 'V', VR is not referenced. */ /* LDVR (input) INTEGER */ /* The leading dimension of the array VR. */ /* LDVR >= 1; and if JOB = 'E' or 'B', LDVR >= N. */ /* S (output) REAL array, dimension (MM) */ /* If JOB = 'E' or 'B', the reciprocal condition numbers of the */ /* selected eigenvalues, stored in consecutive elements of the */ /* array. For a complex conjugate pair of eigenvalues two */ /* consecutive elements of S are set to the same value. Thus */ /* S(j), SEP(j), and the j-th columns of VL and VR all */ /* correspond to the same eigenpair (but not in general the */ /* j-th eigenpair, unless all eigenpairs are selected). */ /* If JOB = 'V', S is not referenced. */ /* SEP (output) REAL array, dimension (MM) */ /* If JOB = 'V' or 'B', the estimated reciprocal condition */ /* numbers of the selected eigenvectors, stored in consecutive */ /* elements of the array. For a complex eigenvector two */ /* consecutive elements of SEP are set to the same value. If */ /* the eigenvalues cannot be reordered to compute SEP(j), SEP(j) */ /* is set to 0; this can only occur when the true value would be */ /* very small anyway. */ /* If JOB = 'E', SEP is not referenced. */ /* MM (input) INTEGER */ /* The number of elements in the arrays S (if JOB = 'E' or 'B') */ /* and/or SEP (if JOB = 'V' or 'B'). MM >= M. */ /* M (output) INTEGER */ /* The number of elements of the arrays S and/or SEP actually */ /* used to store the estimated condition numbers. */ /* If HOWMNY = 'A', M is set to N. */ /* WORK (workspace) REAL array, dimension (LDWORK,N+6) */ /* If JOB = 'E', WORK is not referenced. */ /* LDWORK (input) INTEGER */ /* The leading dimension of the array WORK. */ /* LDWORK >= 1; and if JOB = 'V' or 'B', LDWORK >= N. */ /* IWORK (workspace) INTEGER array, dimension (2*(N-1)) */ /* If JOB = 'E', IWORK is not referenced. */ /* INFO (output) INTEGER */ /* = 0: successful exit */ /* < 0: if INFO = -i, the i-th argument had an illegal value */ /* Further Details */ /* =============== */ /* The reciprocal of the condition number of an eigenvalue lambda is */ /* defined as */ /* S(lambda) = |v'*u| / (norm(u)*norm(v)) */ /* where u and v are the right and left eigenvectors of T corresponding */ /* to lambda; v' denotes the conjugate-transpose of v, and norm(u) */ /* denotes the Euclidean norm. These reciprocal condition numbers always */ /* lie between zero (very badly conditioned) and one (very well */ /* conditioned). If n = 1, S(lambda) is defined to be 1. */ /* An approximate error bound for a computed eigenvalue W(i) is given by */ /* EPS * norm(T) / S(i) */ /* where EPS is the machine precision. */ /* The reciprocal of the condition number of the right eigenvector u */ /* corresponding to lambda is defined as follows. Suppose */ /* T = ( lambda c ) */ /* ( 0 T22 ) */ /* Then the reciprocal condition number is */ /* SEP( lambda, T22 ) = sigma-min( T22 - lambda*I ) */ /* where sigma-min denotes the smallest singular value. We approximate */ /* the smallest singular value by the reciprocal of an estimate of the */ /* one-norm of the inverse of T22 - lambda*I. If n = 1, SEP(1) is */ /* defined to be abs(T(1,1)). */ /* An approximate error bound for a computed right eigenvector VR(i) */ /* is given by */ /* EPS * norm(T) / SEP(i) */ /* ===================================================================== */ /* Decode and test the input parameters */ /* Parameter adjustments */ --select; t_dim1 = *ldt; t_offset = 1 + t_dim1; t -= t_offset; vl_dim1 = *ldvl; vl_offset = 1 + vl_dim1; vl -= vl_offset; vr_dim1 = *ldvr; vr_offset = 1 + vr_dim1; vr -= vr_offset; --s; --sep; work_dim1 = *ldwork; work_offset = 1 + work_dim1; work -= work_offset; --iwork; /* Function Body */ wantbh = lsame_(job, "B"); wants = lsame_(job, "E") || wantbh; wantsp = lsame_(job, "V") || wantbh; somcon = lsame_(howmny, "S"); *info = 0; if (! wants && ! wantsp) { *info = -1; } else if (! lsame_(howmny, "A") && ! somcon) { *info = -2; } else if (*n < 0) { *info = -4; } else if (*ldt < max(1,*n)) { *info = -6; } else if (*ldvl < 1 || wants && *ldvl < *n) { *info = -8; } else if (*ldvr < 1 || wants && *ldvr < *n) { *info = -10; } else { /* Set M to the number of eigenpairs for which condition numbers */ /* are required, and test MM. */ if (somcon) { *m = 0; pair = FALSE_; i__1 = *n; for (k = 1; k <= i__1; ++k) { if (pair) { pair = FALSE_; } else { if (k < *n) { if (t[k + 1 + k * t_dim1] == 0.f) { if (select[k]) { ++(*m); } } else { pair = TRUE_; if (select[k] || select[k + 1]) { *m += 2; } } } else { if (select[*n]) { ++(*m); } } } } } else { *m = *n; } if (*mm < *m) { *info = -13; } else if (*ldwork < 1 || wantsp && *ldwork < *n) { *info = -16; } } if (*info != 0) { i__1 = -(*info); xerbla_("STRSNA", &i__1); return 0; } /* Quick return if possible */ if (*n == 0) { return 0; } if (*n == 1) { if (somcon) { if (! select[1]) { return 0; } } if (wants) { s[1] = 1.f; } if (wantsp) { sep[1] = (r__1 = t[t_dim1 + 1], dabs(r__1)); } return 0; } /* Get machine constants */ eps = slamch_("P"); smlnum = slamch_("S") / eps; bignum = 1.f / smlnum; slabad_(&smlnum, &bignum); ks = 0; pair = FALSE_; i__1 = *n; for (k = 1; k <= i__1; ++k) { /* Determine whether T(k,k) begins a 1-by-1 or 2-by-2 block. */ if (pair) { pair = FALSE_; goto L60; } else { if (k < *n) { pair = t[k + 1 + k * t_dim1] != 0.f; } } /* Determine whether condition numbers are required for the k-th */ /* eigenpair. */ if (somcon) { if (pair) { if (! select[k] && ! select[k + 1]) { goto L60; } } else { if (! select[k]) { goto L60; } } } ++ks; if (wants) { /* Compute the reciprocal condition number of the k-th */ /* eigenvalue. */ if (! pair) { /* Real eigenvalue. */ prod = sdot_(n, &vr[ks * vr_dim1 + 1], &c__1, &vl[ks * vl_dim1 + 1], &c__1); rnrm = snrm2_(n, &vr[ks * vr_dim1 + 1], &c__1); lnrm = snrm2_(n, &vl[ks * vl_dim1 + 1], &c__1); s[ks] = dabs(prod) / (rnrm * lnrm); } else { /* Complex eigenvalue. */ prod1 = sdot_(n, &vr[ks * vr_dim1 + 1], &c__1, &vl[ks * vl_dim1 + 1], &c__1); prod1 += sdot_(n, &vr[(ks + 1) * vr_dim1 + 1], &c__1, &vl[(ks + 1) * vl_dim1 + 1], &c__1); prod2 = sdot_(n, &vl[ks * vl_dim1 + 1], &c__1, &vr[(ks + 1) * vr_dim1 + 1], &c__1); prod2 -= sdot_(n, &vl[(ks + 1) * vl_dim1 + 1], &c__1, &vr[ks * vr_dim1 + 1], &c__1); r__1 = snrm2_(n, &vr[ks * vr_dim1 + 1], &c__1); r__2 = snrm2_(n, &vr[(ks + 1) * vr_dim1 + 1], &c__1); rnrm = slapy2_(&r__1, &r__2); r__1 = snrm2_(n, &vl[ks * vl_dim1 + 1], &c__1); r__2 = snrm2_(n, &vl[(ks + 1) * vl_dim1 + 1], &c__1); lnrm = slapy2_(&r__1, &r__2); cond = slapy2_(&prod1, &prod2) / (rnrm * lnrm); s[ks] = cond; s[ks + 1] = cond; } } if (wantsp) { /* Estimate the reciprocal condition number of the k-th */ /* eigenvector. */ /* Copy the matrix T to the array WORK and swap the diagonal */ /* block beginning at T(k,k) to the (1,1) position. */ slacpy_("Full", n, n, &t[t_offset], ldt, &work[work_offset], ldwork); ifst = k; ilst = 1; strexc_("No Q", n, &work[work_offset], ldwork, dummy, &c__1, & ifst, &ilst, &work[(*n + 1) * work_dim1 + 1], &ierr); if (ierr == 1 || ierr == 2) { /* Could not swap because blocks not well separated */ scale = 1.f; est = bignum; } else { /* Reordering successful */ if (work[work_dim1 + 2] == 0.f) { /* Form C = T22 - lambda*I in WORK(2:N,2:N). */ i__2 = *n; for (i__ = 2; i__ <= i__2; ++i__) { work[i__ + i__ * work_dim1] -= work[work_dim1 + 1]; } n2 = 1; nn = *n - 1; } else { /* Triangularize the 2 by 2 block by unitary */ /* transformation U = [ cs i*ss ] */ /* [ i*ss cs ]. */ /* such that the (1,1) position of WORK is complex */ /* eigenvalue lambda with positive imaginary part. (2,2) */ /* position of WORK is the complex eigenvalue lambda */ /* with negative imaginary part. */ mu = sqrt((r__1 = work[(work_dim1 << 1) + 1], dabs(r__1))) * sqrt((r__2 = work[work_dim1 + 2], dabs(r__2))); delta = slapy2_(&mu, &work[work_dim1 + 2]); cs = mu / delta; sn = -work[work_dim1 + 2] / delta; /* Form */ /* [ mu ] */ /* [ mu ] */ /* where C' is conjugate transpose of complex matrix C, */ /* and RWORK is stored starting in the N+1-st column of */ /* WORK. */ i__2 = *n; for (j = 3; j <= i__2; ++j) { work[j * work_dim1 + 2] = cs * work[j * work_dim1 + 2] ; work[j + j * work_dim1] -= work[work_dim1 + 1]; } work[(work_dim1 << 1) + 2] = 0.f; work[(*n + 1) * work_dim1 + 1] = mu * 2.f; i__2 = *n - 1; for (i__ = 2; i__ <= i__2; ++i__) { work[i__ + (*n + 1) * work_dim1] = sn * work[(i__ + 1) * work_dim1 + 1]; } n2 = 2; nn = *n - 1 << 1; } /* Estimate norm(inv(C')) */ est = 0.f; kase = 0; L50: slacn2_(&nn, &work[(*n + 2) * work_dim1 + 1], &work[(*n + 4) * work_dim1 + 1], &iwork[1], &est, &kase, isave); if (kase != 0) { if (kase == 1) { if (n2 == 1) { /* Real eigenvalue: solve C'*x = scale*c. */ i__2 = *n - 1; slaqtr_(&c_true, &c_true, &i__2, &work[(work_dim1 << 1) + 2], ldwork, dummy, &dumm, &scale, &work[(*n + 4) * work_dim1 + 1], &work[(* n + 6) * work_dim1 + 1], &ierr); } else { /* Complex eigenvalue: solve */ /* C'*(p+iq) = scale*(c+id) in real arithmetic. */ i__2 = *n - 1; slaqtr_(&c_true, &c_false, &i__2, &work[( work_dim1 << 1) + 2], ldwork, &work[(*n + 1) * work_dim1 + 1], &mu, &scale, &work[(* n + 4) * work_dim1 + 1], &work[(*n + 6) * work_dim1 + 1], &ierr); } } else { if (n2 == 1) { /* Real eigenvalue: solve C*x = scale*c. */ i__2 = *n - 1; slaqtr_(&c_false, &c_true, &i__2, &work[( work_dim1 << 1) + 2], ldwork, dummy, & dumm, &scale, &work[(*n + 4) * work_dim1 + 1], &work[(*n + 6) * work_dim1 + 1], & ierr); } else { /* Complex eigenvalue: solve */ /* C*(p+iq) = scale*(c+id) in real arithmetic. */ i__2 = *n - 1; slaqtr_(&c_false, &c_false, &i__2, &work[( work_dim1 << 1) + 2], ldwork, &work[(*n + 1) * work_dim1 + 1], &mu, &scale, &work[(* n + 4) * work_dim1 + 1], &work[(*n + 6) * work_dim1 + 1], &ierr); } } goto L50; } } sep[ks] = scale / dmax(est,smlnum); if (pair) { sep[ks + 1] = sep[ks]; } } if (pair) { ++ks; } L60: ; } return 0; /* End of STRSNA */ } /* strsna_ */
/* Subroutine */ int serrec_(char *path, integer *nunit) { /* Format strings */ static char fmt_9999[] = "(1x,a3,\002 routines passed the tests of the e" "rror exits (\002,i3,\002 tests done)\002)"; static char fmt_9998[] = "(\002 *** \002,a3,\002 routines failed the tes" "ts of the error ex\002,\002its ***\002)"; /* Builtin functions Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void); /* Local variables */ static integer info, ifst, ilst; static real work[4], a[16] /* was [4][4] */, b[16] /* was [4][4] */, c__[ 16] /* was [4][4] */; static integer i__, j, m; static real s[4], scale; static integer iwork[4]; static real wi[4]; static integer nt; static real wr[4]; extern /* Subroutine */ int chkxer_(char *, integer *, integer *, logical *, logical *), strexc_(char *, integer *, real *, integer *, real *, integer *, integer *, integer *, real *, integer *), strsna_(char *, char *, logical *, integer *, real *, integer *, real *, integer *, real *, integer *, real *, real *, integer *, integer *, real *, integer *, integer *, integer *), strsen_(char *, char *, logical *, integer *, real *, integer *, real *, integer *, real *, real *, integer *, real *, real *, real *, integer *, integer *, integer *, integer * ), strsyl_(char *, char *, integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer * , real *, integer *); static logical sel[4]; static real sep[4]; /* Fortran I/O blocks */ static cilist io___19 = { 0, 0, 0, fmt_9999, 0 }; static cilist io___20 = { 0, 0, 0, fmt_9998, 0 }; #define a_ref(a_1,a_2) a[(a_2)*4 + a_1 - 5] #define b_ref(a_1,a_2) b[(a_2)*4 + a_1 - 5] /* -- LAPACK test routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University June 30, 1999 Purpose ======= SERREC tests the error exits for the routines for eigen- condition estimation for REAL matrices: STRSYL, STREXC, STRSNA and STRSEN. Arguments ========= PATH (input) CHARACTER*3 The LAPACK path name for the routines to be tested. NUNIT (input) INTEGER The unit number for output. ===================================================================== */ infoc_1.nout = *nunit; infoc_1.ok = TRUE_; nt = 0; /* Initialize A, B and SEL */ for (j = 1; j <= 4; ++j) { for (i__ = 1; i__ <= 4; ++i__) { a_ref(i__, j) = 0.f; b_ref(i__, j) = 0.f; /* L10: */ } /* L20: */ } for (i__ = 1; i__ <= 4; ++i__) { a_ref(i__, i__) = 1.f; sel[i__ - 1] = TRUE_; /* L30: */ } /* Test STRSYL */ s_copy(srnamc_1.srnamt, "STRSYL", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; strsyl_("X", "N", &c__1, &c__0, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; strsyl_("N", "X", &c__1, &c__0, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 3; strsyl_("N", "N", &c__0, &c__0, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; strsyl_("N", "N", &c__1, &c_n1, &c__0, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 5; strsyl_("N", "N", &c__1, &c__0, &c_n1, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; strsyl_("N", "N", &c__1, &c__2, &c__0, a, &c__1, b, &c__1, c__, &c__2, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 9; strsyl_("N", "N", &c__1, &c__0, &c__2, a, &c__1, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 11; strsyl_("N", "N", &c__1, &c__2, &c__0, a, &c__2, b, &c__1, c__, &c__1, & scale, &info); chkxer_("STRSYL", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 8; /* Test STREXC */ s_copy(srnamc_1.srnamt, "STREXC", (ftnlen)6, (ftnlen)6); ifst = 1; ilst = 1; infoc_1.infot = 1; strexc_("X", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; strexc_("N", &c__0, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; ilst = 2; strexc_("N", &c__2, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 6; strexc_("V", &c__2, a, &c__2, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; ifst = 0; ilst = 1; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 7; ifst = 2; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; ifst = 1; ilst = 0; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; ilst = 2; strexc_("V", &c__1, a, &c__1, b, &c__1, &ifst, &ilst, work, &info); chkxer_("STREXC", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 8; /* Test STRSNA */ s_copy(srnamc_1.srnamt, "STRSNA", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; strsna_("X", "A", sel, &c__0, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__1, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; strsna_("B", "X", sel, &c__0, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__1, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; strsna_("B", "A", sel, &c_n1, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__1, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 6; strsna_("V", "A", sel, &c__2, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__2, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; strsna_("B", "A", sel, &c__2, a, &c__2, b, &c__1, c__, &c__2, s, sep, & c__2, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 10; strsna_("B", "A", sel, &c__2, a, &c__2, b, &c__2, c__, &c__1, s, sep, & c__2, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 13; strsna_("B", "A", sel, &c__1, a, &c__1, b, &c__1, c__, &c__1, s, sep, & c__0, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 13; strsna_("B", "S", sel, &c__2, a, &c__2, b, &c__2, c__, &c__2, s, sep, & c__1, &m, work, &c__2, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 16; strsna_("B", "A", sel, &c__2, a, &c__2, b, &c__2, c__, &c__2, s, sep, & c__2, &m, work, &c__1, iwork, &info); chkxer_("STRSNA", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 9; /* Test STRSEN */ sel[0] = FALSE_; s_copy(srnamc_1.srnamt, "STRSEN", (ftnlen)6, (ftnlen)6); infoc_1.infot = 1; strsen_("X", "N", sel, &c__0, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 2; strsen_("N", "X", sel, &c__0, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 4; strsen_("N", "N", sel, &c_n1, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 6; strsen_("N", "N", sel, &c__2, a, &c__1, b, &c__1, wr, wi, &m, s, sep, work, &c__2, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 8; strsen_("N", "V", sel, &c__2, a, &c__2, b, &c__1, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 15; strsen_("N", "V", sel, &c__2, a, &c__2, b, &c__2, wr, wi, &m, s, sep, work, &c__0, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 15; strsen_("E", "V", sel, &c__3, a, &c__3, b, &c__3, wr, wi, &m, s, sep, work, &c__1, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 15; strsen_("V", "V", sel, &c__3, a, &c__3, b, &c__3, wr, wi, &m, s, sep, work, &c__3, iwork, &c__2, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 17; strsen_("E", "V", sel, &c__2, a, &c__2, b, &c__2, wr, wi, &m, s, sep, work, &c__1, iwork, &c__0, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); infoc_1.infot = 17; strsen_("V", "V", sel, &c__3, a, &c__3, b, &c__3, wr, wi, &m, s, sep, work, &c__4, iwork, &c__1, &info); chkxer_("STRSEN", &infoc_1.infot, &infoc_1.nout, &infoc_1.lerr, & infoc_1.ok); nt += 10; /* Print a summary line. */ if (infoc_1.ok) { io___19.ciunit = infoc_1.nout; s_wsfe(&io___19); do_fio(&c__1, path, (ftnlen)3); do_fio(&c__1, (char *)&nt, (ftnlen)sizeof(integer)); e_wsfe(); } else { io___20.ciunit = infoc_1.nout; s_wsfe(&io___20); do_fio(&c__1, path, (ftnlen)3); e_wsfe(); } return 0; /* End of SERREC */ } /* serrec_ */
/* Subroutine */ int sget36_(real *rmax, integer *lmax, integer *ninfo, integer *knt, integer *nin) { /* System generated locals */ integer i__1, i__2; /* Builtin functions */ integer s_rsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), e_rsle(void); double r_sign(real *, real *); /* Local variables */ integer i__, j, n; real q[100] /* was [10][10] */, t1[100] /* was [10][10] */, t2[100] /* was [10][10] */; integer loc; real eps, res, tmp[100] /* was [10][10] */; integer ifst, ilst; real work[200]; integer info1, info2, ifst1, ifst2, ilst1, ilst2; extern /* Subroutine */ int shst01_(integer *, integer *, integer *, real *, integer *, real *, integer *, real *, integer *, real *, integer *, real *); extern doublereal slamch_(char *); extern /* Subroutine */ int slacpy_(char *, integer *, integer *, real *, integer *, real *, integer *), slaset_(char *, integer *, integer *, real *, real *, real *, integer *), strexc_( char *, integer *, real *, integer *, real *, integer *, integer * , integer *, real *, integer *); integer ifstsv; real result[2]; integer ilstsv; /* Fortran I/O blocks */ static cilist io___2 = { 0, 0, 0, 0, 0 }; static cilist io___7 = { 0, 0, 0, 0, 0 }; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* SGET36 tests STREXC, a routine for moving blocks (either 1 by 1 or */ /* 2 by 2) on the diagonal of a matrix in real Schur form. Thus, SLAEXC */ /* computes an orthogonal matrix Q such that */ /* Q' * T1 * Q = T2 */ /* and where one of the diagonal blocks of T1 (the one at row IFST) has */ /* been moved to position ILST. */ /* The test code verifies that the residual Q'*T1*Q-T2 is small, that T2 */ /* is in Schur form, and that the final position of the IFST block is */ /* ILST (within +-1). */ /* The test matrices are read from a file with logical unit number NIN. */ /* Arguments */ /* ========== */ /* RMAX (output) REAL */ /* Value of the largest test ratio. */ /* LMAX (output) INTEGER */ /* Example number where largest test ratio achieved. */ /* NINFO (output) INTEGER array, dimension (3) */ /* NINFO(J) is the number of examples where INFO=J. */ /* KNT (output) INTEGER */ /* Total number of examples tested. */ /* NIN (input) INTEGER */ /* Input logical unit number. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. Local Arrays .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. External Subroutines .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Parameter adjustments */ --ninfo; /* Function Body */ eps = slamch_("P"); *rmax = 0.f; *lmax = 0; *knt = 0; ninfo[1] = 0; ninfo[2] = 0; ninfo[3] = 0; /* Read input data until N=0 */ L10: io___2.ciunit = *nin; s_rsle(&io___2); do_lio(&c__3, &c__1, (char *)&n, (ftnlen)sizeof(integer)); do_lio(&c__3, &c__1, (char *)&ifst, (ftnlen)sizeof(integer)); do_lio(&c__3, &c__1, (char *)&ilst, (ftnlen)sizeof(integer)); e_rsle(); if (n == 0) { return 0; } ++(*knt); i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { io___7.ciunit = *nin; s_rsle(&io___7); i__2 = n; for (j = 1; j <= i__2; ++j) { do_lio(&c__4, &c__1, (char *)&tmp[i__ + j * 10 - 11], (ftnlen) sizeof(real)); } e_rsle(); /* L20: */ } slacpy_("F", &n, &n, tmp, &c__10, t1, &c__10); slacpy_("F", &n, &n, tmp, &c__10, t2, &c__10); ifstsv = ifst; ilstsv = ilst; ifst1 = ifst; ilst1 = ilst; ifst2 = ifst; ilst2 = ilst; res = 0.f; /* Test without accumulating Q */ slaset_("Full", &n, &n, &c_b21, &c_b22, q, &c__10); strexc_("N", &n, t1, &c__10, q, &c__10, &ifst1, &ilst1, work, &info1); i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = n; for (j = 1; j <= i__2; ++j) { if (i__ == j && q[i__ + j * 10 - 11] != 1.f) { res += 1.f / eps; } if (i__ != j && q[i__ + j * 10 - 11] != 0.f) { res += 1.f / eps; } /* L30: */ } /* L40: */ } /* Test with accumulating Q */ slaset_("Full", &n, &n, &c_b21, &c_b22, q, &c__10); strexc_("V", &n, t2, &c__10, q, &c__10, &ifst2, &ilst2, work, &info2); /* Compare T1 with T2 */ i__1 = n; for (i__ = 1; i__ <= i__1; ++i__) { i__2 = n; for (j = 1; j <= i__2; ++j) { if (t1[i__ + j * 10 - 11] != t2[i__ + j * 10 - 11]) { res += 1.f / eps; } /* L50: */ } /* L60: */ } if (ifst1 != ifst2) { res += 1.f / eps; } if (ilst1 != ilst2) { res += 1.f / eps; } if (info1 != info2) { res += 1.f / eps; } /* Test for successful reordering of T2 */ if (info2 != 0) { ++ninfo[info2]; } else { if ((i__1 = ifst2 - ifstsv, abs(i__1)) > 1) { res += 1.f / eps; } if ((i__1 = ilst2 - ilstsv, abs(i__1)) > 1) { res += 1.f / eps; } } /* Test for small residual, and orthogonality of Q */ shst01_(&n, &c__1, &n, tmp, &c__10, t2, &c__10, q, &c__10, work, &c__200, result); res = res + result[0] + result[1]; /* Test for T2 being in Schur form */ loc = 1; L70: if (t2[loc + 1 + loc * 10 - 11] != 0.f) { /* 2 by 2 block */ if (t2[loc + (loc + 1) * 10 - 11] == 0.f || t2[loc + loc * 10 - 11] != t2[loc + 1 + (loc + 1) * 10 - 11] || r_sign(&c_b22, &t2[loc + (loc + 1) * 10 - 11]) == r_sign(&c_b22, &t2[loc + 1 + loc * 10 - 11])) { res += 1.f / eps; } i__1 = n; for (i__ = loc + 2; i__ <= i__1; ++i__) { if (t2[i__ + loc * 10 - 11] != 0.f) { res += 1.f / res; } if (t2[i__ + (loc + 1) * 10 - 11] != 0.f) { res += 1.f / res; } /* L80: */ } loc += 2; } else { /* 1 by 1 block */ i__1 = n; for (i__ = loc + 1; i__ <= i__1; ++i__) { if (t2[i__ + loc * 10 - 11] != 0.f) { res += 1.f / res; } /* L90: */ } ++loc; } if (loc < n) { goto L70; } if (res > *rmax) { *rmax = res; *lmax = *knt; } goto L10; /* End of SGET36 */ } /* sget36_ */