LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
zgghd3.f
Go to the documentation of this file.
1*> \brief \b ZGGHD3
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download ZGGHD3 + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgghd3.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgghd3.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgghd3.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE ZGGHD3( COMPQ, COMPZ, N, ILO, IHI, A, LDA, B, LDB, Q,
20* LDQ, Z, LDZ, WORK, LWORK, INFO )
21*
22* .. Scalar Arguments ..
23* CHARACTER COMPQ, COMPZ
24* INTEGER IHI, ILO, INFO, LDA, LDB, LDQ, LDZ, N, LWORK
25* ..
26* .. Array Arguments ..
27* COMPLEX*16 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
28* $ Z( LDZ, * ), WORK( * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> ZGGHD3 reduces a pair of complex matrices (A,B) to generalized upper
38*> Hessenberg form using unitary transformations, where A is a
39*> general matrix and B is upper triangular. The form of the
40*> generalized eigenvalue problem is
41*> A*x = lambda*B*x,
42*> and B is typically made upper triangular by computing its QR
43*> factorization and moving the unitary matrix Q to the left side
44*> of the equation.
45*>
46*> This subroutine simultaneously reduces A to a Hessenberg matrix H:
47*> Q**H*A*Z = H
48*> and transforms B to another upper triangular matrix T:
49*> Q**H*B*Z = T
50*> in order to reduce the problem to its standard form
51*> H*y = lambda*T*y
52*> where y = Z**H*x.
53*>
54*> The unitary matrices Q and Z are determined as products of Givens
55*> rotations. They may either be formed explicitly, or they may be
56*> postmultiplied into input matrices Q1 and Z1, so that
57*> Q1 * A * Z1**H = (Q1*Q) * H * (Z1*Z)**H
58*> Q1 * B * Z1**H = (Q1*Q) * T * (Z1*Z)**H
59*> If Q1 is the unitary matrix from the QR factorization of B in the
60*> original equation A*x = lambda*B*x, then ZGGHD3 reduces the original
61*> problem to generalized Hessenberg form.
62*>
63*> This is a blocked variant of CGGHRD, using matrix-matrix
64*> multiplications for parts of the computation to enhance performance.
65*> \endverbatim
66*
67* Arguments:
68* ==========
69*
70*> \param[in] COMPQ
71*> \verbatim
72*> COMPQ is CHARACTER*1
73*> = 'N': do not compute Q;
74*> = 'I': Q is initialized to the unit matrix, and the
75*> unitary matrix Q is returned;
76*> = 'V': Q must contain a unitary matrix Q1 on entry,
77*> and the product Q1*Q is returned.
78*> \endverbatim
79*>
80*> \param[in] COMPZ
81*> \verbatim
82*> COMPZ is CHARACTER*1
83*> = 'N': do not compute Z;
84*> = 'I': Z is initialized to the unit matrix, and the
85*> unitary matrix Z is returned;
86*> = 'V': Z must contain a unitary matrix Z1 on entry,
87*> and the product Z1*Z is returned.
88*> \endverbatim
89*>
90*> \param[in] N
91*> \verbatim
92*> N is INTEGER
93*> The order of the matrices A and B. N >= 0.
94*> \endverbatim
95*>
96*> \param[in] ILO
97*> \verbatim
98*> ILO is INTEGER
99*> \endverbatim
100*>
101*> \param[in] IHI
102*> \verbatim
103*> IHI is INTEGER
104*>
105*> ILO and IHI mark the rows and columns of A which are to be
106*> reduced. It is assumed that A is already upper triangular
107*> in rows and columns 1:ILO-1 and IHI+1:N. ILO and IHI are
108*> normally set by a previous call to ZGGBAL; otherwise they
109*> should be set to 1 and N respectively.
110*> 1 <= ILO <= IHI <= N, if N > 0; ILO=1 and IHI=0, if N=0.
111*> \endverbatim
112*>
113*> \param[in,out] A
114*> \verbatim
115*> A is COMPLEX*16 array, dimension (LDA, N)
116*> On entry, the N-by-N general matrix to be reduced.
117*> On exit, the upper triangle and the first subdiagonal of A
118*> are overwritten with the upper Hessenberg matrix H, and the
119*> rest is set to zero.
120*> \endverbatim
121*>
122*> \param[in] LDA
123*> \verbatim
124*> LDA is INTEGER
125*> The leading dimension of the array A. LDA >= max(1,N).
126*> \endverbatim
127*>
128*> \param[in,out] B
129*> \verbatim
130*> B is COMPLEX*16 array, dimension (LDB, N)
131*> On entry, the N-by-N upper triangular matrix B.
132*> On exit, the upper triangular matrix T = Q**H B Z. The
133*> elements below the diagonal are set to zero.
134*> \endverbatim
135*>
136*> \param[in] LDB
137*> \verbatim
138*> LDB is INTEGER
139*> The leading dimension of the array B. LDB >= max(1,N).
140*> \endverbatim
141*>
142*> \param[in,out] Q
143*> \verbatim
144*> Q is COMPLEX*16 array, dimension (LDQ, N)
145*> On entry, if COMPQ = 'V', the unitary matrix Q1, typically
146*> from the QR factorization of B.
147*> On exit, if COMPQ='I', the unitary matrix Q, and if
148*> COMPQ = 'V', the product Q1*Q.
149*> Not referenced if COMPQ='N'.
150*> \endverbatim
151*>
152*> \param[in] LDQ
153*> \verbatim
154*> LDQ is INTEGER
155*> The leading dimension of the array Q.
156*> LDQ >= N if COMPQ='V' or 'I'; LDQ >= 1 otherwise.
157*> \endverbatim
158*>
159*> \param[in,out] Z
160*> \verbatim
161*> Z is COMPLEX*16 array, dimension (LDZ, N)
162*> On entry, if COMPZ = 'V', the unitary matrix Z1.
163*> On exit, if COMPZ='I', the unitary matrix Z, and if
164*> COMPZ = 'V', the product Z1*Z.
165*> Not referenced if COMPZ='N'.
166*> \endverbatim
167*>
168*> \param[in] LDZ
169*> \verbatim
170*> LDZ is INTEGER
171*> The leading dimension of the array Z.
172*> LDZ >= N if COMPZ='V' or 'I'; LDZ >= 1 otherwise.
173*> \endverbatim
174*>
175*> \param[out] WORK
176*> \verbatim
177*> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
178*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
179*> \endverbatim
180*>
181*> \param[in] LWORK
182*> \verbatim
183*> LWORK is INTEGER
184*> The length of the array WORK. LWORK >= 1.
185*> For optimum performance LWORK >= 6*N*NB, where NB is the
186*> optimal blocksize.
187*>
188*> If LWORK = -1, then a workspace query is assumed; the routine
189*> only calculates the optimal size of the WORK array, returns
190*> this value as the first entry of the WORK array, and no error
191*> message related to LWORK is issued by XERBLA.
192*> \endverbatim
193*>
194*> \param[out] INFO
195*> \verbatim
196*> INFO is INTEGER
197*> = 0: successful exit.
198*> < 0: if INFO = -i, the i-th argument had an illegal value.
199*> \endverbatim
200*
201* Authors:
202* ========
203*
204*> \author Univ. of Tennessee
205*> \author Univ. of California Berkeley
206*> \author Univ. of Colorado Denver
207*> \author NAG Ltd.
208*
209*> \ingroup gghd3
210*
211*> \par Further Details:
212* =====================
213*>
214*> \verbatim
215*>
216*> This routine reduces A to Hessenberg form and maintains B in triangular form
217*> using a blocked variant of Moler and Stewart's original algorithm,
218*> as described by Kagstrom, Kressner, Quintana-Orti, and Quintana-Orti
219*> (BIT 2008).
220*> \endverbatim
221*>
222* =====================================================================
223 SUBROUTINE zgghd3( COMPQ, COMPZ, N, ILO, IHI, A, LDA, B, LDB,
224 $ Q,
225 $ LDQ, Z, LDZ, WORK, LWORK, INFO )
226*
227* -- LAPACK computational routine --
228* -- LAPACK is a software package provided by Univ. of Tennessee, --
229* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
230*
231 IMPLICIT NONE
232*
233* .. Scalar Arguments ..
234 CHARACTER COMPQ, COMPZ
235 INTEGER IHI, ILO, INFO, LDA, LDB, LDQ, LDZ, N, LWORK
236* ..
237* .. Array Arguments ..
238 COMPLEX*16 A( LDA, * ), B( LDB, * ), Q( LDQ, * ),
239 $ Z( LDZ, * ), WORK( * )
240* ..
241*
242* =====================================================================
243*
244* .. Parameters ..
245 COMPLEX*16 CONE, CZERO
246 PARAMETER ( CONE = ( 1.0d+0, 0.0d+0 ),
247 $ czero = ( 0.0d+0, 0.0d+0 ) )
248* ..
249* .. Local Scalars ..
250 LOGICAL BLK22, INITQ, INITZ, LQUERY, WANTQ, WANTZ
251 CHARACTER*1 COMPQ2, COMPZ2
252 INTEGER COLA, I, IERR, J, J0, JCOL, JJ, JROW, K,
253 $ kacc22, len, lwkopt, n2nb, nb, nblst, nbmin,
254 $ nh, nnb, nx, ppw, ppwo, pw, top, topq
255 DOUBLE PRECISION C
256 COMPLEX*16 C1, C2, CTEMP, S, S1, S2, TEMP, TEMP1, TEMP2,
257 $ temp3
258* ..
259* .. External Functions ..
260 LOGICAL LSAME
261 INTEGER ILAENV
262 EXTERNAL ilaenv, lsame
263* ..
264* .. External Subroutines ..
265 EXTERNAL zgghrd, zlartg, zlaset, zunm22, zrot,
266 $ zgemm,
268* ..
269* .. Intrinsic Functions ..
270 INTRINSIC dble, dcmplx, dconjg, max
271* ..
272* .. Executable Statements ..
273*
274* Decode and test the input parameters.
275*
276 info = 0
277 nb = ilaenv( 1, 'ZGGHD3', ' ', n, ilo, ihi, -1 )
278 nh = ihi - ilo + 1
279 IF( nh.LE.1 ) THEN
280 lwkopt = 1
281 ELSE
282 lwkopt = 6*n*nb
283 END IF
284 work( 1 ) = dcmplx( lwkopt )
285 initq = lsame( compq, 'I' )
286 wantq = initq .OR. lsame( compq, 'V' )
287 initz = lsame( compz, 'I' )
288 wantz = initz .OR. lsame( compz, 'V' )
289 lquery = ( lwork.EQ.-1 )
290*
291 IF( .NOT.lsame( compq, 'N' ) .AND. .NOT.wantq ) THEN
292 info = -1
293 ELSE IF( .NOT.lsame( compz, 'N' ) .AND. .NOT.wantz ) THEN
294 info = -2
295 ELSE IF( n.LT.0 ) THEN
296 info = -3
297 ELSE IF( ilo.LT.1 ) THEN
298 info = -4
299 ELSE IF( ihi.GT.n .OR. ihi.LT.ilo-1 ) THEN
300 info = -5
301 ELSE IF( lda.LT.max( 1, n ) ) THEN
302 info = -7
303 ELSE IF( ldb.LT.max( 1, n ) ) THEN
304 info = -9
305 ELSE IF( ( wantq .AND. ldq.LT.n ) .OR. ldq.LT.1 ) THEN
306 info = -11
307 ELSE IF( ( wantz .AND. ldz.LT.n ) .OR. ldz.LT.1 ) THEN
308 info = -13
309 ELSE IF( lwork.LT.1 .AND. .NOT.lquery ) THEN
310 info = -15
311 END IF
312 IF( info.NE.0 ) THEN
313 CALL xerbla( 'ZGGHD3', -info )
314 RETURN
315 ELSE IF( lquery ) THEN
316 RETURN
317 END IF
318*
319* Initialize Q and Z if desired.
320*
321 IF( initq )
322 $ CALL zlaset( 'All', n, n, czero, cone, q, ldq )
323 IF( initz )
324 $ CALL zlaset( 'All', n, n, czero, cone, z, ldz )
325*
326* Zero out lower triangle of B.
327*
328 IF( n.GT.1 )
329 $ CALL zlaset( 'Lower', n-1, n-1, czero, czero, b(2, 1), ldb )
330*
331* Quick return if possible
332*
333 IF( nh.LE.1 ) THEN
334 work( 1 ) = cone
335 RETURN
336 END IF
337*
338* Determine the blocksize.
339*
340 nbmin = ilaenv( 2, 'ZGGHD3', ' ', n, ilo, ihi, -1 )
341 IF( nb.GT.1 .AND. nb.LT.nh ) THEN
342*
343* Determine when to use unblocked instead of blocked code.
344*
345 nx = max( nb, ilaenv( 3, 'ZGGHD3', ' ', n, ilo, ihi, -1 ) )
346 IF( nx.LT.nh ) THEN
347*
348* Determine if workspace is large enough for blocked code.
349*
350 IF( lwork.LT.lwkopt ) THEN
351*
352* Not enough workspace to use optimal NB: determine the
353* minimum value of NB, and reduce NB or force use of
354* unblocked code.
355*
356 nbmin = max( 2, ilaenv( 2, 'ZGGHD3', ' ', n, ilo, ihi,
357 $ -1 ) )
358 IF( lwork.GE.6*n*nbmin ) THEN
359 nb = lwork / ( 6*n )
360 ELSE
361 nb = 1
362 END IF
363 END IF
364 END IF
365 END IF
366*
367 IF( nb.LT.nbmin .OR. nb.GE.nh ) THEN
368*
369* Use unblocked code below
370*
371 jcol = ilo
372*
373 ELSE
374*
375* Use blocked code
376*
377 kacc22 = ilaenv( 16, 'ZGGHD3', ' ', n, ilo, ihi, -1 )
378 blk22 = kacc22.EQ.2
379 DO jcol = ilo, ihi-2, nb
380 nnb = min( nb, ihi-jcol-1 )
381*
382* Initialize small unitary factors that will hold the
383* accumulated Givens rotations in workspace.
384* N2NB denotes the number of 2*NNB-by-2*NNB factors
385* NBLST denotes the (possibly smaller) order of the last
386* factor.
387*
388 n2nb = ( ihi-jcol-1 ) / nnb - 1
389 nblst = ihi - jcol - n2nb*nnb
390 CALL zlaset( 'All', nblst, nblst, czero, cone, work,
391 $ nblst )
392 pw = nblst * nblst + 1
393 DO i = 1, n2nb
394 CALL zlaset( 'All', 2*nnb, 2*nnb, czero, cone,
395 $ work( pw ), 2*nnb )
396 pw = pw + 4*nnb*nnb
397 END DO
398*
399* Reduce columns JCOL:JCOL+NNB-1 of A to Hessenberg form.
400*
401 DO j = jcol, jcol+nnb-1
402*
403* Reduce Jth column of A. Store cosines and sines in Jth
404* column of A and B, respectively.
405*
406 DO i = ihi, j+2, -1
407 temp = a( i-1, j )
408 CALL zlartg( temp, a( i, j ), c, s, a( i-1, j ) )
409 a( i, j ) = dcmplx( c )
410 b( i, j ) = s
411 END DO
412*
413* Accumulate Givens rotations into workspace array.
414*
415 ppw = ( nblst + 1 )*( nblst - 2 ) - j + jcol + 1
416 len = 2 + j - jcol
417 jrow = j + n2nb*nnb + 2
418 DO i = ihi, jrow, -1
419 ctemp = a( i, j )
420 s = b( i, j )
421 DO jj = ppw, ppw+len-1
422 temp = work( jj + nblst )
423 work( jj + nblst ) = ctemp*temp - s*work( jj )
424 work( jj ) = dconjg( s )*temp + ctemp*work( jj )
425 END DO
426 len = len + 1
427 ppw = ppw - nblst - 1
428 END DO
429*
430 ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2*nnb + nnb
431 j0 = jrow - nnb
432 DO jrow = j0, j+2, -nnb
433 ppw = ppwo
434 len = 2 + j - jcol
435 DO i = jrow+nnb-1, jrow, -1
436 ctemp = a( i, j )
437 s = b( i, j )
438 DO jj = ppw, ppw+len-1
439 temp = work( jj + 2*nnb )
440 work( jj + 2*nnb ) = ctemp*temp - s*work( jj )
441 work( jj ) = dconjg( s )*temp + ctemp*work( jj )
442 END DO
443 len = len + 1
444 ppw = ppw - 2*nnb - 1
445 END DO
446 ppwo = ppwo + 4*nnb*nnb
447 END DO
448*
449* TOP denotes the number of top rows in A and B that will
450* not be updated during the next steps.
451*
452 IF( jcol.LE.2 ) THEN
453 top = 0
454 ELSE
455 top = jcol
456 END IF
457*
458* Propagate transformations through B and replace stored
459* left sines/cosines by right sines/cosines.
460*
461 DO jj = n, j+1, -1
462*
463* Update JJth column of B.
464*
465 DO i = min( jj+1, ihi ), j+2, -1
466 ctemp = a( i, j )
467 s = b( i, j )
468 temp = b( i, jj )
469 b( i, jj ) = ctemp*temp - dconjg( s )*b( i-1, jj )
470 b( i-1, jj ) = s*temp + ctemp*b( i-1, jj )
471 END DO
472*
473* Annihilate B( JJ+1, JJ ).
474*
475 IF( jj.LT.ihi ) THEN
476 temp = b( jj+1, jj+1 )
477 CALL zlartg( temp, b( jj+1, jj ), c, s,
478 $ b( jj+1, jj+1 ) )
479 b( jj+1, jj ) = czero
480 CALL zrot( jj-top, b( top+1, jj+1 ), 1,
481 $ b( top+1, jj ), 1, c, s )
482 a( jj+1, j ) = dcmplx( c )
483 b( jj+1, j ) = -dconjg( s )
484 END IF
485 END DO
486*
487* Update A by transformations from right.
488*
489 jj = mod( ihi-j-1, 3 )
490 DO i = ihi-j-3, jj+1, -3
491 ctemp = a( j+1+i, j )
492 s = -b( j+1+i, j )
493 c1 = a( j+2+i, j )
494 s1 = -b( j+2+i, j )
495 c2 = a( j+3+i, j )
496 s2 = -b( j+3+i, j )
497*
498 DO k = top+1, ihi
499 temp = a( k, j+i )
500 temp1 = a( k, j+i+1 )
501 temp2 = a( k, j+i+2 )
502 temp3 = a( k, j+i+3 )
503 a( k, j+i+3 ) = c2*temp3 + dconjg( s2 )*temp2
504 temp2 = -s2*temp3 + c2*temp2
505 a( k, j+i+2 ) = c1*temp2 + dconjg( s1 )*temp1
506 temp1 = -s1*temp2 + c1*temp1
507 a( k, j+i+1 ) = ctemp*temp1 + dconjg( s )*temp
508 a( k, j+i ) = -s*temp1 + ctemp*temp
509 END DO
510 END DO
511*
512 IF( jj.GT.0 ) THEN
513 DO i = jj, 1, -1
514 c = dble( a( j+1+i, j ) )
515 CALL zrot( ihi-top, a( top+1, j+i+1 ), 1,
516 $ a( top+1, j+i ), 1, c,
517 $ -dconjg( b( j+1+i, j ) ) )
518 END DO
519 END IF
520*
521* Update (J+1)th column of A by transformations from left.
522*
523 IF ( j .LT. jcol + nnb - 1 ) THEN
524 len = 1 + j - jcol
525*
526* Multiply with the trailing accumulated unitary
527* matrix, which takes the form
528*
529* [ U11 U12 ]
530* U = [ ],
531* [ U21 U22 ]
532*
533* where U21 is a LEN-by-LEN matrix and U12 is lower
534* triangular.
535*
536 jrow = ihi - nblst + 1
537 CALL zgemv( 'Conjugate', nblst, len, cone, work,
538 $ nblst, a( jrow, j+1 ), 1, czero,
539 $ work( pw ), 1 )
540 ppw = pw + len
541 DO i = jrow, jrow+nblst-len-1
542 work( ppw ) = a( i, j+1 )
543 ppw = ppw + 1
544 END DO
545 CALL ztrmv( 'Lower', 'Conjugate', 'Non-unit',
546 $ nblst-len, work( len*nblst + 1 ), nblst,
547 $ work( pw+len ), 1 )
548 CALL zgemv( 'Conjugate', len, nblst-len, cone,
549 $ work( (len+1)*nblst - len + 1 ), nblst,
550 $ a( jrow+nblst-len, j+1 ), 1, cone,
551 $ work( pw+len ), 1 )
552 ppw = pw
553 DO i = jrow, jrow+nblst-1
554 a( i, j+1 ) = work( ppw )
555 ppw = ppw + 1
556 END DO
557*
558* Multiply with the other accumulated unitary
559* matrices, which take the form
560*
561* [ U11 U12 0 ]
562* [ ]
563* U = [ U21 U22 0 ],
564* [ ]
565* [ 0 0 I ]
566*
567* where I denotes the (NNB-LEN)-by-(NNB-LEN) identity
568* matrix, U21 is a LEN-by-LEN upper triangular matrix
569* and U12 is an NNB-by-NNB lower triangular matrix.
570*
571 ppwo = 1 + nblst*nblst
572 j0 = jrow - nnb
573 DO jrow = j0, jcol+1, -nnb
574 ppw = pw + len
575 DO i = jrow, jrow+nnb-1
576 work( ppw ) = a( i, j+1 )
577 ppw = ppw + 1
578 END DO
579 ppw = pw
580 DO i = jrow+nnb, jrow+nnb+len-1
581 work( ppw ) = a( i, j+1 )
582 ppw = ppw + 1
583 END DO
584 CALL ztrmv( 'Upper', 'Conjugate', 'Non-unit',
585 $ len,
586 $ work( ppwo + nnb ), 2*nnb, work( pw ),
587 $ 1 )
588 CALL ztrmv( 'Lower', 'Conjugate', 'Non-unit',
589 $ nnb,
590 $ work( ppwo + 2*len*nnb ),
591 $ 2*nnb, work( pw + len ), 1 )
592 CALL zgemv( 'Conjugate', nnb, len, cone,
593 $ work( ppwo ), 2*nnb, a( jrow, j+1 ), 1,
594 $ cone, work( pw ), 1 )
595 CALL zgemv( 'Conjugate', len, nnb, cone,
596 $ work( ppwo + 2*len*nnb + nnb ), 2*nnb,
597 $ a( jrow+nnb, j+1 ), 1, cone,
598 $ work( pw+len ), 1 )
599 ppw = pw
600 DO i = jrow, jrow+len+nnb-1
601 a( i, j+1 ) = work( ppw )
602 ppw = ppw + 1
603 END DO
604 ppwo = ppwo + 4*nnb*nnb
605 END DO
606 END IF
607 END DO
608*
609* Apply accumulated unitary matrices to A.
610*
611 cola = n - jcol - nnb + 1
612 j = ihi - nblst + 1
613 CALL zgemm( 'Conjugate', 'No Transpose', nblst,
614 $ cola, nblst, cone, work, nblst,
615 $ a( j, jcol+nnb ), lda, czero, work( pw ),
616 $ nblst )
617 CALL zlacpy( 'All', nblst, cola, work( pw ), nblst,
618 $ a( j, jcol+nnb ), lda )
619 ppwo = nblst*nblst + 1
620 j0 = j - nnb
621 DO j = j0, jcol+1, -nnb
622 IF ( blk22 ) THEN
623*
624* Exploit the structure of
625*
626* [ U11 U12 ]
627* U = [ ]
628* [ U21 U22 ],
629*
630* where all blocks are NNB-by-NNB, U21 is upper
631* triangular and U12 is lower triangular.
632*
633 CALL zunm22( 'Left', 'Conjugate', 2*nnb, cola, nnb,
634 $ nnb, work( ppwo ), 2*nnb,
635 $ a( j, jcol+nnb ), lda, work( pw ),
636 $ lwork-pw+1, ierr )
637 ELSE
638*
639* Ignore the structure of U.
640*
641 CALL zgemm( 'Conjugate', 'No Transpose', 2*nnb,
642 $ cola, 2*nnb, cone, work( ppwo ), 2*nnb,
643 $ a( j, jcol+nnb ), lda, czero, work( pw ),
644 $ 2*nnb )
645 CALL zlacpy( 'All', 2*nnb, cola, work( pw ), 2*nnb,
646 $ a( j, jcol+nnb ), lda )
647 END IF
648 ppwo = ppwo + 4*nnb*nnb
649 END DO
650*
651* Apply accumulated unitary matrices to Q.
652*
653 IF( wantq ) THEN
654 j = ihi - nblst + 1
655 IF ( initq ) THEN
656 topq = max( 2, j - jcol + 1 )
657 nh = ihi - topq + 1
658 ELSE
659 topq = 1
660 nh = n
661 END IF
662 CALL zgemm( 'No Transpose', 'No Transpose', nh,
663 $ nblst, nblst, cone, q( topq, j ), ldq,
664 $ work, nblst, czero, work( pw ), nh )
665 CALL zlacpy( 'All', nh, nblst, work( pw ), nh,
666 $ q( topq, j ), ldq )
667 ppwo = nblst*nblst + 1
668 j0 = j - nnb
669 DO j = j0, jcol+1, -nnb
670 IF ( initq ) THEN
671 topq = max( 2, j - jcol + 1 )
672 nh = ihi - topq + 1
673 END IF
674 IF ( blk22 ) THEN
675*
676* Exploit the structure of U.
677*
678 CALL zunm22( 'Right', 'No Transpose', nh, 2*nnb,
679 $ nnb, nnb, work( ppwo ), 2*nnb,
680 $ q( topq, j ), ldq, work( pw ),
681 $ lwork-pw+1, ierr )
682 ELSE
683*
684* Ignore the structure of U.
685*
686 CALL zgemm( 'No Transpose', 'No Transpose', nh,
687 $ 2*nnb, 2*nnb, cone, q( topq, j ), ldq,
688 $ work( ppwo ), 2*nnb, czero, work( pw ),
689 $ nh )
690 CALL zlacpy( 'All', nh, 2*nnb, work( pw ), nh,
691 $ q( topq, j ), ldq )
692 END IF
693 ppwo = ppwo + 4*nnb*nnb
694 END DO
695 END IF
696*
697* Accumulate right Givens rotations if required.
698*
699 IF ( wantz .OR. top.GT.0 ) THEN
700*
701* Initialize small unitary factors that will hold the
702* accumulated Givens rotations in workspace.
703*
704 CALL zlaset( 'All', nblst, nblst, czero, cone, work,
705 $ nblst )
706 pw = nblst * nblst + 1
707 DO i = 1, n2nb
708 CALL zlaset( 'All', 2*nnb, 2*nnb, czero, cone,
709 $ work( pw ), 2*nnb )
710 pw = pw + 4*nnb*nnb
711 END DO
712*
713* Accumulate Givens rotations into workspace array.
714*
715 DO j = jcol, jcol+nnb-1
716 ppw = ( nblst + 1 )*( nblst - 2 ) - j + jcol + 1
717 len = 2 + j - jcol
718 jrow = j + n2nb*nnb + 2
719 DO i = ihi, jrow, -1
720 ctemp = a( i, j )
721 a( i, j ) = czero
722 s = b( i, j )
723 b( i, j ) = czero
724 DO jj = ppw, ppw+len-1
725 temp = work( jj + nblst )
726 work( jj + nblst ) = ctemp*temp -
727 $ dconjg( s )*work( jj )
728 work( jj ) = s*temp + ctemp*work( jj )
729 END DO
730 len = len + 1
731 ppw = ppw - nblst - 1
732 END DO
733*
734 ppwo = nblst*nblst + ( nnb+j-jcol-1 )*2*nnb + nnb
735 j0 = jrow - nnb
736 DO jrow = j0, j+2, -nnb
737 ppw = ppwo
738 len = 2 + j - jcol
739 DO i = jrow+nnb-1, jrow, -1
740 ctemp = a( i, j )
741 a( i, j ) = czero
742 s = b( i, j )
743 b( i, j ) = czero
744 DO jj = ppw, ppw+len-1
745 temp = work( jj + 2*nnb )
746 work( jj + 2*nnb ) = ctemp*temp -
747 $ dconjg( s )*work( jj )
748 work( jj ) = s*temp + ctemp*work( jj )
749 END DO
750 len = len + 1
751 ppw = ppw - 2*nnb - 1
752 END DO
753 ppwo = ppwo + 4*nnb*nnb
754 END DO
755 END DO
756 ELSE
757*
758 CALL zlaset( 'Lower', ihi - jcol - 1, nnb, czero,
759 $ czero,
760 $ a( jcol + 2, jcol ), lda )
761 CALL zlaset( 'Lower', ihi - jcol - 1, nnb, czero,
762 $ czero,
763 $ b( jcol + 2, jcol ), ldb )
764 END IF
765*
766* Apply accumulated unitary matrices to A and B.
767*
768 IF ( top.GT.0 ) THEN
769 j = ihi - nblst + 1
770 CALL zgemm( 'No Transpose', 'No Transpose', top,
771 $ nblst, nblst, cone, a( 1, j ), lda,
772 $ work, nblst, czero, work( pw ), top )
773 CALL zlacpy( 'All', top, nblst, work( pw ), top,
774 $ a( 1, j ), lda )
775 ppwo = nblst*nblst + 1
776 j0 = j - nnb
777 DO j = j0, jcol+1, -nnb
778 IF ( blk22 ) THEN
779*
780* Exploit the structure of U.
781*
782 CALL zunm22( 'Right', 'No Transpose', top,
783 $ 2*nnb,
784 $ nnb, nnb, work( ppwo ), 2*nnb,
785 $ a( 1, j ), lda, work( pw ),
786 $ lwork-pw+1, ierr )
787 ELSE
788*
789* Ignore the structure of U.
790*
791 CALL zgemm( 'No Transpose', 'No Transpose', top,
792 $ 2*nnb, 2*nnb, cone, a( 1, j ), lda,
793 $ work( ppwo ), 2*nnb, czero,
794 $ work( pw ), top )
795 CALL zlacpy( 'All', top, 2*nnb, work( pw ), top,
796 $ a( 1, j ), lda )
797 END IF
798 ppwo = ppwo + 4*nnb*nnb
799 END DO
800*
801 j = ihi - nblst + 1
802 CALL zgemm( 'No Transpose', 'No Transpose', top,
803 $ nblst, nblst, cone, b( 1, j ), ldb,
804 $ work, nblst, czero, work( pw ), top )
805 CALL zlacpy( 'All', top, nblst, work( pw ), top,
806 $ b( 1, j ), ldb )
807 ppwo = nblst*nblst + 1
808 j0 = j - nnb
809 DO j = j0, jcol+1, -nnb
810 IF ( blk22 ) THEN
811*
812* Exploit the structure of U.
813*
814 CALL zunm22( 'Right', 'No Transpose', top,
815 $ 2*nnb,
816 $ nnb, nnb, work( ppwo ), 2*nnb,
817 $ b( 1, j ), ldb, work( pw ),
818 $ lwork-pw+1, ierr )
819 ELSE
820*
821* Ignore the structure of U.
822*
823 CALL zgemm( 'No Transpose', 'No Transpose', top,
824 $ 2*nnb, 2*nnb, cone, b( 1, j ), ldb,
825 $ work( ppwo ), 2*nnb, czero,
826 $ work( pw ), top )
827 CALL zlacpy( 'All', top, 2*nnb, work( pw ), top,
828 $ b( 1, j ), ldb )
829 END IF
830 ppwo = ppwo + 4*nnb*nnb
831 END DO
832 END IF
833*
834* Apply accumulated unitary matrices to Z.
835*
836 IF( wantz ) THEN
837 j = ihi - nblst + 1
838 IF ( initq ) THEN
839 topq = max( 2, j - jcol + 1 )
840 nh = ihi - topq + 1
841 ELSE
842 topq = 1
843 nh = n
844 END IF
845 CALL zgemm( 'No Transpose', 'No Transpose', nh,
846 $ nblst, nblst, cone, z( topq, j ), ldz,
847 $ work, nblst, czero, work( pw ), nh )
848 CALL zlacpy( 'All', nh, nblst, work( pw ), nh,
849 $ z( topq, j ), ldz )
850 ppwo = nblst*nblst + 1
851 j0 = j - nnb
852 DO j = j0, jcol+1, -nnb
853 IF ( initq ) THEN
854 topq = max( 2, j - jcol + 1 )
855 nh = ihi - topq + 1
856 END IF
857 IF ( blk22 ) THEN
858*
859* Exploit the structure of U.
860*
861 CALL zunm22( 'Right', 'No Transpose', nh, 2*nnb,
862 $ nnb, nnb, work( ppwo ), 2*nnb,
863 $ z( topq, j ), ldz, work( pw ),
864 $ lwork-pw+1, ierr )
865 ELSE
866*
867* Ignore the structure of U.
868*
869 CALL zgemm( 'No Transpose', 'No Transpose', nh,
870 $ 2*nnb, 2*nnb, cone, z( topq, j ), ldz,
871 $ work( ppwo ), 2*nnb, czero, work( pw ),
872 $ nh )
873 CALL zlacpy( 'All', nh, 2*nnb, work( pw ), nh,
874 $ z( topq, j ), ldz )
875 END IF
876 ppwo = ppwo + 4*nnb*nnb
877 END DO
878 END IF
879 END DO
880 END IF
881*
882* Use unblocked code to reduce the rest of the matrix
883* Avoid re-initialization of modified Q and Z.
884*
885 compq2 = compq
886 compz2 = compz
887 IF ( jcol.NE.ilo ) THEN
888 IF ( wantq )
889 $ compq2 = 'V'
890 IF ( wantz )
891 $ compz2 = 'V'
892 END IF
893*
894 IF ( jcol.LT.ihi )
895 $ CALL zgghrd( compq2, compz2, n, jcol, ihi, a, lda, b, ldb,
896 $ q,
897 $ ldq, z, ldz, ierr )
898*
899 work( 1 ) = dcmplx( lwkopt )
900*
901 RETURN
902*
903* End of ZGGHD3
904*
905 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
Definition zgemm.f:188
subroutine zgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
ZGEMV
Definition zgemv.f:160
subroutine zgghd3(compq, compz, n, ilo, ihi, a, lda, b, ldb, q, ldq, z, ldz, work, lwork, info)
ZGGHD3
Definition zgghd3.f:226
subroutine zgghrd(compq, compz, n, ilo, ihi, a, lda, b, ldb, q, ldq, z, ldz, info)
ZGGHRD
Definition zgghrd.f:203
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 zlaset(uplo, m, n, alpha, beta, a, lda)
ZLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition zlaset.f:104
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 ztrmv(uplo, trans, diag, n, a, lda, x, incx)
ZTRMV
Definition ztrmv.f:147
subroutine zunm22(side, trans, m, n, n1, n2, q, ldq, c, ldc, work, lwork, info)
ZUNM22 multiplies a general matrix by a banded unitary matrix.
Definition zunm22.f:160