LAPACK 3.3.0

dgees.f

Go to the documentation of this file.
00001       SUBROUTINE DGEES( JOBVS, SORT, SELECT, N, A, LDA, SDIM, WR, WI,
00002      $                  VS, LDVS, WORK, LWORK, BWORK, INFO )
00003 *
00004 *  -- LAPACK driver 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 *     .. Scalar Arguments ..
00010       CHARACTER          JOBVS, SORT
00011       INTEGER            INFO, LDA, LDVS, LWORK, N, SDIM
00012 *     ..
00013 *     .. Array Arguments ..
00014       LOGICAL            BWORK( * )
00015       DOUBLE PRECISION   A( LDA, * ), VS( LDVS, * ), WI( * ), WORK( * ),
00016      $                   WR( * )
00017 *     ..
00018 *     .. Function Arguments ..
00019       LOGICAL            SELECT
00020       EXTERNAL           SELECT
00021 *     ..
00022 *
00023 *  Purpose
00024 *  =======
00025 *
00026 *  DGEES computes for an N-by-N real nonsymmetric matrix A, the
00027 *  eigenvalues, the real Schur form T, and, optionally, the matrix of
00028 *  Schur vectors Z.  This gives the Schur factorization A = Z*T*(Z**T).
00029 *
00030 *  Optionally, it also orders the eigenvalues on the diagonal of the
00031 *  real Schur form so that selected eigenvalues are at the top left.
00032 *  The leading columns of Z then form an orthonormal basis for the
00033 *  invariant subspace corresponding to the selected eigenvalues.
00034 *
00035 *  A matrix is in real Schur form if it is upper quasi-triangular with
00036 *  1-by-1 and 2-by-2 blocks. 2-by-2 blocks will be standardized in the
00037 *  form
00038 *          [  a  b  ]
00039 *          [  c  a  ]
00040 *
00041 *  where b*c < 0. The eigenvalues of such a block are a +- sqrt(bc).
00042 *
00043 *  Arguments
00044 *  =========
00045 *
00046 *  JOBVS   (input) CHARACTER*1
00047 *          = 'N': Schur vectors are not computed;
00048 *          = 'V': Schur vectors are computed.
00049 *
00050 *  SORT    (input) CHARACTER*1
00051 *          Specifies whether or not to order the eigenvalues on the
00052 *          diagonal of the Schur form.
00053 *          = 'N': Eigenvalues are not ordered;
00054 *          = 'S': Eigenvalues are ordered (see SELECT).
00055 *
00056 *  SELECT  (external procedure) LOGICAL FUNCTION of two DOUBLE PRECISION arguments
00057 *          SELECT must be declared EXTERNAL in the calling subroutine.
00058 *          If SORT = 'S', SELECT is used to select eigenvalues to sort
00059 *          to the top left of the Schur form.
00060 *          If SORT = 'N', SELECT is not referenced.
00061 *          An eigenvalue WR(j)+sqrt(-1)*WI(j) is selected if
00062 *          SELECT(WR(j),WI(j)) is true; i.e., if either one of a complex
00063 *          conjugate pair of eigenvalues is selected, then both complex
00064 *          eigenvalues are selected.
00065 *          Note that a selected complex eigenvalue may no longer
00066 *          satisfy SELECT(WR(j),WI(j)) = .TRUE. after ordering, since
00067 *          ordering may change the value of complex eigenvalues
00068 *          (especially if the eigenvalue is ill-conditioned); in this
00069 *          case INFO is set to N+2 (see INFO below).
00070 *
00071 *  N       (input) INTEGER
00072 *          The order of the matrix A. N >= 0.
00073 *
00074 *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
00075 *          On entry, the N-by-N matrix A.
00076 *          On exit, A has been overwritten by its real Schur form T.
00077 *
00078 *  LDA     (input) INTEGER
00079 *          The leading dimension of the array A.  LDA >= max(1,N).
00080 *
00081 *  SDIM    (output) INTEGER
00082 *          If SORT = 'N', SDIM = 0.
00083 *          If SORT = 'S', SDIM = number of eigenvalues (after sorting)
00084 *                         for which SELECT is true. (Complex conjugate
00085 *                         pairs for which SELECT is true for either
00086 *                         eigenvalue count as 2.)
00087 *
00088 *  WR      (output) DOUBLE PRECISION array, dimension (N)
00089 *  WI      (output) DOUBLE PRECISION array, dimension (N)
00090 *          WR and WI contain the real and imaginary parts,
00091 *          respectively, of the computed eigenvalues in the same order
00092 *          that they appear on the diagonal of the output Schur form T.
00093 *          Complex conjugate pairs of eigenvalues will appear
00094 *          consecutively with the eigenvalue having the positive
00095 *          imaginary part first.
00096 *
00097 *  VS      (output) DOUBLE PRECISION array, dimension (LDVS,N)
00098 *          If JOBVS = 'V', VS contains the orthogonal matrix Z of Schur
00099 *          vectors.
00100 *          If JOBVS = 'N', VS is not referenced.
00101 *
00102 *  LDVS    (input) INTEGER
00103 *          The leading dimension of the array VS.  LDVS >= 1; if
00104 *          JOBVS = 'V', LDVS >= N.
00105 *
00106 *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
00107 *          On exit, if INFO = 0, WORK(1) contains the optimal LWORK.
00108 *
00109 *  LWORK   (input) INTEGER
00110 *          The dimension of the array WORK.  LWORK >= max(1,3*N).
00111 *          For good performance, LWORK must generally be larger.
00112 *
00113 *          If LWORK = -1, then a workspace query is assumed; the routine
00114 *          only calculates the optimal size of the WORK array, returns
00115 *          this value as the first entry of the WORK array, and no error
00116 *          message related to LWORK is issued by XERBLA.
00117 *
00118 *  BWORK   (workspace) LOGICAL array, dimension (N)
00119 *          Not referenced if SORT = 'N'.
00120 *
00121 *  INFO    (output) INTEGER
00122 *          = 0: successful exit
00123 *          < 0: if INFO = -i, the i-th argument had an illegal value.
00124 *          > 0: if INFO = i, and i is
00125 *             <= N: the QR algorithm failed to compute all the
00126 *                   eigenvalues; elements 1:ILO-1 and i+1:N of WR and WI
00127 *                   contain those eigenvalues which have converged; if
00128 *                   JOBVS = 'V', VS contains the matrix which reduces A
00129 *                   to its partially converged Schur form.
00130 *             = N+1: the eigenvalues could not be reordered because some
00131 *                   eigenvalues were too close to separate (the problem
00132 *                   is very ill-conditioned);
00133 *             = N+2: after reordering, roundoff changed values of some
00134 *                   complex eigenvalues so that leading eigenvalues in
00135 *                   the Schur form no longer satisfy SELECT=.TRUE.  This
00136 *                   could also be caused by underflow due to scaling.
00137 *
00138 *  =====================================================================
00139 *
00140 *     .. Parameters ..
00141       DOUBLE PRECISION   ZERO, ONE
00142       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )
00143 *     ..
00144 *     .. Local Scalars ..
00145       LOGICAL            CURSL, LASTSL, LQUERY, LST2SL, SCALEA, WANTST,
00146      $                   WANTVS
00147       INTEGER            HSWORK, I, I1, I2, IBAL, ICOND, IERR, IEVAL,
00148      $                   IHI, ILO, INXT, IP, ITAU, IWRK, MAXWRK, MINWRK
00149       DOUBLE PRECISION   ANRM, BIGNUM, CSCALE, EPS, S, SEP, SMLNUM
00150 *     ..
00151 *     .. Local Arrays ..
00152       INTEGER            IDUM( 1 )
00153       DOUBLE PRECISION   DUM( 1 )
00154 *     ..
00155 *     .. External Subroutines ..
00156       EXTERNAL           DCOPY, DGEBAK, DGEBAL, DGEHRD, DHSEQR, DLACPY,
00157      $                   DLABAD, DLASCL, DORGHR, DSWAP, DTRSEN, XERBLA
00158 *     ..
00159 *     .. External Functions ..
00160       LOGICAL            LSAME
00161       INTEGER            ILAENV
00162       DOUBLE PRECISION   DLAMCH, DLANGE
00163       EXTERNAL           LSAME, ILAENV, DLAMCH, DLANGE
00164 *     ..
00165 *     .. Intrinsic Functions ..
00166       INTRINSIC          MAX, SQRT
00167 *     ..
00168 *     .. Executable Statements ..
00169 *
00170 *     Test the input arguments
00171 *
00172       INFO = 0
00173       LQUERY = ( LWORK.EQ.-1 )
00174       WANTVS = LSAME( JOBVS, 'V' )
00175       WANTST = LSAME( SORT, 'S' )
00176       IF( ( .NOT.WANTVS ) .AND. ( .NOT.LSAME( JOBVS, 'N' ) ) ) THEN
00177          INFO = -1
00178       ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
00179          INFO = -2
00180       ELSE IF( N.LT.0 ) THEN
00181          INFO = -4
00182       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00183          INFO = -6
00184       ELSE IF( LDVS.LT.1 .OR. ( WANTVS .AND. LDVS.LT.N ) ) THEN
00185          INFO = -11
00186       END IF
00187 *
00188 *     Compute workspace
00189 *      (Note: Comments in the code beginning "Workspace:" describe the
00190 *       minimal amount of workspace needed at that point in the code,
00191 *       as well as the preferred amount for good performance.
00192 *       NB refers to the optimal block size for the immediately
00193 *       following subroutine, as returned by ILAENV.
00194 *       HSWORK refers to the workspace preferred by DHSEQR, as
00195 *       calculated below. HSWORK is computed assuming ILO=1 and IHI=N,
00196 *       the worst case.)
00197 *
00198       IF( INFO.EQ.0 ) THEN
00199          IF( N.EQ.0 ) THEN
00200             MINWRK = 1
00201             MAXWRK = 1
00202          ELSE
00203             MAXWRK = 2*N + N*ILAENV( 1, 'DGEHRD', ' ', N, 1, N, 0 )
00204             MINWRK = 3*N
00205 *
00206             CALL DHSEQR( 'S', JOBVS, N, 1, N, A, LDA, WR, WI, VS, LDVS,
00207      $             WORK, -1, IEVAL )
00208             HSWORK = WORK( 1 )
00209 *
00210             IF( .NOT.WANTVS ) THEN
00211                MAXWRK = MAX( MAXWRK, N + HSWORK )
00212             ELSE
00213                MAXWRK = MAX( MAXWRK, 2*N + ( N - 1 )*ILAENV( 1,
00214      $                       'DORGHR', ' ', N, 1, N, -1 ) )
00215                MAXWRK = MAX( MAXWRK, N + HSWORK )
00216             END IF
00217          END IF
00218          WORK( 1 ) = MAXWRK
00219 *
00220          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
00221             INFO = -13
00222          END IF
00223       END IF
00224 *
00225       IF( INFO.NE.0 ) THEN
00226          CALL XERBLA( 'DGEES ', -INFO )
00227          RETURN
00228       ELSE IF( LQUERY ) THEN
00229          RETURN
00230       END IF
00231 *
00232 *     Quick return if possible
00233 *
00234       IF( N.EQ.0 ) THEN
00235          SDIM = 0
00236          RETURN
00237       END IF
00238 *
00239 *     Get machine constants
00240 *
00241       EPS = DLAMCH( 'P' )
00242       SMLNUM = DLAMCH( 'S' )
00243       BIGNUM = ONE / SMLNUM
00244       CALL DLABAD( SMLNUM, BIGNUM )
00245       SMLNUM = SQRT( SMLNUM ) / EPS
00246       BIGNUM = ONE / SMLNUM
00247 *
00248 *     Scale A if max element outside range [SMLNUM,BIGNUM]
00249 *
00250       ANRM = DLANGE( 'M', N, N, A, LDA, DUM )
00251       SCALEA = .FALSE.
00252       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
00253          SCALEA = .TRUE.
00254          CSCALE = SMLNUM
00255       ELSE IF( ANRM.GT.BIGNUM ) THEN
00256          SCALEA = .TRUE.
00257          CSCALE = BIGNUM
00258       END IF
00259       IF( SCALEA )
00260      $   CALL DLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
00261 *
00262 *     Permute the matrix to make it more nearly triangular
00263 *     (Workspace: need N)
00264 *
00265       IBAL = 1
00266       CALL DGEBAL( 'P', N, A, LDA, ILO, IHI, WORK( IBAL ), IERR )
00267 *
00268 *     Reduce to upper Hessenberg form
00269 *     (Workspace: need 3*N, prefer 2*N+N*NB)
00270 *
00271       ITAU = N + IBAL
00272       IWRK = N + ITAU
00273       CALL DGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
00274      $             LWORK-IWRK+1, IERR )
00275 *
00276       IF( WANTVS ) THEN
00277 *
00278 *        Copy Householder vectors to VS
00279 *
00280          CALL DLACPY( 'L', N, N, A, LDA, VS, LDVS )
00281 *
00282 *        Generate orthogonal matrix in VS
00283 *        (Workspace: need 3*N-1, prefer 2*N+(N-1)*NB)
00284 *
00285          CALL DORGHR( N, ILO, IHI, VS, LDVS, WORK( ITAU ), WORK( IWRK ),
00286      $                LWORK-IWRK+1, IERR )
00287       END IF
00288 *
00289       SDIM = 0
00290 *
00291 *     Perform QR iteration, accumulating Schur vectors in VS if desired
00292 *     (Workspace: need N+1, prefer N+HSWORK (see comments) )
00293 *
00294       IWRK = ITAU
00295       CALL DHSEQR( 'S', JOBVS, N, ILO, IHI, A, LDA, WR, WI, VS, LDVS,
00296      $             WORK( IWRK ), LWORK-IWRK+1, IEVAL )
00297       IF( IEVAL.GT.0 )
00298      $   INFO = IEVAL
00299 *
00300 *     Sort eigenvalues if desired
00301 *
00302       IF( WANTST .AND. INFO.EQ.0 ) THEN
00303          IF( SCALEA ) THEN
00304             CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, WR, N, IERR )
00305             CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, WI, N, IERR )
00306          END IF
00307          DO 10 I = 1, N
00308             BWORK( I ) = SELECT( WR( I ), WI( I ) )
00309    10    CONTINUE
00310 *
00311 *        Reorder eigenvalues and transform Schur vectors
00312 *        (Workspace: none needed)
00313 *
00314          CALL DTRSEN( 'N', JOBVS, BWORK, N, A, LDA, VS, LDVS, WR, WI,
00315      $                SDIM, S, SEP, WORK( IWRK ), LWORK-IWRK+1, IDUM, 1,
00316      $                ICOND )
00317          IF( ICOND.GT.0 )
00318      $      INFO = N + ICOND
00319       END IF
00320 *
00321       IF( WANTVS ) THEN
00322 *
00323 *        Undo balancing
00324 *        (Workspace: need N)
00325 *
00326          CALL DGEBAK( 'P', 'R', N, ILO, IHI, WORK( IBAL ), N, VS, LDVS,
00327      $                IERR )
00328       END IF
00329 *
00330       IF( SCALEA ) THEN
00331 *
00332 *        Undo scaling for the Schur form of A
00333 *
00334          CALL DLASCL( 'H', 0, 0, CSCALE, ANRM, N, N, A, LDA, IERR )
00335          CALL DCOPY( N, A, LDA+1, WR, 1 )
00336          IF( CSCALE.EQ.SMLNUM ) THEN
00337 *
00338 *           If scaling back towards underflow, adjust WI if an
00339 *           offdiagonal element of a 2-by-2 block in the Schur form
00340 *           underflows.
00341 *
00342             IF( IEVAL.GT.0 ) THEN
00343                I1 = IEVAL + 1
00344                I2 = IHI - 1
00345                CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, ILO-1, 1, WI,
00346      $                      MAX( ILO-1, 1 ), IERR )
00347             ELSE IF( WANTST ) THEN
00348                I1 = 1
00349                I2 = N - 1
00350             ELSE
00351                I1 = ILO
00352                I2 = IHI - 1
00353             END IF
00354             INXT = I1 - 1
00355             DO 20 I = I1, I2
00356                IF( I.LT.INXT )
00357      $            GO TO 20
00358                IF( WI( I ).EQ.ZERO ) THEN
00359                   INXT = I + 1
00360                ELSE
00361                   IF( A( I+1, I ).EQ.ZERO ) THEN
00362                      WI( I ) = ZERO
00363                      WI( I+1 ) = ZERO
00364                   ELSE IF( A( I+1, I ).NE.ZERO .AND. A( I, I+1 ).EQ.
00365      $                     ZERO ) THEN
00366                      WI( I ) = ZERO
00367                      WI( I+1 ) = ZERO
00368                      IF( I.GT.1 )
00369      $                  CALL DSWAP( I-1, A( 1, I ), 1, A( 1, I+1 ), 1 )
00370                      IF( N.GT.I+1 )
00371      $                  CALL DSWAP( N-I-1, A( I, I+2 ), LDA,
00372      $                              A( I+1, I+2 ), LDA )
00373                      IF( WANTVS ) THEN
00374                         CALL DSWAP( N, VS( 1, I ), 1, VS( 1, I+1 ), 1 )
00375                      END IF
00376                      A( I, I+1 ) = A( I+1, I )
00377                      A( I+1, I ) = ZERO
00378                   END IF
00379                   INXT = I + 2
00380                END IF
00381    20       CONTINUE
00382          END IF
00383 *
00384 *        Undo scaling for the imaginary part of the eigenvalues
00385 *
00386          CALL DLASCL( 'G', 0, 0, CSCALE, ANRM, N-IEVAL, 1,
00387      $                WI( IEVAL+1 ), MAX( N-IEVAL, 1 ), IERR )
00388       END IF
00389 *
00390       IF( WANTST .AND. INFO.EQ.0 ) THEN
00391 *
00392 *        Check if reordering successful
00393 *
00394          LASTSL = .TRUE.
00395          LST2SL = .TRUE.
00396          SDIM = 0
00397          IP = 0
00398          DO 30 I = 1, N
00399             CURSL = SELECT( WR( I ), WI( I ) )
00400             IF( WI( I ).EQ.ZERO ) THEN
00401                IF( CURSL )
00402      $            SDIM = SDIM + 1
00403                IP = 0
00404                IF( CURSL .AND. .NOT.LASTSL )
00405      $            INFO = N + 2
00406             ELSE
00407                IF( IP.EQ.1 ) THEN
00408 *
00409 *                 Last eigenvalue of conjugate pair
00410 *
00411                   CURSL = CURSL .OR. LASTSL
00412                   LASTSL = CURSL
00413                   IF( CURSL )
00414      $               SDIM = SDIM + 2
00415                   IP = -1
00416                   IF( CURSL .AND. .NOT.LST2SL )
00417      $               INFO = N + 2
00418                ELSE
00419 *
00420 *                 First eigenvalue of conjugate pair
00421 *
00422                   IP = 1
00423                END IF
00424             END IF
00425             LST2SL = LASTSL
00426             LASTSL = CURSL
00427    30    CONTINUE
00428       END IF
00429 *
00430       WORK( 1 ) = MAXWRK
00431       RETURN
00432 *
00433 *     End of DGEES
00434 *
00435       END
 All Files Functions