Annotation of rpl/lapack/lapack/dtgexc.f, revision 1.1

1.1     ! bertrand    1:       SUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !             2:      $                   LDZ, IFST, ILST, WORK, LWORK, INFO )
        !             3: *
        !             4: *  -- LAPACK routine (version 3.2) --
        !             5: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
        !             6: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
        !             7: *     November 2006
        !             8: *
        !             9: *     .. Scalar Arguments ..
        !            10:       LOGICAL            WANTQ, WANTZ
        !            11:       INTEGER            IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N
        !            12: *     ..
        !            13: *     .. Array Arguments ..
        !            14:       DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
        !            15:      $                   WORK( * ), Z( LDZ, * )
        !            16: *     ..
        !            17: *
        !            18: *  Purpose
        !            19: *  =======
        !            20: *
        !            21: *  DTGEXC reorders the generalized real Schur decomposition of a real
        !            22: *  matrix pair (A,B) using an orthogonal equivalence transformation
        !            23: *
        !            24: *                 (A, B) = Q * (A, B) * Z',
        !            25: *
        !            26: *  so that the diagonal block of (A, B) with row index IFST is moved
        !            27: *  to row ILST.
        !            28: *
        !            29: *  (A, B) must be in generalized real Schur canonical form (as returned
        !            30: *  by DGGES), i.e. A is block upper triangular with 1-by-1 and 2-by-2
        !            31: *  diagonal blocks. B is upper triangular.
        !            32: *
        !            33: *  Optionally, the matrices Q and Z of generalized Schur vectors are
        !            34: *  updated.
        !            35: *
        !            36: *         Q(in) * A(in) * Z(in)' = Q(out) * A(out) * Z(out)'
        !            37: *         Q(in) * B(in) * Z(in)' = Q(out) * B(out) * Z(out)'
        !            38: *
        !            39: *
        !            40: *  Arguments
        !            41: *  =========
        !            42: *
        !            43: *  WANTQ   (input) LOGICAL
        !            44: *          .TRUE. : update the left transformation matrix Q;
        !            45: *          .FALSE.: do not update Q.
        !            46: *
        !            47: *  WANTZ   (input) LOGICAL
        !            48: *          .TRUE. : update the right transformation matrix Z;
        !            49: *          .FALSE.: do not update Z.
        !            50: *
        !            51: *  N       (input) INTEGER
        !            52: *          The order of the matrices A and B. N >= 0.
        !            53: *
        !            54: *  A       (input/output) DOUBLE PRECISION array, dimension (LDA,N)
        !            55: *          On entry, the matrix A in generalized real Schur canonical
        !            56: *          form.
        !            57: *          On exit, the updated matrix A, again in generalized
        !            58: *          real Schur canonical form.
        !            59: *
        !            60: *  LDA     (input)  INTEGER
        !            61: *          The leading dimension of the array A. LDA >= max(1,N).
        !            62: *
        !            63: *  B       (input/output) DOUBLE PRECISION array, dimension (LDB,N)
        !            64: *          On entry, the matrix B in generalized real Schur canonical
        !            65: *          form (A,B).
        !            66: *          On exit, the updated matrix B, again in generalized
        !            67: *          real Schur canonical form (A,B).
        !            68: *
        !            69: *  LDB     (input)  INTEGER
        !            70: *          The leading dimension of the array B. LDB >= max(1,N).
        !            71: *
        !            72: *  Q       (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
        !            73: *          On entry, if WANTQ = .TRUE., the orthogonal matrix Q.
        !            74: *          On exit, the updated matrix Q.
        !            75: *          If WANTQ = .FALSE., Q is not referenced.
        !            76: *
        !            77: *  LDQ     (input) INTEGER
        !            78: *          The leading dimension of the array Q. LDQ >= 1.
        !            79: *          If WANTQ = .TRUE., LDQ >= N.
        !            80: *
        !            81: *  Z       (input/output) DOUBLE PRECISION array, dimension (LDZ,N)
        !            82: *          On entry, if WANTZ = .TRUE., the orthogonal matrix Z.
        !            83: *          On exit, the updated matrix Z.
        !            84: *          If WANTZ = .FALSE., Z is not referenced.
        !            85: *
        !            86: *  LDZ     (input) INTEGER
        !            87: *          The leading dimension of the array Z. LDZ >= 1.
        !            88: *          If WANTZ = .TRUE., LDZ >= N.
        !            89: *
        !            90: *  IFST    (input/output) INTEGER
        !            91: *  ILST    (input/output) INTEGER
        !            92: *          Specify the reordering of the diagonal blocks of (A, B).
        !            93: *          The block with row index IFST is moved to row ILST, by a
        !            94: *          sequence of swapping between adjacent blocks.
        !            95: *          On exit, if IFST pointed on entry to the second row of
        !            96: *          a 2-by-2 block, it is changed to point to the first row;
        !            97: *          ILST always points to the first row of the block in its
        !            98: *          final position (which may differ from its input value by
        !            99: *          +1 or -1). 1 <= IFST, ILST <= N.
        !           100: *
        !           101: *  WORK    (workspace/output) DOUBLE PRECISION array, dimension (MAX(1,LWORK))
        !           102: *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
        !           103: *
        !           104: *  LWORK   (input) INTEGER
        !           105: *          The dimension of the array WORK.
        !           106: *          LWORK >= 1 when N <= 1, otherwise LWORK >= 4*N + 16.
        !           107: *
        !           108: *          If LWORK = -1, then a workspace query is assumed; the routine
        !           109: *          only calculates the optimal size of the WORK array, returns
        !           110: *          this value as the first entry of the WORK array, and no error
        !           111: *          message related to LWORK is issued by XERBLA.
        !           112: *
        !           113: *  INFO    (output) INTEGER
        !           114: *           =0:  successful exit.
        !           115: *           <0:  if INFO = -i, the i-th argument had an illegal value.
        !           116: *           =1:  The transformed matrix pair (A, B) would be too far
        !           117: *                from generalized Schur form; the problem is ill-
        !           118: *                conditioned. (A, B) may have been partially reordered,
        !           119: *                and ILST points to the first row of the current
        !           120: *                position of the block being moved.
        !           121: *
        !           122: *  Further Details
        !           123: *  ===============
        !           124: *
        !           125: *  Based on contributions by
        !           126: *     Bo Kagstrom and Peter Poromaa, Department of Computing Science,
        !           127: *     Umea University, S-901 87 Umea, Sweden.
        !           128: *
        !           129: *  [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the
        !           130: *      Generalized Real Schur Form of a Regular Matrix Pair (A, B), in
        !           131: *      M.S. Moonen et al (eds), Linear Algebra for Large Scale and
        !           132: *      Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.
        !           133: *
        !           134: *  =====================================================================
        !           135: *
        !           136: *     .. Parameters ..
        !           137:       DOUBLE PRECISION   ZERO
        !           138:       PARAMETER          ( ZERO = 0.0D+0 )
        !           139: *     ..
        !           140: *     .. Local Scalars ..
        !           141:       LOGICAL            LQUERY
        !           142:       INTEGER            HERE, LWMIN, NBF, NBL, NBNEXT
        !           143: *     ..
        !           144: *     .. External Subroutines ..
        !           145:       EXTERNAL           DTGEX2, XERBLA
        !           146: *     ..
        !           147: *     .. Intrinsic Functions ..
        !           148:       INTRINSIC          MAX
        !           149: *     ..
        !           150: *     .. Executable Statements ..
        !           151: *
        !           152: *     Decode and test input arguments.
        !           153: *
        !           154:       INFO = 0
        !           155:       LQUERY = ( LWORK.EQ.-1 )
        !           156:       IF( N.LT.0 ) THEN
        !           157:          INFO = -3
        !           158:       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
        !           159:          INFO = -5
        !           160:       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
        !           161:          INFO = -7
        !           162:       ELSE IF( LDQ.LT.1 .OR. WANTQ .AND. ( LDQ.LT.MAX( 1, N ) ) ) THEN
        !           163:          INFO = -9
        !           164:       ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. ( LDZ.LT.MAX( 1, N ) ) ) THEN
        !           165:          INFO = -11
        !           166:       ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN
        !           167:          INFO = -12
        !           168:       ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN
        !           169:          INFO = -13
        !           170:       END IF
        !           171: *
        !           172:       IF( INFO.EQ.0 ) THEN
        !           173:          IF( N.LE.1 ) THEN
        !           174:             LWMIN = 1
        !           175:          ELSE
        !           176:             LWMIN = 4*N + 16
        !           177:          END IF
        !           178:          WORK(1) = LWMIN
        !           179: *
        !           180:          IF (LWORK.LT.LWMIN .AND. .NOT.LQUERY) THEN
        !           181:             INFO = -15
        !           182:          END IF
        !           183:       END IF
        !           184: *
        !           185:       IF( INFO.NE.0 ) THEN
        !           186:          CALL XERBLA( 'DTGEXC', -INFO )
        !           187:          RETURN
        !           188:       ELSE IF( LQUERY ) THEN
        !           189:          RETURN
        !           190:       END IF
        !           191: *
        !           192: *     Quick return if possible
        !           193: *
        !           194:       IF( N.LE.1 )
        !           195:      $   RETURN
        !           196: *
        !           197: *     Determine the first row of the specified block and find out
        !           198: *     if it is 1-by-1 or 2-by-2.
        !           199: *
        !           200:       IF( IFST.GT.1 ) THEN
        !           201:          IF( A( IFST, IFST-1 ).NE.ZERO )
        !           202:      $      IFST = IFST - 1
        !           203:       END IF
        !           204:       NBF = 1
        !           205:       IF( IFST.LT.N ) THEN
        !           206:          IF( A( IFST+1, IFST ).NE.ZERO )
        !           207:      $      NBF = 2
        !           208:       END IF
        !           209: *
        !           210: *     Determine the first row of the final block
        !           211: *     and find out if it is 1-by-1 or 2-by-2.
        !           212: *
        !           213:       IF( ILST.GT.1 ) THEN
        !           214:          IF( A( ILST, ILST-1 ).NE.ZERO )
        !           215:      $      ILST = ILST - 1
        !           216:       END IF
        !           217:       NBL = 1
        !           218:       IF( ILST.LT.N ) THEN
        !           219:          IF( A( ILST+1, ILST ).NE.ZERO )
        !           220:      $      NBL = 2
        !           221:       END IF
        !           222:       IF( IFST.EQ.ILST )
        !           223:      $   RETURN
        !           224: *
        !           225:       IF( IFST.LT.ILST ) THEN
        !           226: *
        !           227: *        Update ILST.
        !           228: *
        !           229:          IF( NBF.EQ.2 .AND. NBL.EQ.1 )
        !           230:      $      ILST = ILST - 1
        !           231:          IF( NBF.EQ.1 .AND. NBL.EQ.2 )
        !           232:      $      ILST = ILST + 1
        !           233: *
        !           234:          HERE = IFST
        !           235: *
        !           236:    10    CONTINUE
        !           237: *
        !           238: *        Swap with next one below.
        !           239: *
        !           240:          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
        !           241: *
        !           242: *           Current block either 1-by-1 or 2-by-2.
        !           243: *
        !           244:             NBNEXT = 1
        !           245:             IF( HERE+NBF+1.LE.N ) THEN
        !           246:                IF( A( HERE+NBF+1, HERE+NBF ).NE.ZERO )
        !           247:      $            NBNEXT = 2
        !           248:             END IF
        !           249:             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !           250:      $                   LDZ, HERE, NBF, NBNEXT, WORK, LWORK, INFO )
        !           251:             IF( INFO.NE.0 ) THEN
        !           252:                ILST = HERE
        !           253:                RETURN
        !           254:             END IF
        !           255:             HERE = HERE + NBNEXT
        !           256: *
        !           257: *           Test if 2-by-2 block breaks into two 1-by-1 blocks.
        !           258: *
        !           259:             IF( NBF.EQ.2 ) THEN
        !           260:                IF( A( HERE+1, HERE ).EQ.ZERO )
        !           261:      $            NBF = 3
        !           262:             END IF
        !           263: *
        !           264:          ELSE
        !           265: *
        !           266: *           Current block consists of two 1-by-1 blocks, each of which
        !           267: *           must be swapped individually.
        !           268: *
        !           269:             NBNEXT = 1
        !           270:             IF( HERE+3.LE.N ) THEN
        !           271:                IF( A( HERE+3, HERE+2 ).NE.ZERO )
        !           272:      $            NBNEXT = 2
        !           273:             END IF
        !           274:             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !           275:      $                   LDZ, HERE+1, 1, NBNEXT, WORK, LWORK, INFO )
        !           276:             IF( INFO.NE.0 ) THEN
        !           277:                ILST = HERE
        !           278:                RETURN
        !           279:             END IF
        !           280:             IF( NBNEXT.EQ.1 ) THEN
        !           281: *
        !           282: *              Swap two 1-by-1 blocks.
        !           283: *
        !           284:                CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !           285:      $                      LDZ, HERE, 1, 1, WORK, LWORK, INFO )
        !           286:                IF( INFO.NE.0 ) THEN
        !           287:                   ILST = HERE
        !           288:                   RETURN
        !           289:                END IF
        !           290:                HERE = HERE + 1
        !           291: *
        !           292:             ELSE
        !           293: *
        !           294: *              Recompute NBNEXT in case of 2-by-2 split.
        !           295: *
        !           296:                IF( A( HERE+2, HERE+1 ).EQ.ZERO )
        !           297:      $            NBNEXT = 1
        !           298:                IF( NBNEXT.EQ.2 ) THEN
        !           299: *
        !           300: *                 2-by-2 block did not split.
        !           301: *
        !           302:                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
        !           303:      $                         Z, LDZ, HERE, 1, NBNEXT, WORK, LWORK,
        !           304:      $                         INFO )
        !           305:                   IF( INFO.NE.0 ) THEN
        !           306:                      ILST = HERE
        !           307:                      RETURN
        !           308:                   END IF
        !           309:                   HERE = HERE + 2
        !           310:                ELSE
        !           311: *
        !           312: *                 2-by-2 block did split.
        !           313: *
        !           314:                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
        !           315:      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
        !           316:                   IF( INFO.NE.0 ) THEN
        !           317:                      ILST = HERE
        !           318:                      RETURN
        !           319:                   END IF
        !           320:                   HERE = HERE + 1
        !           321:                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
        !           322:      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
        !           323:                   IF( INFO.NE.0 ) THEN
        !           324:                      ILST = HERE
        !           325:                      RETURN
        !           326:                   END IF
        !           327:                   HERE = HERE + 1
        !           328:                END IF
        !           329: *
        !           330:             END IF
        !           331:          END IF
        !           332:          IF( HERE.LT.ILST )
        !           333:      $      GO TO 10
        !           334:       ELSE
        !           335:          HERE = IFST
        !           336: *
        !           337:    20    CONTINUE
        !           338: *
        !           339: *        Swap with next one below.
        !           340: *
        !           341:          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
        !           342: *
        !           343: *           Current block either 1-by-1 or 2-by-2.
        !           344: *
        !           345:             NBNEXT = 1
        !           346:             IF( HERE.GE.3 ) THEN
        !           347:                IF( A( HERE-1, HERE-2 ).NE.ZERO )
        !           348:      $            NBNEXT = 2
        !           349:             END IF
        !           350:             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !           351:      $                   LDZ, HERE-NBNEXT, NBNEXT, NBF, WORK, LWORK,
        !           352:      $                   INFO )
        !           353:             IF( INFO.NE.0 ) THEN
        !           354:                ILST = HERE
        !           355:                RETURN
        !           356:             END IF
        !           357:             HERE = HERE - NBNEXT
        !           358: *
        !           359: *           Test if 2-by-2 block breaks into two 1-by-1 blocks.
        !           360: *
        !           361:             IF( NBF.EQ.2 ) THEN
        !           362:                IF( A( HERE+1, HERE ).EQ.ZERO )
        !           363:      $            NBF = 3
        !           364:             END IF
        !           365: *
        !           366:          ELSE
        !           367: *
        !           368: *           Current block consists of two 1-by-1 blocks, each of which
        !           369: *           must be swapped individually.
        !           370: *
        !           371:             NBNEXT = 1
        !           372:             IF( HERE.GE.3 ) THEN
        !           373:                IF( A( HERE-1, HERE-2 ).NE.ZERO )
        !           374:      $            NBNEXT = 2
        !           375:             END IF
        !           376:             CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !           377:      $                   LDZ, HERE-NBNEXT, NBNEXT, 1, WORK, LWORK,
        !           378:      $                   INFO )
        !           379:             IF( INFO.NE.0 ) THEN
        !           380:                ILST = HERE
        !           381:                RETURN
        !           382:             END IF
        !           383:             IF( NBNEXT.EQ.1 ) THEN
        !           384: *
        !           385: *              Swap two 1-by-1 blocks.
        !           386: *
        !           387:                CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
        !           388:      $                      LDZ, HERE, NBNEXT, 1, WORK, LWORK, INFO )
        !           389:                IF( INFO.NE.0 ) THEN
        !           390:                   ILST = HERE
        !           391:                   RETURN
        !           392:                END IF
        !           393:                HERE = HERE - 1
        !           394:             ELSE
        !           395: *
        !           396: *             Recompute NBNEXT in case of 2-by-2 split.
        !           397: *
        !           398:                IF( A( HERE, HERE-1 ).EQ.ZERO )
        !           399:      $            NBNEXT = 1
        !           400:                IF( NBNEXT.EQ.2 ) THEN
        !           401: *
        !           402: *                 2-by-2 block did not split.
        !           403: *
        !           404:                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
        !           405:      $                         Z, LDZ, HERE-1, 2, 1, WORK, LWORK, INFO )
        !           406:                   IF( INFO.NE.0 ) THEN
        !           407:                      ILST = HERE
        !           408:                      RETURN
        !           409:                   END IF
        !           410:                   HERE = HERE - 2
        !           411:                ELSE
        !           412: *
        !           413: *                 2-by-2 block did split.
        !           414: *
        !           415:                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
        !           416:      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
        !           417:                   IF( INFO.NE.0 ) THEN
        !           418:                      ILST = HERE
        !           419:                      RETURN
        !           420:                   END IF
        !           421:                   HERE = HERE - 1
        !           422:                   CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
        !           423:      $                         Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
        !           424:                   IF( INFO.NE.0 ) THEN
        !           425:                      ILST = HERE
        !           426:                      RETURN
        !           427:                   END IF
        !           428:                   HERE = HERE - 1
        !           429:                END IF
        !           430:             END IF
        !           431:          END IF
        !           432:          IF( HERE.GT.ILST )
        !           433:      $      GO TO 20
        !           434:       END IF
        !           435:       ILST = HERE
        !           436:       WORK( 1 ) = LWMIN
        !           437:       RETURN
        !           438: *
        !           439: *     End of DTGEXC
        !           440: *
        !           441:       END

CVSweb interface <joel.bertrand@systella.fr>