Annotation of rpl/lapack/lapack/dtrexc.f, revision 1.1
1.1 ! bertrand 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>