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