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>