LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
ztgex2.f
Go to the documentation of this file.
1*> \brief \b ZTGEX2 swaps adjacent diagonal blocks in an upper (quasi) triangular matrix pair by an unitary equivalence transformation.
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download ZTGEX2 + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ztgex2.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ztgex2.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ztgex2.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE ZTGEX2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
20* LDZ, J1, INFO )
21*
22* .. Scalar Arguments ..
23* LOGICAL WANTQ, WANTZ
24* INTEGER INFO, J1, LDA, LDB, LDQ, LDZ, N
25* ..
26* .. Array Arguments ..
27* COMPLEX*16 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
28* $ Z( LDZ, * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> ZTGEX2 swaps adjacent diagonal 1 by 1 blocks (A11,B11) and (A22,B22)
38*> in an upper triangular matrix pair (A, B) by an unitary equivalence
39*> transformation.
40*>
41*> (A, B) must be in generalized Schur canonical form, that is, A and
42*> B are both upper triangular.
43*>
44*> Optionally, the matrices Q and Z of generalized Schur vectors are
45*> updated.
46*>
47*> Q(in) * A(in) * Z(in)**H = Q(out) * A(out) * Z(out)**H
48*> Q(in) * B(in) * Z(in)**H = Q(out) * B(out) * Z(out)**H
49*>
50*> \endverbatim
51*
52* Arguments:
53* ==========
54*
55*> \param[in] WANTQ
56*> \verbatim
57*> WANTQ is LOGICAL
58*> .TRUE. : update the left transformation matrix Q;
59*> .FALSE.: do not update Q.
60*> \endverbatim
61*>
62*> \param[in] WANTZ
63*> \verbatim
64*> WANTZ is LOGICAL
65*> .TRUE. : update the right transformation matrix Z;
66*> .FALSE.: do not update Z.
67*> \endverbatim
68*>
69*> \param[in] N
70*> \verbatim
71*> N is INTEGER
72*> The order of the matrices A and B. N >= 0.
73*> \endverbatim
74*>
75*> \param[in,out] A
76*> \verbatim
77*> A is COMPLEX*16 array, dimensions (LDA,N)
78*> On entry, the matrix A in the pair (A, B).
79*> On exit, the updated matrix A.
80*> \endverbatim
81*>
82*> \param[in] LDA
83*> \verbatim
84*> LDA is INTEGER
85*> The leading dimension of the array A. LDA >= max(1,N).
86*> \endverbatim
87*>
88*> \param[in,out] B
89*> \verbatim
90*> B is COMPLEX*16 array, dimensions (LDB,N)
91*> On entry, the matrix B in the pair (A, B).
92*> On exit, the updated matrix B.
93*> \endverbatim
94*>
95*> \param[in] LDB
96*> \verbatim
97*> LDB is INTEGER
98*> The leading dimension of the array B. LDB >= max(1,N).
99*> \endverbatim
100*>
101*> \param[in,out] Q
102*> \verbatim
103*> Q is COMPLEX*16 array, dimension (LDQ,N)
104*> If WANTQ = .TRUE, on entry, the unitary matrix Q. On exit,
105*> the updated matrix Q.
106*> Not referenced if WANTQ = .FALSE..
107*> \endverbatim
108*>
109*> \param[in] LDQ
110*> \verbatim
111*> LDQ is INTEGER
112*> The leading dimension of the array Q. LDQ >= 1;
113*> If WANTQ = .TRUE., LDQ >= N.
114*> \endverbatim
115*>
116*> \param[in,out] Z
117*> \verbatim
118*> Z is COMPLEX*16 array, dimension (LDZ,N)
119*> If WANTZ = .TRUE, on entry, the unitary matrix Z. On exit,
120*> the updated matrix Z.
121*> Not referenced if WANTZ = .FALSE..
122*> \endverbatim
123*>
124*> \param[in] LDZ
125*> \verbatim
126*> LDZ is INTEGER
127*> The leading dimension of the array Z. LDZ >= 1;
128*> If WANTZ = .TRUE., LDZ >= N.
129*> \endverbatim
130*>
131*> \param[in] J1
132*> \verbatim
133*> J1 is INTEGER
134*> The index to the first block (A11, B11).
135*> \endverbatim
136*>
137*> \param[out] INFO
138*> \verbatim
139*> INFO is INTEGER
140*> =0: Successful exit.
141*> =1: The transformed matrix pair (A, B) would be too far
142*> from generalized Schur form; the problem is ill-
143*> conditioned.
144*> \endverbatim
145*
146* Authors:
147* ========
148*
149*> \author Univ. of Tennessee
150*> \author Univ. of California Berkeley
151*> \author Univ. of Colorado Denver
152*> \author NAG Ltd.
153*
154*> \ingroup tgex2
155*
156*> \par Further Details:
157* =====================
158*>
159*> In the current code both weak and strong stability tests are
160*> performed. The user can omit the strong stability test by changing
161*> the internal logical parameter WANDS to .FALSE.. See ref. [2] for
162*> details.
163*
164*> \par Contributors:
165* ==================
166*>
167*> Bo Kagstrom and Peter Poromaa, Department of Computing Science,
168*> Umea University, S-901 87 Umea, Sweden.
169*
170*> \par References:
171* ================
172*>
173*> [1] B. Kagstrom; A Direct Method for Reordering Eigenvalues in the
174*> Generalized Real Schur Form of a Regular Matrix Pair (A, B), in
175*> M.S. Moonen et al (eds), Linear Algebra for Large Scale and
176*> Real-Time Applications, Kluwer Academic Publ. 1993, pp 195-218.
177*> \n
178*> [2] B. Kagstrom and P. Poromaa; Computing Eigenspaces with Specified
179*> Eigenvalues of a Regular Matrix Pair (A, B) and Condition
180*> Estimation: Theory, Algorithms and Software, Report UMINF-94.04,
181*> Department of Computing Science, Umea University, S-901 87 Umea,
182*> Sweden, 1994. Also as LAPACK Working Note 87. To appear in
183*> Numerical Algorithms, 1996.
184*>
185* =====================================================================
186 SUBROUTINE ztgex2( WANTQ, WANTZ, N, A, LDA, B, LDB, Q, LDQ, Z,
187 $ LDZ, J1, INFO )
188*
189* -- LAPACK auxiliary routine --
190* -- LAPACK is a software package provided by Univ. of Tennessee, --
191* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
192*
193* .. Scalar Arguments ..
194 LOGICAL WANTQ, WANTZ
195 INTEGER INFO, J1, LDA, LDB, LDQ, LDZ, N
196* ..
197* .. Array Arguments ..
198 COMPLEX*16 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
199 $ z( ldz, * )
200* ..
201*
202* =====================================================================
203*
204* .. Parameters ..
205 COMPLEX*16 CZERO, CONE
206 parameter( czero = ( 0.0d+0, 0.0d+0 ),
207 $ cone = ( 1.0d+0, 0.0d+0 ) )
208 DOUBLE PRECISION TWENTY
209 parameter( twenty = 2.0d+1 )
210 INTEGER LDST
211 parameter( ldst = 2 )
212 LOGICAL WANDS
213 parameter( wands = .true. )
214* ..
215* .. Local Scalars ..
216 LOGICAL STRONG, WEAK
217 INTEGER I, M
218 DOUBLE PRECISION CQ, CZ, EPS, SA, SB, SCALE, SMLNUM, SUM,
219 $ thresha, threshb
220 COMPLEX*16 CDUM, F, G, SQ, SZ
221* ..
222* .. Local Arrays ..
223 COMPLEX*16 S( LDST, LDST ), T( LDST, LDST ), WORK( 8 )
224* ..
225* .. External Functions ..
226 DOUBLE PRECISION DLAMCH
227 EXTERNAL dlamch
228* ..
229* .. External Subroutines ..
230 EXTERNAL zlacpy, zlartg, zlassq, zrot
231* ..
232* .. Intrinsic Functions ..
233 INTRINSIC abs, dble, dconjg, max, sqrt
234* ..
235* .. Executable Statements ..
236*
237 info = 0
238*
239* Quick return if possible
240*
241 IF( n.LE.1 )
242 $ RETURN
243*
244 m = ldst
245 weak = .false.
246 strong = .false.
247*
248* Make a local copy of selected block in (A, B)
249*
250 CALL zlacpy( 'Full', m, m, a( j1, j1 ), lda, s, ldst )
251 CALL zlacpy( 'Full', m, m, b( j1, j1 ), ldb, t, ldst )
252*
253* Compute the threshold for testing the acceptance of swapping.
254*
255 eps = dlamch( 'P' )
256 smlnum = dlamch( 'S' ) / eps
257 scale = dble( czero )
258 sum = dble( cone )
259 CALL zlacpy( 'Full', m, m, s, ldst, work, m )
260 CALL zlacpy( 'Full', m, m, t, ldst, work( m*m+1 ), m )
261 CALL zlassq( m*m, work, 1, scale, sum )
262 sa = scale*sqrt( sum )
263 scale = dble( czero )
264 sum = dble( cone )
265 CALL zlassq( m*m, work(m*m+1), 1, scale, sum )
266 sb = scale*sqrt( sum )
267*
268* THRES has been changed from
269* THRESH = MAX( TEN*EPS*SA, SMLNUM )
270* to
271* THRESH = MAX( TWENTY*EPS*SA, SMLNUM )
272* on 04/01/10.
273* "Bug" reported by Ondra Kamenik, confirmed by Julie Langou, fixed by
274* Jim Demmel and Guillaume Revy. See forum post 1783.
275*
276 thresha = max( twenty*eps*sa, smlnum )
277 threshb = max( twenty*eps*sb, smlnum )
278*
279* Compute unitary QL and RQ that swap 1-by-1 and 1-by-1 blocks
280* using Givens rotations and perform the swap tentatively.
281*
282 f = s( 2, 2 )*t( 1, 1 ) - t( 2, 2 )*s( 1, 1 )
283 g = s( 2, 2 )*t( 1, 2 ) - t( 2, 2 )*s( 1, 2 )
284 sa = abs( s( 2, 2 ) ) * abs( t( 1, 1 ) )
285 sb = abs( s( 1, 1 ) ) * abs( t( 2, 2 ) )
286 CALL zlartg( g, f, cz, sz, cdum )
287 sz = -sz
288 CALL zrot( 2, s( 1, 1 ), 1, s( 1, 2 ), 1, cz, dconjg( sz ) )
289 CALL zrot( 2, t( 1, 1 ), 1, t( 1, 2 ), 1, cz, dconjg( sz ) )
290 IF( sa.GE.sb ) THEN
291 CALL zlartg( s( 1, 1 ), s( 2, 1 ), cq, sq, cdum )
292 ELSE
293 CALL zlartg( t( 1, 1 ), t( 2, 1 ), cq, sq, cdum )
294 END IF
295 CALL zrot( 2, s( 1, 1 ), ldst, s( 2, 1 ), ldst, cq, sq )
296 CALL zrot( 2, t( 1, 1 ), ldst, t( 2, 1 ), ldst, cq, sq )
297*
298* Weak stability test: |S21| <= O(EPS F-norm((A)))
299* and |T21| <= O(EPS F-norm((B)))
300*
301 weak = abs( s( 2, 1 ) ).LE.thresha .AND.
302 $ abs( t( 2, 1 ) ).LE.threshb
303 IF( .NOT.weak )
304 $ GO TO 20
305*
306 IF( wands ) THEN
307*
308* Strong stability test:
309* F-norm((A-QL**H*S*QR)) <= O(EPS*F-norm((A)))
310* and
311* F-norm((B-QL**H*T*QR)) <= O(EPS*F-norm((B)))
312*
313 CALL zlacpy( 'Full', m, m, s, ldst, work, m )
314 CALL zlacpy( 'Full', m, m, t, ldst, work( m*m+1 ), m )
315 CALL zrot( 2, work, 1, work( 3 ), 1, cz, -dconjg( sz ) )
316 CALL zrot( 2, work( 5 ), 1, work( 7 ), 1, cz,
317 $ -dconjg( sz ) )
318 CALL zrot( 2, work, 2, work( 2 ), 2, cq, -sq )
319 CALL zrot( 2, work( 5 ), 2, work( 6 ), 2, cq, -sq )
320 DO 10 i = 1, 2
321 work( i ) = work( i ) - a( j1+i-1, j1 )
322 work( i+2 ) = work( i+2 ) - a( j1+i-1, j1+1 )
323 work( i+4 ) = work( i+4 ) - b( j1+i-1, j1 )
324 work( i+6 ) = work( i+6 ) - b( j1+i-1, j1+1 )
325 10 CONTINUE
326 scale = dble( czero )
327 sum = dble( cone )
328 CALL zlassq( m*m, work, 1, scale, sum )
329 sa = scale*sqrt( sum )
330 scale = dble( czero )
331 sum = dble( cone )
332 CALL zlassq( m*m, work(m*m+1), 1, scale, sum )
333 sb = scale*sqrt( sum )
334 strong = sa.LE.thresha .AND. sb.LE.threshb
335 IF( .NOT.strong )
336 $ GO TO 20
337 END IF
338*
339* If the swap is accepted ("weakly" and "strongly"), apply the
340* equivalence transformations to the original matrix pair (A,B)
341*
342 CALL zrot( j1+1, a( 1, j1 ), 1, a( 1, j1+1 ), 1, cz,
343 $ dconjg( sz ) )
344 CALL zrot( j1+1, b( 1, j1 ), 1, b( 1, j1+1 ), 1, cz,
345 $ dconjg( sz ) )
346 CALL zrot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda, cq,
347 $ sq )
348 CALL zrot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb, cq,
349 $ sq )
350*
351* Set N1 by N2 (2,1) blocks to 0
352*
353 a( j1+1, j1 ) = czero
354 b( j1+1, j1 ) = czero
355*
356* Accumulate transformations into Q and Z if requested.
357*
358 IF( wantz )
359 $ CALL zrot( n, z( 1, j1 ), 1, z( 1, j1+1 ), 1, cz,
360 $ dconjg( sz ) )
361 IF( wantq )
362 $ CALL zrot( n, q( 1, j1 ), 1, q( 1, j1+1 ), 1, cq,
363 $ dconjg( sq ) )
364*
365* Exit with INFO = 0 if swap was successfully performed.
366*
367 RETURN
368*
369* Exit with INFO = 1 if swap was rejected.
370*
371 20 CONTINUE
372 info = 1
373 RETURN
374*
375* End of ZTGEX2
376*
377 END
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
Definition zlacpy.f:101
subroutine zlartg(f, g, c, s, r)
ZLARTG generates a plane rotation with real cosine and complex sine.
Definition zlartg.f90:116
subroutine zlassq(n, x, incx, scale, sumsq)
ZLASSQ updates a sum of squares represented in scaled form.
Definition zlassq.f90:122
subroutine zrot(n, cx, incx, cy, incy, c, s)
ZROT applies a plane rotation with real cosine and complex sine to a pair of complex vectors.
Definition zrot.f:101
subroutine ztgex2(wantq, wantz, n, a, lda, b, ldb, q, ldq, z, ldz, j1, info)
ZTGEX2 swaps adjacent diagonal blocks in an upper (quasi) triangular matrix pair by an unitary equiva...
Definition ztgex2.f:188