LAPACK 3.3.0

strsen.f

Go to the documentation of this file.
00001       SUBROUTINE STRSEN( JOB, COMPQ, SELECT, N, T, LDT, Q, LDQ, WR, WI,
00002      $                   M, S, SEP, WORK, LWORK, IWORK, LIWORK, INFO )
00003 *
00004 *  -- LAPACK routine (version 3.2) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *     November 2006
00008 *
00009 *     Modified to call SLACN2 in place of SLACON, 7 Feb 03, SJH.
00010 *
00011 *     .. Scalar Arguments ..
00012       CHARACTER          COMPQ, JOB
00013       INTEGER            INFO, LDQ, LDT, LIWORK, LWORK, M, N
00014       REAL               S, SEP
00015 *     ..
00016 *     .. Array Arguments ..
00017       LOGICAL            SELECT( * )
00018       INTEGER            IWORK( * )
00019       REAL               Q( LDQ, * ), T( LDT, * ), WI( * ), WORK( * ),
00020      $                   WR( * )
00021 *     ..
00022 *
00023 *  Purpose
00024 *  =======
00025 *
00026 *  STRSEN reorders the real Schur factorization of a real matrix
00027 *  A = Q*T*Q**T, so that a selected cluster of eigenvalues appears in
00028 *  the leading diagonal blocks of the upper quasi-triangular matrix T,
00029 *  and the leading columns of Q form an orthonormal basis of the
00030 *  corresponding right invariant subspace.
00031 *
00032 *  Optionally the routine computes the reciprocal condition numbers of
00033 *  the cluster of eigenvalues and/or the invariant subspace.
00034 *
00035 *  T must be in Schur canonical form (as returned by SHSEQR), that is,
00036 *  block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each
00037 *  2-by-2 diagonal block has its diagonal elemnts equal and its
00038 *  off-diagonal elements of opposite sign.
00039 *
00040 *  Arguments
00041 *  =========
00042 *
00043 *  JOB     (input) CHARACTER*1
00044 *          Specifies whether condition numbers are required for the
00045 *          cluster of eigenvalues (S) or the invariant subspace (SEP):
00046 *          = 'N': none;
00047 *          = 'E': for eigenvalues only (S);
00048 *          = 'V': for invariant subspace only (SEP);
00049 *          = 'B': for both eigenvalues and invariant subspace (S and
00050 *                 SEP).
00051 *
00052 *  COMPQ   (input) CHARACTER*1
00053 *          = 'V': update the matrix Q of Schur vectors;
00054 *          = 'N': do not update Q.
00055 *
00056 *  SELECT  (input) LOGICAL array, dimension (N)
00057 *          SELECT specifies the eigenvalues in the selected cluster. To
00058 *          select a real eigenvalue w(j), SELECT(j) must be set to
00059 *          .TRUE.. To select a complex conjugate pair of eigenvalues
00060 *          w(j) and w(j+1), corresponding to a 2-by-2 diagonal block,
00061 *          either SELECT(j) or SELECT(j+1) or both must be set to
00062 *          .TRUE.; a complex conjugate pair of eigenvalues must be
00063 *          either both included in the cluster or both excluded.
00064 *
00065 *  N       (input) INTEGER
00066 *          The order of the matrix T. N >= 0.
00067 *
00068 *  T       (input/output) REAL array, dimension (LDT,N)
00069 *          On entry, the upper quasi-triangular matrix T, in Schur
00070 *          canonical form.
00071 *          On exit, T is overwritten by the reordered matrix T, again in
00072 *          Schur canonical form, with the selected eigenvalues in the
00073 *          leading diagonal blocks.
00074 *
00075 *  LDT     (input) INTEGER
00076 *          The leading dimension of the array T. LDT >= max(1,N).
00077 *
00078 *  Q       (input/output) REAL array, dimension (LDQ,N)
00079 *          On entry, if COMPQ = 'V', the matrix Q of Schur vectors.
00080 *          On exit, if COMPQ = 'V', Q has been postmultiplied by the
00081 *          orthogonal transformation matrix which reorders T; the
00082 *          leading M columns of Q form an orthonormal basis for the
00083 *          specified invariant subspace.
00084 *          If COMPQ = 'N', Q is not referenced.
00085 *
00086 *  LDQ     (input) INTEGER
00087 *          The leading dimension of the array Q.
00088 *          LDQ >= 1; and if COMPQ = 'V', LDQ >= N.
00089 *
00090 *  WR      (output) REAL array, dimension (N)
00091 *  WI      (output) REAL array, dimension (N)
00092 *          The real and imaginary parts, respectively, of the reordered
00093 *          eigenvalues of T. The eigenvalues are stored in the same
00094 *          order as on the diagonal of T, with WR(i) = T(i,i) and, if
00095 *          T(i:i+1,i:i+1) is a 2-by-2 diagonal block, WI(i) > 0 and
00096 *          WI(i+1) = -WI(i). Note that if a complex eigenvalue is
00097 *          sufficiently ill-conditioned, then its value may differ
00098 *          significantly from its value before reordering.
00099 *
00100 *  M       (output) INTEGER
00101 *          The dimension of the specified invariant subspace.
00102 *          0 < = M <= N.
00103 *
00104 *  S       (output) REAL
00105 *          If JOB = 'E' or 'B', S is a lower bound on the reciprocal
00106 *          condition number for the selected cluster of eigenvalues.
00107 *          S cannot underestimate the true reciprocal condition number
00108 *          by more than a factor of sqrt(N). If M = 0 or N, S = 1.
00109 *          If JOB = 'N' or 'V', S is not referenced.
00110 *
00111 *  SEP     (output) REAL
00112 *          If JOB = 'V' or 'B', SEP is the estimated reciprocal
00113 *          condition number of the specified invariant subspace. If
00114 *          M = 0 or N, SEP = norm(T).
00115 *          If JOB = 'N' or 'E', SEP is not referenced.
00116 *
00117 *  WORK    (workspace/output) REAL array, dimension (MAX(1,LWORK))
00118 *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
00119 *
00120 *  LWORK   (input) INTEGER
00121 *          The dimension of the array WORK.
00122 *          If JOB = 'N', LWORK >= max(1,N);
00123 *          if JOB = 'E', LWORK >= max(1,M*(N-M));
00124 *          if JOB = 'V' or 'B', LWORK >= max(1,2*M*(N-M)).
00125 *
00126 *          If LWORK = -1, then a workspace query is assumed; the routine
00127 *          only calculates the optimal size of the WORK array, returns
00128 *          this value as the first entry of the WORK array, and no error
00129 *          message related to LWORK is issued by XERBLA.
00130 *
00131 *  IWORK   (workspace) INTEGER array, dimension (MAX(1,LIWORK))
00132 *          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
00133 *
00134 *  LIWORK  (input) INTEGER
00135 *          The dimension of the array IWORK.
00136 *          If JOB = 'N' or 'E', LIWORK >= 1;
00137 *          if JOB = 'V' or 'B', LIWORK >= max(1,M*(N-M)).
00138 *
00139 *          If LIWORK = -1, then a workspace query is assumed; the
00140 *          routine only calculates the optimal size of the IWORK array,
00141 *          returns this value as the first entry of the IWORK array, and
00142 *          no error message related to LIWORK is issued by XERBLA.
00143 *
00144 *  INFO    (output) INTEGER
00145 *          = 0: successful exit
00146 *          < 0: if INFO = -i, the i-th argument had an illegal value
00147 *          = 1: reordering of T failed because some eigenvalues are too
00148 *               close to separate (the problem is very ill-conditioned);
00149 *               T may have been partially reordered, and WR and WI
00150 *               contain the eigenvalues in the same order as in T; S and
00151 *               SEP (if requested) are set to zero.
00152 *
00153 *  Further Details
00154 *  ===============
00155 *
00156 *  STRSEN first collects the selected eigenvalues by computing an
00157 *  orthogonal transformation Z to move them to the top left corner of T.
00158 *  In other words, the selected eigenvalues are the eigenvalues of T11
00159 *  in:
00160 *
00161 *                Z'*T*Z = ( T11 T12 ) n1
00162 *                         (  0  T22 ) n2
00163 *                            n1  n2
00164 *
00165 *  where N = n1+n2 and Z' means the transpose of Z. The first n1 columns
00166 *  of Z span the specified invariant subspace of T.
00167 *
00168 *  If T has been obtained from the real Schur factorization of a matrix
00169 *  A = Q*T*Q', then the reordered real Schur factorization of A is given
00170 *  by A = (Q*Z)*(Z'*T*Z)*(Q*Z)', and the first n1 columns of Q*Z span
00171 *  the corresponding invariant subspace of A.
00172 *
00173 *  The reciprocal condition number of the average of the eigenvalues of
00174 *  T11 may be returned in S. S lies between 0 (very badly conditioned)
00175 *  and 1 (very well conditioned). It is computed as follows. First we
00176 *  compute R so that
00177 *
00178 *                         P = ( I  R ) n1
00179 *                             ( 0  0 ) n2
00180 *                               n1 n2
00181 *
00182 *  is the projector on the invariant subspace associated with T11.
00183 *  R is the solution of the Sylvester equation:
00184 *
00185 *                        T11*R - R*T22 = T12.
00186 *
00187 *  Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote
00188 *  the two-norm of M. Then S is computed as the lower bound
00189 *
00190 *                      (1 + F-norm(R)**2)**(-1/2)
00191 *
00192 *  on the reciprocal of 2-norm(P), the true reciprocal condition number.
00193 *  S cannot underestimate 1 / 2-norm(P) by more than a factor of
00194 *  sqrt(N).
00195 *
00196 *  An approximate error bound for the computed average of the
00197 *  eigenvalues of T11 is
00198 *
00199 *                         EPS * norm(T) / S
00200 *
00201 *  where EPS is the machine precision.
00202 *
00203 *  The reciprocal condition number of the right invariant subspace
00204 *  spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP.
00205 *  SEP is defined as the separation of T11 and T22:
00206 *
00207 *                     sep( T11, T22 ) = sigma-min( C )
00208 *
00209 *  where sigma-min(C) is the smallest singular value of the
00210 *  n1*n2-by-n1*n2 matrix
00211 *
00212 *     C  = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) )
00213 *
00214 *  I(m) is an m by m identity matrix, and kprod denotes the Kronecker
00215 *  product. We estimate sigma-min(C) by the reciprocal of an estimate of
00216 *  the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C)
00217 *  cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2).
00218 *
00219 *  When SEP is small, small changes in T can cause large changes in
00220 *  the invariant subspace. An approximate bound on the maximum angular
00221 *  error in the computed right invariant subspace is
00222 *
00223 *                      EPS * norm(T) / SEP
00224 *
00225 *  =====================================================================
00226 *
00227 *     .. Parameters ..
00228       REAL               ZERO, ONE
00229       PARAMETER          ( ZERO = 0.0E+0, ONE = 1.0E+0 )
00230 *     ..
00231 *     .. Local Scalars ..
00232       LOGICAL            LQUERY, PAIR, SWAP, WANTBH, WANTQ, WANTS,
00233      $                    WANTSP
00234       INTEGER            IERR, K, KASE, KK, KS, LIWMIN, LWMIN, N1, N2,
00235      $                   NN
00236       REAL               EST, RNORM, SCALE
00237 *     ..
00238 *     .. Local Arrays ..
00239       INTEGER            ISAVE( 3 )
00240 *     ..
00241 *     .. External Functions ..
00242       LOGICAL            LSAME
00243       REAL               SLANGE
00244       EXTERNAL           LSAME, SLANGE
00245 *     ..
00246 *     .. External Subroutines ..
00247       EXTERNAL           SLACN2, SLACPY, STREXC, STRSYL, XERBLA
00248 *     ..
00249 *     .. Intrinsic Functions ..
00250       INTRINSIC          ABS, MAX, SQRT
00251 *     ..
00252 *     .. Executable Statements ..
00253 *
00254 *     Decode and test the input parameters
00255 *
00256       WANTBH = LSAME( JOB, 'B' )
00257       WANTS = LSAME( JOB, 'E' ) .OR. WANTBH
00258       WANTSP = LSAME( JOB, 'V' ) .OR. WANTBH
00259       WANTQ = LSAME( COMPQ, 'V' )
00260 *
00261       INFO = 0
00262       LQUERY = ( LWORK.EQ.-1 )
00263       IF( .NOT.LSAME( JOB, 'N' ) .AND. .NOT.WANTS .AND. .NOT.WANTSP )
00264      $     THEN
00265          INFO = -1
00266       ELSE IF( .NOT.LSAME( COMPQ, 'N' ) .AND. .NOT.WANTQ ) THEN
00267          INFO = -2
00268       ELSE IF( N.LT.0 ) THEN
00269          INFO = -4
00270       ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
00271          INFO = -6
00272       ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.N ) ) THEN
00273          INFO = -8
00274       ELSE
00275 *
00276 *        Set M to the dimension of the specified invariant subspace,
00277 *        and test LWORK and LIWORK.
00278 *
00279          M = 0
00280          PAIR = .FALSE.
00281          DO 10 K = 1, N
00282             IF( PAIR ) THEN
00283                PAIR = .FALSE.
00284             ELSE
00285                IF( K.LT.N ) THEN
00286                   IF( T( K+1, K ).EQ.ZERO ) THEN
00287                      IF( SELECT( K ) )
00288      $                  M = M + 1
00289                   ELSE
00290                      PAIR = .TRUE.
00291                      IF( SELECT( K ) .OR. SELECT( K+1 ) )
00292      $                  M = M + 2
00293                   END IF
00294                ELSE
00295                   IF( SELECT( N ) )
00296      $               M = M + 1
00297                END IF
00298             END IF
00299    10    CONTINUE
00300 *
00301          N1 = M
00302          N2 = N - M
00303          NN = N1*N2
00304 *
00305          IF(  WANTSP ) THEN
00306             LWMIN = MAX( 1, 2*NN )
00307             LIWMIN = MAX( 1, NN )
00308          ELSE IF( LSAME( JOB, 'N' ) ) THEN
00309             LWMIN = MAX( 1, N )
00310             LIWMIN = 1
00311          ELSE IF( LSAME( JOB, 'E' ) ) THEN
00312             LWMIN = MAX( 1, NN )
00313             LIWMIN = 1
00314          END IF
00315 *
00316          IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
00317             INFO = -15
00318          ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
00319             INFO = -17
00320          END IF
00321       END IF
00322 *
00323       IF( INFO.EQ.0 ) THEN
00324          WORK( 1 ) = LWMIN
00325          IWORK( 1 ) = LIWMIN
00326       END IF
00327 *
00328       IF( INFO.NE.0 ) THEN
00329          CALL XERBLA( 'STRSEN', -INFO )
00330          RETURN
00331       ELSE IF( LQUERY ) THEN
00332          RETURN
00333       END IF
00334 *
00335 *     Quick return if possible.
00336 *
00337       IF( M.EQ.N .OR. M.EQ.0 ) THEN
00338          IF( WANTS )
00339      $      S = ONE
00340          IF( WANTSP )
00341      $      SEP = SLANGE( '1', N, N, T, LDT, WORK )
00342          GO TO 40
00343       END IF
00344 *
00345 *     Collect the selected blocks at the top-left corner of T.
00346 *
00347       KS = 0
00348       PAIR = .FALSE.
00349       DO 20 K = 1, N
00350          IF( PAIR ) THEN
00351             PAIR = .FALSE.
00352          ELSE
00353             SWAP = SELECT( K )
00354             IF( K.LT.N ) THEN
00355                IF( T( K+1, K ).NE.ZERO ) THEN
00356                   PAIR = .TRUE.
00357                   SWAP = SWAP .OR. SELECT( K+1 )
00358                END IF
00359             END IF
00360             IF( SWAP ) THEN
00361                KS = KS + 1
00362 *
00363 *              Swap the K-th block to position KS.
00364 *
00365                IERR = 0
00366                KK = K
00367                IF( K.NE.KS )
00368      $            CALL STREXC( COMPQ, N, T, LDT, Q, LDQ, KK, KS, WORK,
00369      $                         IERR )
00370                IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN
00371 *
00372 *                 Blocks too close to swap: exit.
00373 *
00374                   INFO = 1
00375                   IF( WANTS )
00376      $               S = ZERO
00377                   IF( WANTSP )
00378      $               SEP = ZERO
00379                   GO TO 40
00380                END IF
00381                IF( PAIR )
00382      $            KS = KS + 1
00383             END IF
00384          END IF
00385    20 CONTINUE
00386 *
00387       IF( WANTS ) THEN
00388 *
00389 *        Solve Sylvester equation for R:
00390 *
00391 *           T11*R - R*T22 = scale*T12
00392 *
00393          CALL SLACPY( 'F', N1, N2, T( 1, N1+1 ), LDT, WORK, N1 )
00394          CALL STRSYL( 'N', 'N', -1, N1, N2, T, LDT, T( N1+1, N1+1 ),
00395      $                LDT, WORK, N1, SCALE, IERR )
00396 *
00397 *        Estimate the reciprocal of the condition number of the cluster
00398 *        of eigenvalues.
00399 *
00400          RNORM = SLANGE( 'F', N1, N2, WORK, N1, WORK )
00401          IF( RNORM.EQ.ZERO ) THEN
00402             S = ONE
00403          ELSE
00404             S = SCALE / ( SQRT( SCALE*SCALE / RNORM+RNORM )*
00405      $          SQRT( RNORM ) )
00406          END IF
00407       END IF
00408 *
00409       IF( WANTSP ) THEN
00410 *
00411 *        Estimate sep(T11,T22).
00412 *
00413          EST = ZERO
00414          KASE = 0
00415    30    CONTINUE
00416          CALL SLACN2( NN, WORK( NN+1 ), WORK, IWORK, EST, KASE, ISAVE )
00417          IF( KASE.NE.0 ) THEN
00418             IF( KASE.EQ.1 ) THEN
00419 *
00420 *              Solve  T11*R - R*T22 = scale*X.
00421 *
00422                CALL STRSYL( 'N', 'N', -1, N1, N2, T, LDT,
00423      $                      T( N1+1, N1+1 ), LDT, WORK, N1, SCALE,
00424      $                      IERR )
00425             ELSE
00426 *
00427 *              Solve  T11'*R - R*T22' = scale*X.
00428 *
00429                CALL STRSYL( 'T', 'T', -1, N1, N2, T, LDT,
00430      $                      T( N1+1, N1+1 ), LDT, WORK, N1, SCALE,
00431      $                      IERR )
00432             END IF
00433             GO TO 30
00434          END IF
00435 *
00436          SEP = SCALE / EST
00437       END IF
00438 *
00439    40 CONTINUE
00440 *
00441 *     Store the output eigenvalues in WR and WI.
00442 *
00443       DO 50 K = 1, N
00444          WR( K ) = T( K, K )
00445          WI( K ) = ZERO
00446    50 CONTINUE
00447       DO 60 K = 1, N - 1
00448          IF( T( K+1, K ).NE.ZERO ) THEN
00449             WI( K ) = SQRT( ABS( T( K, K+1 ) ) )*
00450      $                SQRT( ABS( T( K+1, K ) ) )
00451             WI( K+1 ) = -WI( K )
00452          END IF
00453    60 CONTINUE
00454 *
00455       WORK( 1 ) = LWMIN
00456       IWORK( 1 ) = LIWMIN
00457 *
00458       RETURN
00459 *
00460 *     End of STRSEN
00461 *
00462       END
 All Files Functions