File:  [local] / rpl / lapack / lapack / dtrexc.f
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Jan 26 15:22:45 2010 UTC (14 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Initial revision

    1:       SUBROUTINE DTREXC( COMPQ, N, T, LDT, Q, LDQ, IFST, ILST, WORK,
    2:      $                   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:       CHARACTER          COMPQ
   11:       INTEGER            IFST, ILST, INFO, LDQ, LDT, N
   12: *     ..
   13: *     .. Array Arguments ..
   14:       DOUBLE PRECISION   Q( LDQ, * ), T( LDT, * ), WORK( * )
   15: *     ..
   16: *
   17: *  Purpose
   18: *  =======
   19: *
   20: *  DTREXC reorders the real Schur factorization of a real matrix
   21: *  A = Q*T*Q**T, so that the diagonal block of T with row index IFST is
   22: *  moved to row ILST.
   23: *
   24: *  The real Schur form T is reordered by an orthogonal similarity
   25: *  transformation Z**T*T*Z, and optionally the matrix Q of Schur vectors
   26: *  is updated by postmultiplying it with Z.
   27: *
   28: *  T must be in Schur canonical form (as returned by DHSEQR), that is,
   29: *  block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each
   30: *  2-by-2 diagonal block has its diagonal elements equal and its
   31: *  off-diagonal elements of opposite sign.
   32: *
   33: *  Arguments
   34: *  =========
   35: *
   36: *  COMPQ   (input) CHARACTER*1
   37: *          = 'V':  update the matrix Q of Schur vectors;
   38: *          = 'N':  do not update Q.
   39: *
   40: *  N       (input) INTEGER
   41: *          The order of the matrix T. N >= 0.
   42: *
   43: *  T       (input/output) DOUBLE PRECISION array, dimension (LDT,N)
   44: *          On entry, the upper quasi-triangular matrix T, in Schur
   45: *          Schur canonical form.
   46: *          On exit, the reordered upper quasi-triangular matrix, again
   47: *          in Schur canonical form.
   48: *
   49: *  LDT     (input) INTEGER
   50: *          The leading dimension of the array T. LDT >= max(1,N).
   51: *
   52: *  Q       (input/output) DOUBLE PRECISION array, dimension (LDQ,N)
   53: *          On entry, if COMPQ = 'V', the matrix Q of Schur vectors.
   54: *          On exit, if COMPQ = 'V', Q has been postmultiplied by the
   55: *          orthogonal transformation matrix Z which reorders T.
   56: *          If COMPQ = 'N', Q is not referenced.
   57: *
   58: *  LDQ     (input) INTEGER
   59: *          The leading dimension of the array Q.  LDQ >= max(1,N).
   60: *
   61: *  IFST    (input/output) INTEGER
   62: *  ILST    (input/output) INTEGER
   63: *          Specify the reordering of the diagonal blocks of T.
   64: *          The block with row index IFST is moved to row ILST, by a
   65: *          sequence of transpositions between adjacent blocks.
   66: *          On exit, if IFST pointed on entry to the second row of a
   67: *          2-by-2 block, it is changed to point to the first row; ILST
   68: *          always points to the first row of the block in its final
   69: *          position (which may differ from its input value by +1 or -1).
   70: *          1 <= IFST <= N; 1 <= ILST <= N.
   71: *
   72: *  WORK    (workspace) DOUBLE PRECISION array, dimension (N)
   73: *
   74: *  INFO    (output) INTEGER
   75: *          = 0:  successful exit
   76: *          < 0:  if INFO = -i, the i-th argument had an illegal value
   77: *          = 1:  two adjacent blocks were too close to swap (the problem
   78: *                is very ill-conditioned); T may have been partially
   79: *                reordered, and ILST points to the first row of the
   80: *                current position of the block being moved.
   81: *
   82: *  =====================================================================
   83: *
   84: *     .. Parameters ..
   85:       DOUBLE PRECISION   ZERO
   86:       PARAMETER          ( ZERO = 0.0D+0 )
   87: *     ..
   88: *     .. Local Scalars ..
   89:       LOGICAL            WANTQ
   90:       INTEGER            HERE, NBF, NBL, NBNEXT
   91: *     ..
   92: *     .. External Functions ..
   93:       LOGICAL            LSAME
   94:       EXTERNAL           LSAME
   95: *     ..
   96: *     .. External Subroutines ..
   97:       EXTERNAL           DLAEXC, XERBLA
   98: *     ..
   99: *     .. Intrinsic Functions ..
  100:       INTRINSIC          MAX
  101: *     ..
  102: *     .. Executable Statements ..
  103: *
  104: *     Decode and test the input arguments.
  105: *
  106:       INFO = 0
  107:       WANTQ = LSAME( COMPQ, 'V' )
  108:       IF( .NOT.WANTQ .AND. .NOT.LSAME( COMPQ, 'N' ) ) THEN
  109:          INFO = -1
  110:       ELSE IF( N.LT.0 ) THEN
  111:          INFO = -2
  112:       ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
  113:          INFO = -4
  114:       ELSE IF( LDQ.LT.1 .OR. ( WANTQ .AND. LDQ.LT.MAX( 1, N ) ) ) THEN
  115:          INFO = -6
  116:       ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN
  117:          INFO = -7
  118:       ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN
  119:          INFO = -8
  120:       END IF
  121:       IF( INFO.NE.0 ) THEN
  122:          CALL XERBLA( 'DTREXC', -INFO )
  123:          RETURN
  124:       END IF
  125: *
  126: *     Quick return if possible
  127: *
  128:       IF( N.LE.1 )
  129:      $   RETURN
  130: *
  131: *     Determine the first row of specified block
  132: *     and find out it is 1 by 1 or 2 by 2.
  133: *
  134:       IF( IFST.GT.1 ) THEN
  135:          IF( T( IFST, IFST-1 ).NE.ZERO )
  136:      $      IFST = IFST - 1
  137:       END IF
  138:       NBF = 1
  139:       IF( IFST.LT.N ) THEN
  140:          IF( T( IFST+1, IFST ).NE.ZERO )
  141:      $      NBF = 2
  142:       END IF
  143: *
  144: *     Determine the first row of the final block
  145: *     and find out it is 1 by 1 or 2 by 2.
  146: *
  147:       IF( ILST.GT.1 ) THEN
  148:          IF( T( ILST, ILST-1 ).NE.ZERO )
  149:      $      ILST = ILST - 1
  150:       END IF
  151:       NBL = 1
  152:       IF( ILST.LT.N ) THEN
  153:          IF( T( ILST+1, ILST ).NE.ZERO )
  154:      $      NBL = 2
  155:       END IF
  156: *
  157:       IF( IFST.EQ.ILST )
  158:      $   RETURN
  159: *
  160:       IF( IFST.LT.ILST ) THEN
  161: *
  162: *        Update ILST
  163: *
  164:          IF( NBF.EQ.2 .AND. NBL.EQ.1 )
  165:      $      ILST = ILST - 1
  166:          IF( NBF.EQ.1 .AND. NBL.EQ.2 )
  167:      $      ILST = ILST + 1
  168: *
  169:          HERE = IFST
  170: *
  171:    10    CONTINUE
  172: *
  173: *        Swap block with next one below
  174: *
  175:          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
  176: *
  177: *           Current block either 1 by 1 or 2 by 2
  178: *
  179:             NBNEXT = 1
  180:             IF( HERE+NBF+1.LE.N ) THEN
  181:                IF( T( HERE+NBF+1, HERE+NBF ).NE.ZERO )
  182:      $            NBNEXT = 2
  183:             END IF
  184:             CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBF, NBNEXT,
  185:      $                   WORK, INFO )
  186:             IF( INFO.NE.0 ) THEN
  187:                ILST = HERE
  188:                RETURN
  189:             END IF
  190:             HERE = HERE + NBNEXT
  191: *
  192: *           Test if 2 by 2 block breaks into two 1 by 1 blocks
  193: *
  194:             IF( NBF.EQ.2 ) THEN
  195:                IF( T( HERE+1, HERE ).EQ.ZERO )
  196:      $            NBF = 3
  197:             END IF
  198: *
  199:          ELSE
  200: *
  201: *           Current block consists of two 1 by 1 blocks each of which
  202: *           must be swapped individually
  203: *
  204:             NBNEXT = 1
  205:             IF( HERE+3.LE.N ) THEN
  206:                IF( T( HERE+3, HERE+2 ).NE.ZERO )
  207:      $            NBNEXT = 2
  208:             END IF
  209:             CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, NBNEXT,
  210:      $                   WORK, INFO )
  211:             IF( INFO.NE.0 ) THEN
  212:                ILST = HERE
  213:                RETURN
  214:             END IF
  215:             IF( NBNEXT.EQ.1 ) THEN
  216: *
  217: *              Swap two 1 by 1 blocks, no problems possible
  218: *
  219:                CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, NBNEXT,
  220:      $                      WORK, INFO )
  221:                HERE = HERE + 1
  222:             ELSE
  223: *
  224: *              Recompute NBNEXT in case 2 by 2 split
  225: *
  226:                IF( T( HERE+2, HERE+1 ).EQ.ZERO )
  227:      $            NBNEXT = 1
  228:                IF( NBNEXT.EQ.2 ) THEN
  229: *
  230: *                 2 by 2 Block did not split
  231: *
  232:                   CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1,
  233:      $                         NBNEXT, WORK, INFO )
  234:                   IF( INFO.NE.0 ) THEN
  235:                      ILST = HERE
  236:                      RETURN
  237:                   END IF
  238:                   HERE = HERE + 2
  239:                ELSE
  240: *
  241: *                 2 by 2 Block did split
  242: *
  243:                   CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,
  244:      $                         WORK, INFO )
  245:                   CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE+1, 1, 1,
  246:      $                         WORK, INFO )
  247:                   HERE = HERE + 2
  248:                END IF
  249:             END IF
  250:          END IF
  251:          IF( HERE.LT.ILST )
  252:      $      GO TO 10
  253: *
  254:       ELSE
  255: *
  256:          HERE = IFST
  257:    20    CONTINUE
  258: *
  259: *        Swap block with next one above
  260: *
  261:          IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
  262: *
  263: *           Current block either 1 by 1 or 2 by 2
  264: *
  265:             NBNEXT = 1
  266:             IF( HERE.GE.3 ) THEN
  267:                IF( T( HERE-1, HERE-2 ).NE.ZERO )
  268:      $            NBNEXT = 2
  269:             END IF
  270:             CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,
  271:      $                   NBF, WORK, INFO )
  272:             IF( INFO.NE.0 ) THEN
  273:                ILST = HERE
  274:                RETURN
  275:             END IF
  276:             HERE = HERE - NBNEXT
  277: *
  278: *           Test if 2 by 2 block breaks into two 1 by 1 blocks
  279: *
  280:             IF( NBF.EQ.2 ) THEN
  281:                IF( T( HERE+1, HERE ).EQ.ZERO )
  282:      $            NBF = 3
  283:             END IF
  284: *
  285:          ELSE
  286: *
  287: *           Current block consists of two 1 by 1 blocks each of which
  288: *           must be swapped individually
  289: *
  290:             NBNEXT = 1
  291:             IF( HERE.GE.3 ) THEN
  292:                IF( T( HERE-1, HERE-2 ).NE.ZERO )
  293:      $            NBNEXT = 2
  294:             END IF
  295:             CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-NBNEXT, NBNEXT,
  296:      $                   1, WORK, INFO )
  297:             IF( INFO.NE.0 ) THEN
  298:                ILST = HERE
  299:                RETURN
  300:             END IF
  301:             IF( NBNEXT.EQ.1 ) THEN
  302: *
  303: *              Swap two 1 by 1 blocks, no problems possible
  304: *
  305:                CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, NBNEXT, 1,
  306:      $                      WORK, INFO )
  307:                HERE = HERE - 1
  308:             ELSE
  309: *
  310: *              Recompute NBNEXT in case 2 by 2 split
  311: *
  312:                IF( T( HERE, HERE-1 ).EQ.ZERO )
  313:      $            NBNEXT = 1
  314:                IF( NBNEXT.EQ.2 ) THEN
  315: *
  316: *                 2 by 2 Block did not split
  317: *
  318:                   CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 2, 1,
  319:      $                         WORK, INFO )
  320:                   IF( INFO.NE.0 ) THEN
  321:                      ILST = HERE
  322:                      RETURN
  323:                   END IF
  324:                   HERE = HERE - 2
  325:                ELSE
  326: *
  327: *                 2 by 2 Block did split
  328: *
  329:                   CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE, 1, 1,
  330:      $                         WORK, INFO )
  331:                   CALL DLAEXC( WANTQ, N, T, LDT, Q, LDQ, HERE-1, 1, 1,
  332:      $                         WORK, INFO )
  333:                   HERE = HERE - 2
  334:                END IF
  335:             END IF
  336:          END IF
  337:          IF( HERE.GT.ILST )
  338:      $      GO TO 20
  339:       END IF
  340:       ILST = HERE
  341: *
  342:       RETURN
  343: *
  344: *     End of DTREXC
  345: *
  346:       END

CVSweb interface <joel.bertrand@systella.fr>