LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
ctgex2.f
Go to the documentation of this file.
1*> \brief \b CTGEX2 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 CTGEX2 + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ctgex2.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ctgex2.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ctgex2.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE CTGEX2( 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 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
28* $ Z( LDZ, * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> CTGEX2 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 array, dimension (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 array, dimension (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 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 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 ctgex2( 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 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
199 $ z( ldz, * )
200* ..
201*
202* =====================================================================
203*
204* .. Parameters ..
205 COMPLEX CZERO, CONE
206 parameter( czero = ( 0.0e+0, 0.0e+0 ),
207 $ cone = ( 1.0e+0, 0.0e+0 ) )
208 REAL TWENTY
209 parameter( twenty = 2.0e+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 REAL CQ, CZ, EPS, SA, SB, SCALE, SMLNUM, SUM,
219 $ thresha, threshb
220 COMPLEX CDUM, F, G, SQ, SZ
221* ..
222* .. Local Arrays ..
223 COMPLEX S( LDST, LDST ), T( LDST, LDST ), WORK( 8 )
224* ..
225* .. External Functions ..
226 REAL SLAMCH
227 EXTERNAL slamch
228* ..
229* .. External Subroutines ..
230 EXTERNAL clacpy, clartg, classq, crot
231* ..
232* .. Intrinsic Functions ..
233 INTRINSIC abs, conjg, max, real, 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 clacpy( 'Full', m, m, a( j1, j1 ), lda, s, ldst )
251 CALL clacpy( 'Full', m, m, b( j1, j1 ), ldb, t, ldst )
252*
253* Compute the threshold for testing the acceptance of swapping.
254*
255 eps = slamch( 'P' )
256 smlnum = slamch( 'S' ) / eps
257 scale = real( czero )
258 sum = real( cone )
259 CALL clacpy( 'Full', m, m, s, ldst, work, m )
260 CALL clacpy( 'Full', m, m, t, ldst, work( m*m+1 ), m )
261 CALL classq( m*m, work, 1, scale, sum )
262 sa = scale*sqrt( sum )
263 scale = dble( czero )
264 sum = dble( cone )
265 CALL classq( 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 clartg( g, f, cz, sz, cdum )
287 sz = -sz
288 CALL crot( 2, s( 1, 1 ), 1, s( 1, 2 ), 1, cz, conjg( sz ) )
289 CALL crot( 2, t( 1, 1 ), 1, t( 1, 2 ), 1, cz, conjg( sz ) )
290 IF( sa.GE.sb ) THEN
291 CALL clartg( s( 1, 1 ), s( 2, 1 ), cq, sq, cdum )
292 ELSE
293 CALL clartg( t( 1, 1 ), t( 2, 1 ), cq, sq, cdum )
294 END IF
295 CALL crot( 2, s( 1, 1 ), ldst, s( 2, 1 ), ldst, cq, sq )
296 CALL crot( 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, B-QL**H*T*QR)) <= O(EPS*F-norm((A, B)))
310*
311 CALL clacpy( 'Full', m, m, s, ldst, work, m )
312 CALL clacpy( 'Full', m, m, t, ldst, work( m*m+1 ), m )
313 CALL crot( 2, work, 1, work( 3 ), 1, cz, -conjg( sz ) )
314 CALL crot( 2, work( 5 ), 1, work( 7 ), 1, cz, -conjg( sz ) )
315 CALL crot( 2, work, 2, work( 2 ), 2, cq, -sq )
316 CALL crot( 2, work( 5 ), 2, work( 6 ), 2, cq, -sq )
317 DO 10 i = 1, 2
318 work( i ) = work( i ) - a( j1+i-1, j1 )
319 work( i+2 ) = work( i+2 ) - a( j1+i-1, j1+1 )
320 work( i+4 ) = work( i+4 ) - b( j1+i-1, j1 )
321 work( i+6 ) = work( i+6 ) - b( j1+i-1, j1+1 )
322 10 CONTINUE
323 scale = dble( czero )
324 sum = dble( cone )
325 CALL classq( m*m, work, 1, scale, sum )
326 sa = scale*sqrt( sum )
327 scale = dble( czero )
328 sum = dble( cone )
329 CALL classq( m*m, work(m*m+1), 1, scale, sum )
330 sb = scale*sqrt( sum )
331 strong = sa.LE.thresha .AND. sb.LE.threshb
332 IF( .NOT.strong )
333 $ GO TO 20
334 END IF
335*
336* If the swap is accepted ("weakly" and "strongly"), apply the
337* equivalence transformations to the original matrix pair (A,B)
338*
339 CALL crot( j1+1, a( 1, j1 ), 1, a( 1, j1+1 ), 1, cz,
340 $ conjg( sz ) )
341 CALL crot( j1+1, b( 1, j1 ), 1, b( 1, j1+1 ), 1, cz,
342 $ conjg( sz ) )
343 CALL crot( n-j1+1, a( j1, j1 ), lda, a( j1+1, j1 ), lda, cq,
344 $ sq )
345 CALL crot( n-j1+1, b( j1, j1 ), ldb, b( j1+1, j1 ), ldb, cq,
346 $ sq )
347*
348* Set N1 by N2 (2,1) blocks to 0
349*
350 a( j1+1, j1 ) = czero
351 b( j1+1, j1 ) = czero
352*
353* Accumulate transformations into Q and Z if requested.
354*
355 IF( wantz )
356 $ CALL crot( n, z( 1, j1 ), 1, z( 1, j1+1 ), 1, cz,
357 $ conjg( sz ) )
358 IF( wantq )
359 $ CALL crot( n, q( 1, j1 ), 1, q( 1, j1+1 ), 1, cq,
360 $ conjg( sq ) )
361*
362* Exit with INFO = 0 if swap was successfully performed.
363*
364 RETURN
365*
366* Exit with INFO = 1 if swap was rejected.
367*
368 20 CONTINUE
369 info = 1
370 RETURN
371*
372* End of CTGEX2
373*
374 END
subroutine clacpy(uplo, m, n, a, lda, b, ldb)
CLACPY copies all or part of one two-dimensional array to another.
Definition clacpy.f:101
subroutine clartg(f, g, c, s, r)
CLARTG generates a plane rotation with real cosine and complex sine.
Definition clartg.f90:116
subroutine classq(n, x, incx, scale, sumsq)
CLASSQ updates a sum of squares represented in scaled form.
Definition classq.f90:122
subroutine crot(n, cx, incx, cy, incy, c, s)
CROT applies a plane rotation with real cosine and complex sine to a pair of complex vectors.
Definition crot.f:101
subroutine ctgex2(wantq, wantz, n, a, lda, b, ldb, q, ldq, z, ldz, j1, info)
CTGEX2 swaps adjacent diagonal blocks in an upper (quasi) triangular matrix pair by an unitary equiva...
Definition ctgex2.f:188