LAPACK 3.3.0

dtgexc.f

Go to the documentation of this file.
00001       SUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00002      $                   LDZ, IFST, ILST, WORK, LWORK, INFO )
00003 *
00004 *  -- LAPACK routine (version 3.2.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 *     June 2010
00008 *
00009 *     .. Scalar Arguments ..
00010       LOGICAL            WANTQ, WANTZ
00011       INTEGER            IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N
00012 *     ..
00013 *     .. Array Arguments ..
00014       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
00015      $                   WORK( * ), Z( LDZ, * )
00016 *     ..
00017 *
00018 *  Purpose
00019 *  =======
00020 *
00021 *  DTGEXC reorders the generalized real Schur decomposition of a real
00022 *  matrix pair (A,B) using an orthogonal equivalence transformation
00023 *
00024 *                 (A, B) = Q * (A, B) * Z',
00025 *
00026 *  so that the diagonal block of (A, B) with row index IFST is moved
00027 *  to row ILST.
00028 *
00029 *  (A, B) must be in generalized real Schur canonical form (as returned
00030 *  by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2
00031 *  diagonal blocks. B is upper triangular.
00032 *
00033 *  Optionally, the matrices Q and Z of generalized Schur vectors are
00034 *  updated.
00035 *
00036 *         Q(in) * A(in) * Z(in)' = Q(out) * A(out) * Z(out)'
00037 *         Q(in) * B(in) * Z(in)' = Q(out) * B(out) * Z(out)'
00038 *
00039 *
00040 *  Arguments
00041 *  =========
00042 *
00043 *  WANTQ   (input) LOGICAL
00044 *          .TRUE. : update the left transformation matrix Q;
00045 *          .FALSE.: do not update Q.
00046 *
00047 *  WANTZ   (input) LOGICAL
00048 *          .TRUE. : update the right transformation matrix Z;
00049 *          .FALSE.: do not update Z.
00050 *
00051 *  N       (input) INTEGER
00052 *          The order of the matrices A and B. N >= 0.
00053 *
00054 *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
00055 *          On entry, the matrix A in generalized real Schur canonical
00056 *          form.
00057 *          On exit, the updated matrix A, again in generalized
00058 *          real Schur canonical form.
00059 *
00060 *  LDA     (input) INTEGER
00061 *          The leading dimension of the array A. LDA >= max(1,N).
00062 *
00063 *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
00064 *          On entry, the matrix B in generalized real Schur canonical
00065 *          form (A,B).
00066 *          On exit, the updated matrix B, again in generalized
00067 *          real Schur canonical form (A,B).
00068 *
00069 *  LDB     (input) INTEGER
00070 *          The leading dimension of the array B. LDB >= max(1,N).
00071 *
00072 *  Q       (input/output) DOUBLE PRECISION array, dimension (LDQ,N)
00073 *          On entry, if WANTQ = .TRUE., the orthogonal matrix Q.
00074 *          On exit, the updated matrix Q.
00075 *          If WANTQ = .FALSE., Q is not referenced.
00076 *
00077 *  LDQ     (input) INTEGER
00078 *          The leading dimension of the array Q. LDQ >= 1.
00079 *          If WANTQ = .TRUE., LDQ >= N.
00080 *
00081 *  Z       (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
00082 *          On entry, if WANTZ = .TRUE., the orthogonal matrix Z.
00083 *          On exit, the updated matrix Z.
00084 *          If WANTZ = .FALSE., Z is not referenced.
00085 *
00086 *  LDZ     (input) INTEGER
00087 *          The leading dimension of the array Z. LDZ >= 1.
00088 *          If WANTZ = .TRUE., LDZ >= N.
00089 *
00090 *  IFST    (input/output) INTEGER
00091 *  ILST    (input/output) INTEGER
00092 *          Specify the reordering of the diagonal blocks of (A, B).
00093 *          The block with row index IFST is moved to row ILST, by a
00094 *          sequence of swapping between adjacent blocks.
00095 *          On exit, if IFST pointed on entry to the second row of
00096 *          a 2-by-2 block, it is changed to point to the first row;
00097 *          ILST always points to the first row of the block in its
00098 *          final position (which may differ from its input value by
00099 *          +1 or -1). 1 <= IFST, ILST <= N.
00100 *
00101 *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
00102 *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
00103 *
00104 *  LWORK   (input) INTEGER
00105 *          The dimension of the array WORK.
00106 *          LWORK >= 1 when N <= 1, otherwise LWORK >= 4*N + 16.
00107 *
00108 *          If LWORK = -1, then a workspace query is assumed; the routine
00109 *          only calculates the optimal size of the WORK array, returns
00110 *          this value as the first entry of the WORK array, and no error
00111 *          message related to LWORK is issued by XERBLA.
00112 *
00113 *  INFO    (output) INTEGER
00114 *           =0:  successful exit.
00115 *           <0:  if INFO = -i, the i-th argument had an illegal value.
00116 *           =1:  The transformed matrix pair (A, B) would be too far
00117 *                from generalized Schur form; the problem is ill-
00118 *                conditioned. (A, B) may have been partially reordered,
00119 *                and ILST points to the first row of the current
00120 *                position of the block being moved.
00121 *
00122 *  Further Details
00123 *  ===============
00124 *
00125 *  Based on contributions by
00126 *     Bo Kagstrom and Peter Poromaa, Department of Computing Science,
00127 *     Umea University, S-901 87 Umea, Sweden.
00128 *
00129 *  [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the
00130 *      Generalized Real Schur Form of a Regular Matrix Pair (A, B), in
00131 *      M.S. Moonen et al (eds), Linear Algebra for Large Scale and
00132 *      Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.
00133 *
00134 *  =====================================================================
00135 *
00136 *     .. Parameters ..
00137       DOUBLE PRECISION   ZERO
00138       PARAMETER          ( ZERO = 0.0D+0 )
00139 *     ..
00140 *     .. Local Scalars ..
00141       LOGICAL            LQUERY
00142       INTEGER            HERE, LWMIN, NBF, NBL, NBNEXT
00143 *     ..
00144 *     .. External Subroutines ..
00145       EXTERNAL           DTGEX2, XERBLA
00146 *     ..
00147 *     .. Intrinsic Functions ..
00148       INTRINSIC          MAX
00149 *     ..
00150 *     .. Executable Statements ..
00151 *
00152 *     Decode and test input arguments.
00153 *
00154       INFO = 0
00155       LQUERY = ( LWORK.EQ.-1 )
00156       IF( N.LT.0 ) THEN
00157          INFO = -3
00158       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
00159          INFO = -5
00160       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
00161          INFO = -7
00162       ELSE IF( LDQ.LT.1 .OR. WANTQ .AND. ( LDQ.LT.MAX( 1, N ) ) ) THEN
00163          INFO = -9
00164       ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. ( LDZ.LT.MAX( 1, N ) ) ) THEN
00165          INFO = -11
00166       ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN
00167          INFO = -12
00168       ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN
00169          INFO = -13
00170       END IF
00171 *
00172       IF( INFO.EQ.0 ) THEN
00173          IF( N.LE.1 ) THEN
00174             LWMIN = 1
00175          ELSE
00176             LWMIN = 4*N + 16
00177          END IF
00178          WORK(1) = LWMIN
00179 *
00180          IF (LWORK.LT.LWMIN .AND. .NOT.LQUERY) THEN
00181             INFO = -15
00182          END IF
00183       END IF
00184 *
00185       IF( INFO.NE.0 ) THEN
00186          CALL XERBLA( 'DTGEXC', -INFO )
00187          RETURN
00188       ELSE IF( LQUERY ) THEN
00189          RETURN
00190       END IF
00191 *
00192 *     Quick return if possible
00193 *
00194       IF( N.LE.1 )
00195      $   RETURN
00196 *
00197 *     Determine the first row of the specified block and find out
00198 *     if it is 1-by-1 or 2-by-2.
00199 *
00200       IF( IFST.GT.1 ) THEN
00201          IF( A( IFST, IFST-1 ).NE.ZERO )
00202      $      IFST = IFST - 1
00203       END IF
00204       NBF = 1
00205       IF( IFST.LT.N ) THEN
00206          IF( A( IFST+1, IFST ).NE.ZERO )
00207      $      NBF = 2
00208       END IF
00209 *
00210 *     Determine the first row of the final block
00211 *     and find out if it is 1-by-1 or 2-by-2.
00212 *
00213       IF( ILST.GT.1 ) THEN
00214          IF( A( ILST, ILST-1 ).NE.ZERO )
00215      $      ILST = ILST - 1
00216       END IF
00217       NBL = 1
00218       IF( ILST.LT.N ) THEN
00219          IF( A( ILST+1, ILST ).NE.ZERO )
00220      $      NBL = 2
00221       END IF
00222       IF( IFST.EQ.ILST )
00223      $   RETURN
00224 *
00225       IF( IFST.LT.ILST ) THEN
00226 *
00227 *        Update ILST.
00228 *
00229          IF( NBF.EQ.2 .AND. NBL.EQ.1 )
00230      $      ILST = ILST - 1
00231          IF( NBF.EQ.1 .AND. NBL.EQ.2 )
00232      $      ILST = ILST + 1
00233 *
00234          HERE = IFST
00235 *
00236    10    CONTINUE
00237 *
00238 *        Swap with next one below.
00239 *
00240          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
00241 *
00242 *           Current block either 1-by-1 or 2-by-2.
00243 *
00244             NBNEXT = 1
00245             IF( HERE+NBF+1.LE.N ) THEN
00246                IF( A( HERE+NBF+1, HERE+NBF ).NE.ZERO )
00247      $            NBNEXT = 2
00248             END IF
00249             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00250      $                   LDZ, HERE, NBF, NBNEXT, WORK, LWORK, INFO )
00251             IF( INFO.NE.0 ) THEN
00252                ILST = HERE
00253                RETURN
00254             END IF
00255             HERE = HERE + NBNEXT
00256 *
00257 *           Test if 2-by-2 block breaks into two 1-by-1 blocks.
00258 *
00259             IF( NBF.EQ.2 ) THEN
00260                IF( A( HERE+1, HERE ).EQ.ZERO )
00261      $            NBF = 3
00262             END IF
00263 *
00264          ELSE
00265 *
00266 *           Current block consists of two 1-by-1 blocks, each of which
00267 *           must be swapped individually.
00268 *
00269             NBNEXT = 1
00270             IF( HERE+3.LE.N ) THEN
00271                IF( A( HERE+3, HERE+2 ).NE.ZERO )
00272      $            NBNEXT = 2
00273             END IF
00274             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00275      $                   LDZ, HERE+1, 1, NBNEXT, WORK, LWORK, INFO )
00276             IF( INFO.NE.0 ) THEN
00277                ILST = HERE
00278                RETURN
00279             END IF
00280             IF( NBNEXT.EQ.1 ) THEN
00281 *
00282 *              Swap two 1-by-1 blocks.
00283 *
00284                CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00285      $                      LDZ, HERE, 1, 1, WORK, LWORK, INFO )
00286                IF( INFO.NE.0 ) THEN
00287                   ILST = HERE
00288                   RETURN
00289                END IF
00290                HERE = HERE + 1
00291 *
00292             ELSE
00293 *
00294 *              Recompute NBNEXT in case of 2-by-2 split.
00295 *
00296                IF( A( HERE+2, HERE+1 ).EQ.ZERO )
00297      $            NBNEXT = 1
00298                IF( NBNEXT.EQ.2 ) THEN
00299 *
00300 *                 2-by-2 block did not split.
00301 *
00302                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
00303      $                         Z, LDZ, HERE, 1, NBNEXT, WORK, LWORK,
00304      $                         INFO )
00305                   IF( INFO.NE.0 ) THEN
00306                      ILST = HERE
00307                      RETURN
00308                   END IF
00309                   HERE = HERE + 2
00310                ELSE
00311 *
00312 *                 2-by-2 block did split.
00313 *
00314                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
00315      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
00316                   IF( INFO.NE.0 ) THEN
00317                      ILST = HERE
00318                      RETURN
00319                   END IF
00320                   HERE = HERE + 1
00321                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
00322      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
00323                   IF( INFO.NE.0 ) THEN
00324                      ILST = HERE
00325                      RETURN
00326                   END IF
00327                   HERE = HERE + 1
00328                END IF
00329 *
00330             END IF
00331          END IF
00332          IF( HERE.LT.ILST )
00333      $      GO TO 10
00334       ELSE
00335          HERE = IFST
00336 *
00337    20    CONTINUE
00338 *
00339 *        Swap with next one below.
00340 *
00341          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
00342 *
00343 *           Current block either 1-by-1 or 2-by-2.
00344 *
00345             NBNEXT = 1
00346             IF( HERE.GE.3 ) THEN
00347                IF( A( HERE-1, HERE-2 ).NE.ZERO )
00348      $            NBNEXT = 2
00349             END IF
00350             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00351      $                   LDZ, HERE-NBNEXT, NBNEXT, NBF, WORK, LWORK,
00352      $                   INFO )
00353             IF( INFO.NE.0 ) THEN
00354                ILST = HERE
00355                RETURN
00356             END IF
00357             HERE = HERE - NBNEXT
00358 *
00359 *           Test if 2-by-2 block breaks into two 1-by-1 blocks.
00360 *
00361             IF( NBF.EQ.2 ) THEN
00362                IF( A( HERE+1, HERE ).EQ.ZERO )
00363      $            NBF = 3
00364             END IF
00365 *
00366          ELSE
00367 *
00368 *           Current block consists of two 1-by-1 blocks, each of which
00369 *           must be swapped individually.
00370 *
00371             NBNEXT = 1
00372             IF( HERE.GE.3 ) THEN
00373                IF( A( HERE-1, HERE-2 ).NE.ZERO )
00374      $            NBNEXT = 2
00375             END IF
00376             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00377      $                   LDZ, HERE-NBNEXT, NBNEXT, 1, WORK, LWORK,
00378      $                   INFO )
00379             IF( INFO.NE.0 ) THEN
00380                ILST = HERE
00381                RETURN
00382             END IF
00383             IF( NBNEXT.EQ.1 ) THEN
00384 *
00385 *              Swap two 1-by-1 blocks.
00386 *
00387                CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
00388      $                      LDZ, HERE, NBNEXT, 1, WORK, LWORK, INFO )
00389                IF( INFO.NE.0 ) THEN
00390                   ILST = HERE
00391                   RETURN
00392                END IF
00393                HERE = HERE - 1
00394             ELSE
00395 *
00396 *             Recompute NBNEXT in case of 2-by-2 split.
00397 *
00398                IF( A( HERE, HERE-1 ).EQ.ZERO )
00399      $            NBNEXT = 1
00400                IF( NBNEXT.EQ.2 ) THEN
00401 *
00402 *                 2-by-2 block did not split.
00403 *
00404                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
00405      $                         Z, LDZ, HERE-1, 2, 1, WORK, LWORK, INFO )
00406                   IF( INFO.NE.0 ) THEN
00407                      ILST = HERE
00408                      RETURN
00409                   END IF
00410                   HERE = HERE - 2
00411                ELSE
00412 *
00413 *                 2-by-2 block did split.
00414 *
00415                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
00416      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
00417                   IF( INFO.NE.0 ) THEN
00418                      ILST = HERE
00419                      RETURN
00420                   END IF
00421                   HERE = HERE - 1
00422                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
00423      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
00424                   IF( INFO.NE.0 ) THEN
00425                      ILST = HERE
00426                      RETURN
00427                   END IF
00428                   HERE = HERE - 1
00429                END IF
00430             END IF
00431          END IF
00432          IF( HERE.GT.ILST )
00433      $      GO TO 20
00434       END IF
00435       ILST = HERE
00436       WORK( 1 ) = LWMIN
00437       RETURN
00438 *
00439 *     End of DTGEXC
00440 *
00441       END
 All Files Functions