3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download DTGEXC + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dtgexc.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dtgexc.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgexc.f">
21 * SUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
22 * LDZ, IFST, ILST, WORK, LWORK, INFO )
24 * .. Scalar Arguments ..
25 * LOGICAL WANTQ, WANTZ
26 * INTEGER IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N
28 * .. Array Arguments ..
29 * DOUBLE PRECISION A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
30 * $ WORK( * ), Z( LDZ, * )
39 *> DTGEXC reorders the generalized real Schur decomposition of a real
40 *> matrix pair (A,B) using an orthogonal equivalence transformation
42 *> (A, B) = Q * (A, B) * Z**T,
44 *> so that the diagonal block of (A, B) with row index IFST is moved
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.
51 *> Optionally, the matrices Q and Z of generalized Schur vectors are
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
65 *> .TRUE. : update the left transformation matrix Q;
66 *> .FALSE.: do not update Q.
72 *> .TRUE. : update the right transformation matrix Z;
73 *> .FALSE.: do not update Z.
79 *> The order of the matrices A and B. N >= 0.
84 *> A is DOUBLE PRECISION array, dimension (LDA,N)
85 *> On entry, the matrix A in generalized real Schur canonical
87 *> On exit, the updated matrix A, again in generalized
88 *> real Schur canonical form.
94 *> The leading dimension of the array A. LDA >= max(1,N).
99 *> B is DOUBLE PRECISION array, dimension (LDB,N)
100 *> On entry, the matrix B in generalized real Schur canonical
102 *> On exit, the updated matrix B, again in generalized
103 *> real Schur canonical form (A,B).
109 *> The leading dimension of the array B. LDB >= max(1,N).
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.
123 *> The leading dimension of the array Q. LDQ >= 1.
124 *> If WANTQ = .TRUE., LDQ >= N.
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.
138 *> The leading dimension of the array Z. LDZ >= 1.
139 *> If WANTZ = .TRUE., LDZ >= N.
142 *> \param[in,out] IFST
147 *> \param[in,out] ILST
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.
162 *> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
163 *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
169 *> The dimension of the array WORK.
170 *> LWORK >= 1 when N <= 1, otherwise LWORK >= 4*N + 16.
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.
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.
193 *> \author Univ. of Tennessee
194 *> \author Univ. of California Berkeley
195 *> \author Univ. of Colorado Denver
198 *> \date November 2011
200 *> \ingroup doubleGEcomputational
202 *> \par Contributors:
205 *> Bo Kagstrom and Peter Poromaa, Department of Computing Science,
206 *> Umea University, S-901 87 Umea, Sweden.
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.
219 * =====================================================================
220 SUBROUTINE DTGEXC( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
221 $ LDZ, IFST, ILST, WORK, LWORK, INFO )
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..--
228 * .. Scalar Arguments ..
230 INTEGER IFST, ILST, INFO, LDA, LDB, LDQ, LDZ, LWORK, N
232 * .. Array Arguments ..
233 DOUBLE PRECISION A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
234 $ WORK( * ), Z( LDZ, * )
237 * =====================================================================
240 DOUBLE PRECISION ZERO
241 PARAMETER ( ZERO = 0.0D+0 )
243 * .. Local Scalars ..
245 INTEGER HERE, LWMIN, NBF, NBL, NBNEXT
247 * .. External Subroutines ..
248 EXTERNAL DTGEX2, XERBLA
250 * .. Intrinsic Functions ..
253 * .. Executable Statements ..
255 * Decode and test input arguments.
258 LQUERY = ( LWORK.EQ.-1 )
261 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
263 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
265 ELSE IF( LDQ.LT.1 .OR. WANTQ .AND. ( LDQ.LT.MAX( 1, N ) ) ) THEN
267 ELSE IF( LDZ.LT.1 .OR. WANTZ .AND. ( LDZ.LT.MAX( 1, N ) ) ) THEN
269 ELSE IF( IFST.LT.1 .OR. IFST.GT.N ) THEN
271 ELSE IF( ILST.LT.1 .OR. ILST.GT.N ) THEN
283 IF (LWORK.LT.LWMIN .AND. .NOT.LQUERY) THEN
289 CALL XERBLA( 'DTGEXC', -INFO )
291 ELSE IF( LQUERY ) THEN
295 * Quick return if possible
300 * Determine the first row of the specified block and find out
301 * if it is 1-by-1 or 2-by-2.
304 IF( A( IFST, IFST-1 ).NE.ZERO )
309 IF( A( IFST+1, IFST ).NE.ZERO )
313 * Determine the first row of the final block
314 * and find out if it is 1-by-1 or 2-by-2.
317 IF( A( ILST, ILST-1 ).NE.ZERO )
322 IF( A( ILST+1, ILST ).NE.ZERO )
328 IF( IFST.LT.ILST ) THEN
332 IF( NBF.EQ.2 .AND. NBL.EQ.1 )
334 IF( NBF.EQ.1 .AND. NBL.EQ.2 )
341 * Swap with next one below.
343 IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
345 * Current block either 1-by-1 or 2-by-2.
348 IF( HERE+NBF+1.LE.N ) THEN
349 IF( A( HERE+NBF+1, HERE+NBF ).NE.ZERO )
352 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
353 $ LDZ, HERE, NBF, NBNEXT, WORK, LWORK, INFO )
360 * Test if 2-by-2 block breaks into two 1-by-1 blocks.
363 IF( A( HERE+1, HERE ).EQ.ZERO )
369 * Current block consists of two 1-by-1 blocks, each of which
370 * must be swapped individually.
373 IF( HERE+3.LE.N ) THEN
374 IF( A( HERE+3, HERE+2 ).NE.ZERO )
377 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
378 $ LDZ, HERE+1, 1, NBNEXT, WORK, LWORK, INFO )
383 IF( NBNEXT.EQ.1 ) THEN
385 * Swap two 1-by-1 blocks.
387 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
388 $ LDZ, HERE, 1, 1, WORK, LWORK, INFO )
397 * Recompute NBNEXT in case of 2-by-2 split.
399 IF( A( HERE+2, HERE+1 ).EQ.ZERO )
401 IF( NBNEXT.EQ.2 ) THEN
403 * 2-by-2 block did not split.
405 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
406 $ Z, LDZ, HERE, 1, NBNEXT, WORK, LWORK,
415 * 2-by-2 block did split.
417 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
418 $ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
424 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
425 $ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
442 * Swap with next one below.
444 IF( NBF.EQ.1 .OR. NBF.EQ.2 ) THEN
446 * Current block either 1-by-1 or 2-by-2.
450 IF( A( HERE-1, HERE-2 ).NE.ZERO )
453 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
454 $ LDZ, HERE-NBNEXT, NBNEXT, NBF, WORK, LWORK,
462 * Test if 2-by-2 block breaks into two 1-by-1 blocks.
465 IF( A( HERE+1, HERE ).EQ.ZERO )
471 * Current block consists of two 1-by-1 blocks, each of which
472 * must be swapped individually.
476 IF( A( HERE-1, HERE-2 ).NE.ZERO )
479 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
480 $ LDZ, HERE-NBNEXT, NBNEXT, 1, WORK, LWORK,
486 IF( NBNEXT.EQ.1 ) THEN
488 * Swap two 1-by-1 blocks.
490 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
491 $ LDZ, HERE, NBNEXT, 1, WORK, LWORK, INFO )
499 * Recompute NBNEXT in case of 2-by-2 split.
501 IF( A( HERE, HERE-1 ).EQ.ZERO )
503 IF( NBNEXT.EQ.2 ) THEN
505 * 2-by-2 block did not split.
507 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
508 $ Z, LDZ, HERE-1, 2, 1, WORK, LWORK, INFO )
516 * 2-by-2 block did split.
518 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
519 $ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )
525 CALL DTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ,
526 $ Z, LDZ, HERE, 1, 1, WORK, LWORK, INFO )