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