Return to zhbgst.f CVS log | Up to [local] / rpl / lapack / lapack |
1.9 bertrand 1: *> \brief \b ZHBGST
2: *
3: * =========== DOCUMENTATION ===========
4: *
1.15 bertrand 5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
1.9 bertrand 7: *
8: *> \htmlonly
1.15 bertrand 9: *> Download ZHBGST + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zhbgst.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zhbgst.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhbgst.f">
1.9 bertrand 15: *> [TXT]</a>
1.15 bertrand 16: *> \endhtmlonly
1.9 bertrand 17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE ZHBGST( VECT, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, X,
22: * LDX, WORK, RWORK, INFO )
1.15 bertrand 23: *
1.9 bertrand 24: * .. Scalar Arguments ..
25: * CHARACTER UPLO, VECT
26: * INTEGER INFO, KA, KB, LDAB, LDBB, LDX, N
27: * ..
28: * .. Array Arguments ..
29: * DOUBLE PRECISION RWORK( * )
30: * COMPLEX*16 AB( LDAB, * ), BB( LDBB, * ), WORK( * ),
31: * $ X( LDX, * )
32: * ..
1.15 bertrand 33: *
1.9 bertrand 34: *
35: *> \par Purpose:
36: * =============
37: *>
38: *> \verbatim
39: *>
40: *> ZHBGST reduces a complex Hermitian-definite banded generalized
41: *> eigenproblem A*x = lambda*B*x to standard form C*y = lambda*y,
42: *> such that C has the same bandwidth as A.
43: *>
44: *> B must have been previously factorized as S**H*S by ZPBSTF, using a
45: *> split Cholesky factorization. A is overwritten by C = X**H*A*X, where
46: *> X = S**(-1)*Q and Q is a unitary matrix chosen to preserve the
47: *> bandwidth of A.
48: *> \endverbatim
49: *
50: * Arguments:
51: * ==========
52: *
53: *> \param[in] VECT
54: *> \verbatim
55: *> VECT is CHARACTER*1
56: *> = 'N': do not form the transformation matrix X;
57: *> = 'V': form X.
58: *> \endverbatim
59: *>
60: *> \param[in] UPLO
61: *> \verbatim
62: *> UPLO is CHARACTER*1
63: *> = 'U': Upper triangle of A is stored;
64: *> = 'L': Lower triangle of A is stored.
65: *> \endverbatim
66: *>
67: *> \param[in] N
68: *> \verbatim
69: *> N is INTEGER
70: *> The order of the matrices A and B. N >= 0.
71: *> \endverbatim
72: *>
73: *> \param[in] KA
74: *> \verbatim
75: *> KA is INTEGER
76: *> The number of superdiagonals of the matrix A if UPLO = 'U',
77: *> or the number of subdiagonals if UPLO = 'L'. KA >= 0.
78: *> \endverbatim
79: *>
80: *> \param[in] KB
81: *> \verbatim
82: *> KB is INTEGER
83: *> The number of superdiagonals of the matrix B if UPLO = 'U',
84: *> or the number of subdiagonals if UPLO = 'L'. KA >= KB >= 0.
85: *> \endverbatim
86: *>
87: *> \param[in,out] AB
88: *> \verbatim
89: *> AB is COMPLEX*16 array, dimension (LDAB,N)
90: *> On entry, the upper or lower triangle of the Hermitian band
91: *> matrix A, stored in the first ka+1 rows of the array. The
92: *> j-th column of A is stored in the j-th column of the array AB
93: *> as follows:
94: *> if UPLO = 'U', AB(ka+1+i-j,j) = A(i,j) for max(1,j-ka)<=i<=j;
95: *> if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+ka).
96: *>
97: *> On exit, the transformed matrix X**H*A*X, stored in the same
98: *> format as A.
99: *> \endverbatim
100: *>
101: *> \param[in] LDAB
102: *> \verbatim
103: *> LDAB is INTEGER
104: *> The leading dimension of the array AB. LDAB >= KA+1.
105: *> \endverbatim
106: *>
107: *> \param[in] BB
108: *> \verbatim
109: *> BB is COMPLEX*16 array, dimension (LDBB,N)
110: *> The banded factor S from the split Cholesky factorization of
111: *> B, as returned by ZPBSTF, stored in the first kb+1 rows of
112: *> the array.
113: *> \endverbatim
114: *>
115: *> \param[in] LDBB
116: *> \verbatim
117: *> LDBB is INTEGER
118: *> The leading dimension of the array BB. LDBB >= KB+1.
119: *> \endverbatim
120: *>
121: *> \param[out] X
122: *> \verbatim
123: *> X is COMPLEX*16 array, dimension (LDX,N)
124: *> If VECT = 'V', the n-by-n matrix X.
125: *> If VECT = 'N', the array X is not referenced.
126: *> \endverbatim
127: *>
128: *> \param[in] LDX
129: *> \verbatim
130: *> LDX is INTEGER
131: *> The leading dimension of the array X.
132: *> LDX >= max(1,N) if VECT = 'V'; LDX >= 1 otherwise.
133: *> \endverbatim
134: *>
135: *> \param[out] WORK
136: *> \verbatim
137: *> WORK is COMPLEX*16 array, dimension (N)
138: *> \endverbatim
139: *>
140: *> \param[out] RWORK
141: *> \verbatim
142: *> RWORK is DOUBLE PRECISION array, dimension (N)
143: *> \endverbatim
144: *>
145: *> \param[out] INFO
146: *> \verbatim
147: *> INFO is INTEGER
148: *> = 0: successful exit
149: *> < 0: if INFO = -i, the i-th argument had an illegal value.
150: *> \endverbatim
151: *
152: * Authors:
153: * ========
154: *
1.15 bertrand 155: *> \author Univ. of Tennessee
156: *> \author Univ. of California Berkeley
157: *> \author Univ. of Colorado Denver
158: *> \author NAG Ltd.
1.9 bertrand 159: *
160: *> \ingroup complex16OTHERcomputational
161: *
162: * =====================================================================
1.1 bertrand 163: SUBROUTINE ZHBGST( VECT, UPLO, N, KA, KB, AB, LDAB, BB, LDBB, X,
164: $ LDX, WORK, RWORK, INFO )
165: *
1.18 ! bertrand 166: * -- LAPACK computational routine --
1.1 bertrand 167: * -- LAPACK is a software package provided by Univ. of Tennessee, --
168: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
169: *
170: * .. Scalar Arguments ..
171: CHARACTER UPLO, VECT
172: INTEGER INFO, KA, KB, LDAB, LDBB, LDX, N
173: * ..
174: * .. Array Arguments ..
175: DOUBLE PRECISION RWORK( * )
176: COMPLEX*16 AB( LDAB, * ), BB( LDBB, * ), WORK( * ),
177: $ X( LDX, * )
178: * ..
179: *
180: * =====================================================================
181: *
182: * .. Parameters ..
183: COMPLEX*16 CZERO, CONE
184: DOUBLE PRECISION ONE
185: PARAMETER ( CZERO = ( 0.0D+0, 0.0D+0 ),
186: $ CONE = ( 1.0D+0, 0.0D+0 ), ONE = 1.0D+0 )
187: * ..
188: * .. Local Scalars ..
189: LOGICAL UPDATE, UPPER, WANTX
190: INTEGER I, I0, I1, I2, INCA, J, J1, J1T, J2, J2T, K,
191: $ KA1, KB1, KBT, L, M, NR, NRT, NX
192: DOUBLE PRECISION BII
193: COMPLEX*16 RA, RA1, T
194: * ..
195: * .. External Functions ..
196: LOGICAL LSAME
197: EXTERNAL LSAME
198: * ..
199: * .. External Subroutines ..
200: EXTERNAL XERBLA, ZDSCAL, ZGERC, ZGERU, ZLACGV, ZLAR2V,
201: $ ZLARGV, ZLARTG, ZLARTV, ZLASET, ZROT
202: * ..
203: * .. Intrinsic Functions ..
204: INTRINSIC DBLE, DCONJG, MAX, MIN
205: * ..
206: * .. Executable Statements ..
207: *
208: * Test the input parameters
209: *
210: WANTX = LSAME( VECT, 'V' )
211: UPPER = LSAME( UPLO, 'U' )
212: KA1 = KA + 1
213: KB1 = KB + 1
214: INFO = 0
215: IF( .NOT.WANTX .AND. .NOT.LSAME( VECT, 'N' ) ) THEN
216: INFO = -1
217: ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
218: INFO = -2
219: ELSE IF( N.LT.0 ) THEN
220: INFO = -3
221: ELSE IF( KA.LT.0 ) THEN
222: INFO = -4
223: ELSE IF( KB.LT.0 .OR. KB.GT.KA ) THEN
224: INFO = -5
225: ELSE IF( LDAB.LT.KA+1 ) THEN
226: INFO = -7
227: ELSE IF( LDBB.LT.KB+1 ) THEN
228: INFO = -9
229: ELSE IF( LDX.LT.1 .OR. WANTX .AND. LDX.LT.MAX( 1, N ) ) THEN
230: INFO = -11
231: END IF
232: IF( INFO.NE.0 ) THEN
233: CALL XERBLA( 'ZHBGST', -INFO )
234: RETURN
235: END IF
236: *
237: * Quick return if possible
238: *
239: IF( N.EQ.0 )
240: $ RETURN
241: *
242: INCA = LDAB*KA1
243: *
244: * Initialize X to the unit matrix, if needed
245: *
246: IF( WANTX )
247: $ CALL ZLASET( 'Full', N, N, CZERO, CONE, X, LDX )
248: *
249: * Set M to the splitting point m. It must be the same value as is
250: * used in ZPBSTF. The chosen value allows the arrays WORK and RWORK
251: * to be of dimension (N).
252: *
253: M = ( N+KB ) / 2
254: *
255: * The routine works in two phases, corresponding to the two halves
256: * of the split Cholesky factorization of B as S**H*S where
257: *
258: * S = ( U )
259: * ( M L )
260: *
261: * with U upper triangular of order m, and L lower triangular of
262: * order n-m. S has the same bandwidth as B.
263: *
264: * S is treated as a product of elementary matrices:
265: *
266: * S = S(m)*S(m-1)*...*S(2)*S(1)*S(m+1)*S(m+2)*...*S(n-1)*S(n)
267: *
268: * where S(i) is determined by the i-th row of S.
269: *
270: * In phase 1, the index i takes the values n, n-1, ... , m+1;
271: * in phase 2, it takes the values 1, 2, ... , m.
272: *
273: * For each value of i, the current matrix A is updated by forming
274: * inv(S(i))**H*A*inv(S(i)). This creates a triangular bulge outside
275: * the band of A. The bulge is then pushed down toward the bottom of
276: * A in phase 1, and up toward the top of A in phase 2, by applying
277: * plane rotations.
278: *
279: * There are kb*(kb+1)/2 elements in the bulge, but at most 2*kb-1
280: * of them are linearly independent, so annihilating a bulge requires
281: * only 2*kb-1 plane rotations. The rotations are divided into a 1st
282: * set of kb-1 rotations, and a 2nd set of kb rotations.
283: *
284: * Wherever possible, rotations are generated and applied in vector
285: * operations of length NR between the indices J1 and J2 (sometimes
286: * replaced by modified values NRT, J1T or J2T).
287: *
288: * The real cosines and complex sines of the rotations are stored in
289: * the arrays RWORK and WORK, those of the 1st set in elements
290: * 2:m-kb-1, and those of the 2nd set in elements m-kb+1:n.
291: *
292: * The bulges are not formed explicitly; nonzero elements outside the
293: * band are created only when they are required for generating new
294: * rotations; they are stored in the array WORK, in positions where
295: * they are later overwritten by the sines of the rotations which
296: * annihilate them.
297: *
298: * **************************** Phase 1 *****************************
299: *
300: * The logical structure of this phase is:
301: *
302: * UPDATE = .TRUE.
303: * DO I = N, M + 1, -1
304: * use S(i) to update A and create a new bulge
305: * apply rotations to push all bulges KA positions downward
306: * END DO
307: * UPDATE = .FALSE.
308: * DO I = M + KA + 1, N - 1
309: * apply rotations to push all bulges KA positions downward
310: * END DO
311: *
312: * To avoid duplicating code, the two loops are merged.
313: *
314: UPDATE = .TRUE.
315: I = N + 1
316: 10 CONTINUE
317: IF( UPDATE ) THEN
318: I = I - 1
319: KBT = MIN( KB, I-1 )
320: I0 = I - 1
321: I1 = MIN( N, I+KA )
322: I2 = I - KBT + KA1
323: IF( I.LT.M+1 ) THEN
324: UPDATE = .FALSE.
325: I = I + 1
326: I0 = M
327: IF( KA.EQ.0 )
328: $ GO TO 480
329: GO TO 10
330: END IF
331: ELSE
332: I = I + KA
333: IF( I.GT.N-1 )
334: $ GO TO 480
335: END IF
336: *
337: IF( UPPER ) THEN
338: *
339: * Transform A, working with the upper triangle
340: *
341: IF( UPDATE ) THEN
342: *
343: * Form inv(S(i))**H * A * inv(S(i))
344: *
345: BII = DBLE( BB( KB1, I ) )
346: AB( KA1, I ) = ( DBLE( AB( KA1, I ) ) / BII ) / BII
347: DO 20 J = I + 1, I1
348: AB( I-J+KA1, J ) = AB( I-J+KA1, J ) / BII
349: 20 CONTINUE
350: DO 30 J = MAX( 1, I-KA ), I - 1
351: AB( J-I+KA1, I ) = AB( J-I+KA1, I ) / BII
352: 30 CONTINUE
353: DO 60 K = I - KBT, I - 1
354: DO 40 J = I - KBT, K
355: AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -
356: $ BB( J-I+KB1, I )*
357: $ DCONJG( AB( K-I+KA1, I ) ) -
358: $ DCONJG( BB( K-I+KB1, I ) )*
359: $ AB( J-I+KA1, I ) +
360: $ DBLE( AB( KA1, I ) )*
361: $ BB( J-I+KB1, I )*
362: $ DCONJG( BB( K-I+KB1, I ) )
363: 40 CONTINUE
364: DO 50 J = MAX( 1, I-KA ), I - KBT - 1
365: AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -
366: $ DCONJG( BB( K-I+KB1, I ) )*
367: $ AB( J-I+KA1, I )
368: 50 CONTINUE
369: 60 CONTINUE
370: DO 80 J = I, I1
371: DO 70 K = MAX( J-KA, I-KBT ), I - 1
372: AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -
373: $ BB( K-I+KB1, I )*AB( I-J+KA1, J )
374: 70 CONTINUE
375: 80 CONTINUE
376: *
377: IF( WANTX ) THEN
378: *
379: * post-multiply X by inv(S(i))
380: *
381: CALL ZDSCAL( N-M, ONE / BII, X( M+1, I ), 1 )
382: IF( KBT.GT.0 )
383: $ CALL ZGERC( N-M, KBT, -CONE, X( M+1, I ), 1,
384: $ BB( KB1-KBT, I ), 1, X( M+1, I-KBT ),
385: $ LDX )
386: END IF
387: *
388: * store a(i,i1) in RA1 for use in next loop over K
389: *
390: RA1 = AB( I-I1+KA1, I1 )
391: END IF
392: *
393: * Generate and apply vectors of rotations to chase all the
394: * existing bulges KA positions down toward the bottom of the
395: * band
396: *
397: DO 130 K = 1, KB - 1
398: IF( UPDATE ) THEN
399: *
400: * Determine the rotations which would annihilate the bulge
401: * which has in theory just been created
402: *
403: IF( I-K+KA.LT.N .AND. I-K.GT.1 ) THEN
404: *
405: * generate rotation to annihilate a(i,i-k+ka+1)
406: *
407: CALL ZLARTG( AB( K+1, I-K+KA ), RA1,
408: $ RWORK( I-K+KA-M ), WORK( I-K+KA-M ), RA )
409: *
410: * create nonzero element a(i-k,i-k+ka+1) outside the
411: * band and store it in WORK(i-k)
412: *
413: T = -BB( KB1-K, I )*RA1
414: WORK( I-K ) = RWORK( I-K+KA-M )*T -
415: $ DCONJG( WORK( I-K+KA-M ) )*
416: $ AB( 1, I-K+KA )
417: AB( 1, I-K+KA ) = WORK( I-K+KA-M )*T +
418: $ RWORK( I-K+KA-M )*AB( 1, I-K+KA )
419: RA1 = RA
420: END IF
421: END IF
422: J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
423: NR = ( N-J2+KA ) / KA1
424: J1 = J2 + ( NR-1 )*KA1
425: IF( UPDATE ) THEN
426: J2T = MAX( J2, I+2*KA-K+1 )
427: ELSE
428: J2T = J2
429: END IF
430: NRT = ( N-J2T+KA ) / KA1
431: DO 90 J = J2T, J1, KA1
432: *
433: * create nonzero element a(j-ka,j+1) outside the band
434: * and store it in WORK(j-m)
435: *
436: WORK( J-M ) = WORK( J-M )*AB( 1, J+1 )
437: AB( 1, J+1 ) = RWORK( J-M )*AB( 1, J+1 )
438: 90 CONTINUE
439: *
440: * generate rotations in 1st set to annihilate elements which
441: * have been created outside the band
442: *
443: IF( NRT.GT.0 )
444: $ CALL ZLARGV( NRT, AB( 1, J2T ), INCA, WORK( J2T-M ), KA1,
445: $ RWORK( J2T-M ), KA1 )
446: IF( NR.GT.0 ) THEN
447: *
448: * apply rotations in 1st set from the right
449: *
450: DO 100 L = 1, KA - 1
451: CALL ZLARTV( NR, AB( KA1-L, J2 ), INCA,
452: $ AB( KA-L, J2+1 ), INCA, RWORK( J2-M ),
453: $ WORK( J2-M ), KA1 )
454: 100 CONTINUE
455: *
456: * apply rotations in 1st set from both sides to diagonal
457: * blocks
458: *
459: CALL ZLAR2V( NR, AB( KA1, J2 ), AB( KA1, J2+1 ),
460: $ AB( KA, J2+1 ), INCA, RWORK( J2-M ),
461: $ WORK( J2-M ), KA1 )
462: *
463: CALL ZLACGV( NR, WORK( J2-M ), KA1 )
464: END IF
465: *
466: * start applying rotations in 1st set from the left
467: *
468: DO 110 L = KA - 1, KB - K + 1, -1
469: NRT = ( N-J2+L ) / KA1
470: IF( NRT.GT.0 )
471: $ CALL ZLARTV( NRT, AB( L, J2+KA1-L ), INCA,
472: $ AB( L+1, J2+KA1-L ), INCA, RWORK( J2-M ),
473: $ WORK( J2-M ), KA1 )
474: 110 CONTINUE
475: *
476: IF( WANTX ) THEN
477: *
478: * post-multiply X by product of rotations in 1st set
479: *
480: DO 120 J = J2, J1, KA1
481: CALL ZROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
482: $ RWORK( J-M ), DCONJG( WORK( J-M ) ) )
483: 120 CONTINUE
484: END IF
485: 130 CONTINUE
486: *
487: IF( UPDATE ) THEN
488: IF( I2.LE.N .AND. KBT.GT.0 ) THEN
489: *
490: * create nonzero element a(i-kbt,i-kbt+ka+1) outside the
491: * band and store it in WORK(i-kbt)
492: *
493: WORK( I-KBT ) = -BB( KB1-KBT, I )*RA1
494: END IF
495: END IF
496: *
497: DO 170 K = KB, 1, -1
498: IF( UPDATE ) THEN
499: J2 = I - K - 1 + MAX( 2, K-I0+1 )*KA1
500: ELSE
501: J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
502: END IF
503: *
504: * finish applying rotations in 2nd set from the left
505: *
506: DO 140 L = KB - K, 1, -1
507: NRT = ( N-J2+KA+L ) / KA1
508: IF( NRT.GT.0 )
509: $ CALL ZLARTV( NRT, AB( L, J2-L+1 ), INCA,
510: $ AB( L+1, J2-L+1 ), INCA, RWORK( J2-KA ),
511: $ WORK( J2-KA ), KA1 )
512: 140 CONTINUE
513: NR = ( N-J2+KA ) / KA1
514: J1 = J2 + ( NR-1 )*KA1
515: DO 150 J = J1, J2, -KA1
516: WORK( J ) = WORK( J-KA )
517: RWORK( J ) = RWORK( J-KA )
518: 150 CONTINUE
519: DO 160 J = J2, J1, KA1
520: *
521: * create nonzero element a(j-ka,j+1) outside the band
522: * and store it in WORK(j)
523: *
524: WORK( J ) = WORK( J )*AB( 1, J+1 )
525: AB( 1, J+1 ) = RWORK( J )*AB( 1, J+1 )
526: 160 CONTINUE
527: IF( UPDATE ) THEN
528: IF( I-K.LT.N-KA .AND. K.LE.KBT )
529: $ WORK( I-K+KA ) = WORK( I-K )
530: END IF
531: 170 CONTINUE
532: *
533: DO 210 K = KB, 1, -1
534: J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
535: NR = ( N-J2+KA ) / KA1
536: J1 = J2 + ( NR-1 )*KA1
537: IF( NR.GT.0 ) THEN
538: *
539: * generate rotations in 2nd set to annihilate elements
540: * which have been created outside the band
541: *
542: CALL ZLARGV( NR, AB( 1, J2 ), INCA, WORK( J2 ), KA1,
543: $ RWORK( J2 ), KA1 )
544: *
545: * apply rotations in 2nd set from the right
546: *
547: DO 180 L = 1, KA - 1
548: CALL ZLARTV( NR, AB( KA1-L, J2 ), INCA,
549: $ AB( KA-L, J2+1 ), INCA, RWORK( J2 ),
550: $ WORK( J2 ), KA1 )
551: 180 CONTINUE
552: *
553: * apply rotations in 2nd set from both sides to diagonal
554: * blocks
555: *
556: CALL ZLAR2V( NR, AB( KA1, J2 ), AB( KA1, J2+1 ),
557: $ AB( KA, J2+1 ), INCA, RWORK( J2 ),
558: $ WORK( J2 ), KA1 )
559: *
560: CALL ZLACGV( NR, WORK( J2 ), KA1 )
561: END IF
562: *
563: * start applying rotations in 2nd set from the left
564: *
565: DO 190 L = KA - 1, KB - K + 1, -1
566: NRT = ( N-J2+L ) / KA1
567: IF( NRT.GT.0 )
568: $ CALL ZLARTV( NRT, AB( L, J2+KA1-L ), INCA,
569: $ AB( L+1, J2+KA1-L ), INCA, RWORK( J2 ),
570: $ WORK( J2 ), KA1 )
571: 190 CONTINUE
572: *
573: IF( WANTX ) THEN
574: *
575: * post-multiply X by product of rotations in 2nd set
576: *
577: DO 200 J = J2, J1, KA1
578: CALL ZROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
579: $ RWORK( J ), DCONJG( WORK( J ) ) )
580: 200 CONTINUE
581: END IF
582: 210 CONTINUE
583: *
584: DO 230 K = 1, KB - 1
585: J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
586: *
587: * finish applying rotations in 1st set from the left
588: *
589: DO 220 L = KB - K, 1, -1
590: NRT = ( N-J2+L ) / KA1
591: IF( NRT.GT.0 )
592: $ CALL ZLARTV( NRT, AB( L, J2+KA1-L ), INCA,
593: $ AB( L+1, J2+KA1-L ), INCA, RWORK( J2-M ),
594: $ WORK( J2-M ), KA1 )
595: 220 CONTINUE
596: 230 CONTINUE
597: *
598: IF( KB.GT.1 ) THEN
1.5 bertrand 599: DO 240 J = N - 1, J2 + KA, -1
1.1 bertrand 600: RWORK( J-M ) = RWORK( J-KA-M )
601: WORK( J-M ) = WORK( J-KA-M )
602: 240 CONTINUE
603: END IF
604: *
605: ELSE
606: *
607: * Transform A, working with the lower triangle
608: *
609: IF( UPDATE ) THEN
610: *
611: * Form inv(S(i))**H * A * inv(S(i))
612: *
613: BII = DBLE( BB( 1, I ) )
614: AB( 1, I ) = ( DBLE( AB( 1, I ) ) / BII ) / BII
615: DO 250 J = I + 1, I1
616: AB( J-I+1, I ) = AB( J-I+1, I ) / BII
617: 250 CONTINUE
618: DO 260 J = MAX( 1, I-KA ), I - 1
619: AB( I-J+1, J ) = AB( I-J+1, J ) / BII
620: 260 CONTINUE
621: DO 290 K = I - KBT, I - 1
622: DO 270 J = I - KBT, K
623: AB( K-J+1, J ) = AB( K-J+1, J ) -
624: $ BB( I-J+1, J )*DCONJG( AB( I-K+1,
625: $ K ) ) - DCONJG( BB( I-K+1, K ) )*
626: $ AB( I-J+1, J ) + DBLE( AB( 1, I ) )*
627: $ BB( I-J+1, J )*DCONJG( BB( I-K+1,
628: $ K ) )
629: 270 CONTINUE
630: DO 280 J = MAX( 1, I-KA ), I - KBT - 1
631: AB( K-J+1, J ) = AB( K-J+1, J ) -
632: $ DCONJG( BB( I-K+1, K ) )*
633: $ AB( I-J+1, J )
634: 280 CONTINUE
635: 290 CONTINUE
636: DO 310 J = I, I1
637: DO 300 K = MAX( J-KA, I-KBT ), I - 1
638: AB( J-K+1, K ) = AB( J-K+1, K ) -
639: $ BB( I-K+1, K )*AB( J-I+1, I )
640: 300 CONTINUE
641: 310 CONTINUE
642: *
643: IF( WANTX ) THEN
644: *
645: * post-multiply X by inv(S(i))
646: *
647: CALL ZDSCAL( N-M, ONE / BII, X( M+1, I ), 1 )
648: IF( KBT.GT.0 )
649: $ CALL ZGERU( N-M, KBT, -CONE, X( M+1, I ), 1,
650: $ BB( KBT+1, I-KBT ), LDBB-1,
651: $ X( M+1, I-KBT ), LDX )
652: END IF
653: *
654: * store a(i1,i) in RA1 for use in next loop over K
655: *
656: RA1 = AB( I1-I+1, I )
657: END IF
658: *
659: * Generate and apply vectors of rotations to chase all the
660: * existing bulges KA positions down toward the bottom of the
661: * band
662: *
663: DO 360 K = 1, KB - 1
664: IF( UPDATE ) THEN
665: *
666: * Determine the rotations which would annihilate the bulge
667: * which has in theory just been created
668: *
669: IF( I-K+KA.LT.N .AND. I-K.GT.1 ) THEN
670: *
671: * generate rotation to annihilate a(i-k+ka+1,i)
672: *
673: CALL ZLARTG( AB( KA1-K, I ), RA1, RWORK( I-K+KA-M ),
674: $ WORK( I-K+KA-M ), RA )
675: *
676: * create nonzero element a(i-k+ka+1,i-k) outside the
677: * band and store it in WORK(i-k)
678: *
679: T = -BB( K+1, I-K )*RA1
680: WORK( I-K ) = RWORK( I-K+KA-M )*T -
681: $ DCONJG( WORK( I-K+KA-M ) )*
682: $ AB( KA1, I-K )
683: AB( KA1, I-K ) = WORK( I-K+KA-M )*T +
684: $ RWORK( I-K+KA-M )*AB( KA1, I-K )
685: RA1 = RA
686: END IF
687: END IF
688: J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
689: NR = ( N-J2+KA ) / KA1
690: J1 = J2 + ( NR-1 )*KA1
691: IF( UPDATE ) THEN
692: J2T = MAX( J2, I+2*KA-K+1 )
693: ELSE
694: J2T = J2
695: END IF
696: NRT = ( N-J2T+KA ) / KA1
697: DO 320 J = J2T, J1, KA1
698: *
699: * create nonzero element a(j+1,j-ka) outside the band
700: * and store it in WORK(j-m)
701: *
702: WORK( J-M ) = WORK( J-M )*AB( KA1, J-KA+1 )
703: AB( KA1, J-KA+1 ) = RWORK( J-M )*AB( KA1, J-KA+1 )
704: 320 CONTINUE
705: *
706: * generate rotations in 1st set to annihilate elements which
707: * have been created outside the band
708: *
709: IF( NRT.GT.0 )
710: $ CALL ZLARGV( NRT, AB( KA1, J2T-KA ), INCA, WORK( J2T-M ),
711: $ KA1, RWORK( J2T-M ), KA1 )
712: IF( NR.GT.0 ) THEN
713: *
714: * apply rotations in 1st set from the left
715: *
716: DO 330 L = 1, KA - 1
717: CALL ZLARTV( NR, AB( L+1, J2-L ), INCA,
718: $ AB( L+2, J2-L ), INCA, RWORK( J2-M ),
719: $ WORK( J2-M ), KA1 )
720: 330 CONTINUE
721: *
722: * apply rotations in 1st set from both sides to diagonal
723: * blocks
724: *
725: CALL ZLAR2V( NR, AB( 1, J2 ), AB( 1, J2+1 ), AB( 2, J2 ),
726: $ INCA, RWORK( J2-M ), WORK( J2-M ), KA1 )
727: *
728: CALL ZLACGV( NR, WORK( J2-M ), KA1 )
729: END IF
730: *
731: * start applying rotations in 1st set from the right
732: *
733: DO 340 L = KA - 1, KB - K + 1, -1
734: NRT = ( N-J2+L ) / KA1
735: IF( NRT.GT.0 )
736: $ CALL ZLARTV( NRT, AB( KA1-L+1, J2 ), INCA,
737: $ AB( KA1-L, J2+1 ), INCA, RWORK( J2-M ),
738: $ WORK( J2-M ), KA1 )
739: 340 CONTINUE
740: *
741: IF( WANTX ) THEN
742: *
743: * post-multiply X by product of rotations in 1st set
744: *
745: DO 350 J = J2, J1, KA1
746: CALL ZROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
747: $ RWORK( J-M ), WORK( J-M ) )
748: 350 CONTINUE
749: END IF
750: 360 CONTINUE
751: *
752: IF( UPDATE ) THEN
753: IF( I2.LE.N .AND. KBT.GT.0 ) THEN
754: *
755: * create nonzero element a(i-kbt+ka+1,i-kbt) outside the
756: * band and store it in WORK(i-kbt)
757: *
758: WORK( I-KBT ) = -BB( KBT+1, I-KBT )*RA1
759: END IF
760: END IF
761: *
762: DO 400 K = KB, 1, -1
763: IF( UPDATE ) THEN
764: J2 = I - K - 1 + MAX( 2, K-I0+1 )*KA1
765: ELSE
766: J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
767: END IF
768: *
769: * finish applying rotations in 2nd set from the right
770: *
771: DO 370 L = KB - K, 1, -1
772: NRT = ( N-J2+KA+L ) / KA1
773: IF( NRT.GT.0 )
774: $ CALL ZLARTV( NRT, AB( KA1-L+1, J2-KA ), INCA,
775: $ AB( KA1-L, J2-KA+1 ), INCA,
776: $ RWORK( J2-KA ), WORK( J2-KA ), KA1 )
777: 370 CONTINUE
778: NR = ( N-J2+KA ) / KA1
779: J1 = J2 + ( NR-1 )*KA1
780: DO 380 J = J1, J2, -KA1
781: WORK( J ) = WORK( J-KA )
782: RWORK( J ) = RWORK( J-KA )
783: 380 CONTINUE
784: DO 390 J = J2, J1, KA1
785: *
786: * create nonzero element a(j+1,j-ka) outside the band
787: * and store it in WORK(j)
788: *
789: WORK( J ) = WORK( J )*AB( KA1, J-KA+1 )
790: AB( KA1, J-KA+1 ) = RWORK( J )*AB( KA1, J-KA+1 )
791: 390 CONTINUE
792: IF( UPDATE ) THEN
793: IF( I-K.LT.N-KA .AND. K.LE.KBT )
794: $ WORK( I-K+KA ) = WORK( I-K )
795: END IF
796: 400 CONTINUE
797: *
798: DO 440 K = KB, 1, -1
799: J2 = I - K - 1 + MAX( 1, K-I0+1 )*KA1
800: NR = ( N-J2+KA ) / KA1
801: J1 = J2 + ( NR-1 )*KA1
802: IF( NR.GT.0 ) THEN
803: *
804: * generate rotations in 2nd set to annihilate elements
805: * which have been created outside the band
806: *
807: CALL ZLARGV( NR, AB( KA1, J2-KA ), INCA, WORK( J2 ), KA1,
808: $ RWORK( J2 ), KA1 )
809: *
810: * apply rotations in 2nd set from the left
811: *
812: DO 410 L = 1, KA - 1
813: CALL ZLARTV( NR, AB( L+1, J2-L ), INCA,
814: $ AB( L+2, J2-L ), INCA, RWORK( J2 ),
815: $ WORK( J2 ), KA1 )
816: 410 CONTINUE
817: *
818: * apply rotations in 2nd set from both sides to diagonal
819: * blocks
820: *
821: CALL ZLAR2V( NR, AB( 1, J2 ), AB( 1, J2+1 ), AB( 2, J2 ),
822: $ INCA, RWORK( J2 ), WORK( J2 ), KA1 )
823: *
824: CALL ZLACGV( NR, WORK( J2 ), KA1 )
825: END IF
826: *
827: * start applying rotations in 2nd set from the right
828: *
829: DO 420 L = KA - 1, KB - K + 1, -1
830: NRT = ( N-J2+L ) / KA1
831: IF( NRT.GT.0 )
832: $ CALL ZLARTV( NRT, AB( KA1-L+1, J2 ), INCA,
833: $ AB( KA1-L, J2+1 ), INCA, RWORK( J2 ),
834: $ WORK( J2 ), KA1 )
835: 420 CONTINUE
836: *
837: IF( WANTX ) THEN
838: *
839: * post-multiply X by product of rotations in 2nd set
840: *
841: DO 430 J = J2, J1, KA1
842: CALL ZROT( N-M, X( M+1, J ), 1, X( M+1, J+1 ), 1,
843: $ RWORK( J ), WORK( J ) )
844: 430 CONTINUE
845: END IF
846: 440 CONTINUE
847: *
848: DO 460 K = 1, KB - 1
849: J2 = I - K - 1 + MAX( 1, K-I0+2 )*KA1
850: *
851: * finish applying rotations in 1st set from the right
852: *
853: DO 450 L = KB - K, 1, -1
854: NRT = ( N-J2+L ) / KA1
855: IF( NRT.GT.0 )
856: $ CALL ZLARTV( NRT, AB( KA1-L+1, J2 ), INCA,
857: $ AB( KA1-L, J2+1 ), INCA, RWORK( J2-M ),
858: $ WORK( J2-M ), KA1 )
859: 450 CONTINUE
860: 460 CONTINUE
861: *
862: IF( KB.GT.1 ) THEN
1.5 bertrand 863: DO 470 J = N - 1, J2 + KA, -1
1.1 bertrand 864: RWORK( J-M ) = RWORK( J-KA-M )
865: WORK( J-M ) = WORK( J-KA-M )
866: 470 CONTINUE
867: END IF
868: *
869: END IF
870: *
871: GO TO 10
872: *
873: 480 CONTINUE
874: *
875: * **************************** Phase 2 *****************************
876: *
877: * The logical structure of this phase is:
878: *
879: * UPDATE = .TRUE.
880: * DO I = 1, M
881: * use S(i) to update A and create a new bulge
882: * apply rotations to push all bulges KA positions upward
883: * END DO
884: * UPDATE = .FALSE.
885: * DO I = M - KA - 1, 2, -1
886: * apply rotations to push all bulges KA positions upward
887: * END DO
888: *
889: * To avoid duplicating code, the two loops are merged.
890: *
891: UPDATE = .TRUE.
892: I = 0
893: 490 CONTINUE
894: IF( UPDATE ) THEN
895: I = I + 1
896: KBT = MIN( KB, M-I )
897: I0 = I + 1
898: I1 = MAX( 1, I-KA )
899: I2 = I + KBT - KA1
900: IF( I.GT.M ) THEN
901: UPDATE = .FALSE.
902: I = I - 1
903: I0 = M + 1
904: IF( KA.EQ.0 )
905: $ RETURN
906: GO TO 490
907: END IF
908: ELSE
909: I = I - KA
910: IF( I.LT.2 )
911: $ RETURN
912: END IF
913: *
914: IF( I.LT.M-KBT ) THEN
915: NX = M
916: ELSE
917: NX = N
918: END IF
919: *
920: IF( UPPER ) THEN
921: *
922: * Transform A, working with the upper triangle
923: *
924: IF( UPDATE ) THEN
925: *
926: * Form inv(S(i))**H * A * inv(S(i))
927: *
928: BII = DBLE( BB( KB1, I ) )
929: AB( KA1, I ) = ( DBLE( AB( KA1, I ) ) / BII ) / BII
930: DO 500 J = I1, I - 1
931: AB( J-I+KA1, I ) = AB( J-I+KA1, I ) / BII
932: 500 CONTINUE
933: DO 510 J = I + 1, MIN( N, I+KA )
934: AB( I-J+KA1, J ) = AB( I-J+KA1, J ) / BII
935: 510 CONTINUE
936: DO 540 K = I + 1, I + KBT
937: DO 520 J = K, I + KBT
938: AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -
939: $ BB( I-J+KB1, J )*
940: $ DCONJG( AB( I-K+KA1, K ) ) -
941: $ DCONJG( BB( I-K+KB1, K ) )*
942: $ AB( I-J+KA1, J ) +
943: $ DBLE( AB( KA1, I ) )*
944: $ BB( I-J+KB1, J )*
945: $ DCONJG( BB( I-K+KB1, K ) )
946: 520 CONTINUE
947: DO 530 J = I + KBT + 1, MIN( N, I+KA )
948: AB( K-J+KA1, J ) = AB( K-J+KA1, J ) -
949: $ DCONJG( BB( I-K+KB1, K ) )*
950: $ AB( I-J+KA1, J )
951: 530 CONTINUE
952: 540 CONTINUE
953: DO 560 J = I1, I
954: DO 550 K = I + 1, MIN( J+KA, I+KBT )
955: AB( J-K+KA1, K ) = AB( J-K+KA1, K ) -
956: $ BB( I-K+KB1, K )*AB( J-I+KA1, I )
957: 550 CONTINUE
958: 560 CONTINUE
959: *
960: IF( WANTX ) THEN
961: *
962: * post-multiply X by inv(S(i))
963: *
964: CALL ZDSCAL( NX, ONE / BII, X( 1, I ), 1 )
965: IF( KBT.GT.0 )
966: $ CALL ZGERU( NX, KBT, -CONE, X( 1, I ), 1,
967: $ BB( KB, I+1 ), LDBB-1, X( 1, I+1 ), LDX )
968: END IF
969: *
970: * store a(i1,i) in RA1 for use in next loop over K
971: *
972: RA1 = AB( I1-I+KA1, I )
973: END IF
974: *
975: * Generate and apply vectors of rotations to chase all the
976: * existing bulges KA positions up toward the top of the band
977: *
978: DO 610 K = 1, KB - 1
979: IF( UPDATE ) THEN
980: *
981: * Determine the rotations which would annihilate the bulge
982: * which has in theory just been created
983: *
984: IF( I+K-KA1.GT.0 .AND. I+K.LT.M ) THEN
985: *
986: * generate rotation to annihilate a(i+k-ka-1,i)
987: *
988: CALL ZLARTG( AB( K+1, I ), RA1, RWORK( I+K-KA ),
989: $ WORK( I+K-KA ), RA )
990: *
991: * create nonzero element a(i+k-ka-1,i+k) outside the
992: * band and store it in WORK(m-kb+i+k)
993: *
994: T = -BB( KB1-K, I+K )*RA1
995: WORK( M-KB+I+K ) = RWORK( I+K-KA )*T -
996: $ DCONJG( WORK( I+K-KA ) )*
997: $ AB( 1, I+K )
998: AB( 1, I+K ) = WORK( I+K-KA )*T +
999: $ RWORK( I+K-KA )*AB( 1, I+K )
1000: RA1 = RA
1001: END IF
1002: END IF
1003: J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
1004: NR = ( J2+KA-1 ) / KA1
1005: J1 = J2 - ( NR-1 )*KA1
1006: IF( UPDATE ) THEN
1007: J2T = MIN( J2, I-2*KA+K-1 )
1008: ELSE
1009: J2T = J2
1010: END IF
1011: NRT = ( J2T+KA-1 ) / KA1
1012: DO 570 J = J1, J2T, KA1
1013: *
1014: * create nonzero element a(j-1,j+ka) outside the band
1015: * and store it in WORK(j)
1016: *
1017: WORK( J ) = WORK( J )*AB( 1, J+KA-1 )
1018: AB( 1, J+KA-1 ) = RWORK( J )*AB( 1, J+KA-1 )
1019: 570 CONTINUE
1020: *
1021: * generate rotations in 1st set to annihilate elements which
1022: * have been created outside the band
1023: *
1024: IF( NRT.GT.0 )
1025: $ CALL ZLARGV( NRT, AB( 1, J1+KA ), INCA, WORK( J1 ), KA1,
1026: $ RWORK( J1 ), KA1 )
1027: IF( NR.GT.0 ) THEN
1028: *
1029: * apply rotations in 1st set from the left
1030: *
1031: DO 580 L = 1, KA - 1
1032: CALL ZLARTV( NR, AB( KA1-L, J1+L ), INCA,
1033: $ AB( KA-L, J1+L ), INCA, RWORK( J1 ),
1034: $ WORK( J1 ), KA1 )
1035: 580 CONTINUE
1036: *
1037: * apply rotations in 1st set from both sides to diagonal
1038: * blocks
1039: *
1040: CALL ZLAR2V( NR, AB( KA1, J1 ), AB( KA1, J1-1 ),
1041: $ AB( KA, J1 ), INCA, RWORK( J1 ), WORK( J1 ),
1042: $ KA1 )
1043: *
1044: CALL ZLACGV( NR, WORK( J1 ), KA1 )
1045: END IF
1046: *
1047: * start applying rotations in 1st set from the right
1048: *
1049: DO 590 L = KA - 1, KB - K + 1, -1
1050: NRT = ( J2+L-1 ) / KA1
1051: J1T = J2 - ( NRT-1 )*KA1
1052: IF( NRT.GT.0 )
1053: $ CALL ZLARTV( NRT, AB( L, J1T ), INCA,
1054: $ AB( L+1, J1T-1 ), INCA, RWORK( J1T ),
1055: $ WORK( J1T ), KA1 )
1056: 590 CONTINUE
1057: *
1058: IF( WANTX ) THEN
1059: *
1060: * post-multiply X by product of rotations in 1st set
1061: *
1062: DO 600 J = J1, J2, KA1
1063: CALL ZROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
1064: $ RWORK( J ), WORK( J ) )
1065: 600 CONTINUE
1066: END IF
1067: 610 CONTINUE
1068: *
1069: IF( UPDATE ) THEN
1070: IF( I2.GT.0 .AND. KBT.GT.0 ) THEN
1071: *
1072: * create nonzero element a(i+kbt-ka-1,i+kbt) outside the
1073: * band and store it in WORK(m-kb+i+kbt)
1074: *
1075: WORK( M-KB+I+KBT ) = -BB( KB1-KBT, I+KBT )*RA1
1076: END IF
1077: END IF
1078: *
1079: DO 650 K = KB, 1, -1
1080: IF( UPDATE ) THEN
1081: J2 = I + K + 1 - MAX( 2, K+I0-M )*KA1
1082: ELSE
1083: J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
1084: END IF
1085: *
1086: * finish applying rotations in 2nd set from the right
1087: *
1088: DO 620 L = KB - K, 1, -1
1089: NRT = ( J2+KA+L-1 ) / KA1
1090: J1T = J2 - ( NRT-1 )*KA1
1091: IF( NRT.GT.0 )
1092: $ CALL ZLARTV( NRT, AB( L, J1T+KA ), INCA,
1093: $ AB( L+1, J1T+KA-1 ), INCA,
1094: $ RWORK( M-KB+J1T+KA ),
1095: $ WORK( M-KB+J1T+KA ), KA1 )
1096: 620 CONTINUE
1097: NR = ( J2+KA-1 ) / KA1
1098: J1 = J2 - ( NR-1 )*KA1
1099: DO 630 J = J1, J2, KA1
1100: WORK( M-KB+J ) = WORK( M-KB+J+KA )
1101: RWORK( M-KB+J ) = RWORK( M-KB+J+KA )
1102: 630 CONTINUE
1103: DO 640 J = J1, J2, KA1
1104: *
1105: * create nonzero element a(j-1,j+ka) outside the band
1106: * and store it in WORK(m-kb+j)
1107: *
1108: WORK( M-KB+J ) = WORK( M-KB+J )*AB( 1, J+KA-1 )
1109: AB( 1, J+KA-1 ) = RWORK( M-KB+J )*AB( 1, J+KA-1 )
1110: 640 CONTINUE
1111: IF( UPDATE ) THEN
1112: IF( I+K.GT.KA1 .AND. K.LE.KBT )
1113: $ WORK( M-KB+I+K-KA ) = WORK( M-KB+I+K )
1114: END IF
1115: 650 CONTINUE
1116: *
1117: DO 690 K = KB, 1, -1
1118: J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
1119: NR = ( J2+KA-1 ) / KA1
1120: J1 = J2 - ( NR-1 )*KA1
1121: IF( NR.GT.0 ) THEN
1122: *
1123: * generate rotations in 2nd set to annihilate elements
1124: * which have been created outside the band
1125: *
1126: CALL ZLARGV( NR, AB( 1, J1+KA ), INCA, WORK( M-KB+J1 ),
1127: $ KA1, RWORK( M-KB+J1 ), KA1 )
1128: *
1129: * apply rotations in 2nd set from the left
1130: *
1131: DO 660 L = 1, KA - 1
1132: CALL ZLARTV( NR, AB( KA1-L, J1+L ), INCA,
1133: $ AB( KA-L, J1+L ), INCA, RWORK( M-KB+J1 ),
1134: $ WORK( M-KB+J1 ), KA1 )
1135: 660 CONTINUE
1136: *
1137: * apply rotations in 2nd set from both sides to diagonal
1138: * blocks
1139: *
1140: CALL ZLAR2V( NR, AB( KA1, J1 ), AB( KA1, J1-1 ),
1141: $ AB( KA, J1 ), INCA, RWORK( M-KB+J1 ),
1142: $ WORK( M-KB+J1 ), KA1 )
1143: *
1144: CALL ZLACGV( NR, WORK( M-KB+J1 ), KA1 )
1145: END IF
1146: *
1147: * start applying rotations in 2nd set from the right
1148: *
1149: DO 670 L = KA - 1, KB - K + 1, -1
1150: NRT = ( J2+L-1 ) / KA1
1151: J1T = J2 - ( NRT-1 )*KA1
1152: IF( NRT.GT.0 )
1153: $ CALL ZLARTV( NRT, AB( L, J1T ), INCA,
1154: $ AB( L+1, J1T-1 ), INCA,
1155: $ RWORK( M-KB+J1T ), WORK( M-KB+J1T ),
1156: $ KA1 )
1157: 670 CONTINUE
1158: *
1159: IF( WANTX ) THEN
1160: *
1161: * post-multiply X by product of rotations in 2nd set
1162: *
1163: DO 680 J = J1, J2, KA1
1164: CALL ZROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
1165: $ RWORK( M-KB+J ), WORK( M-KB+J ) )
1166: 680 CONTINUE
1167: END IF
1168: 690 CONTINUE
1169: *
1170: DO 710 K = 1, KB - 1
1171: J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
1172: *
1173: * finish applying rotations in 1st set from the right
1174: *
1175: DO 700 L = KB - K, 1, -1
1176: NRT = ( J2+L-1 ) / KA1
1177: J1T = J2 - ( NRT-1 )*KA1
1178: IF( NRT.GT.0 )
1179: $ CALL ZLARTV( NRT, AB( L, J1T ), INCA,
1180: $ AB( L+1, J1T-1 ), INCA, RWORK( J1T ),
1181: $ WORK( J1T ), KA1 )
1182: 700 CONTINUE
1183: 710 CONTINUE
1184: *
1185: IF( KB.GT.1 ) THEN
1186: DO 720 J = 2, I2 - KA
1187: RWORK( J ) = RWORK( J+KA )
1188: WORK( J ) = WORK( J+KA )
1189: 720 CONTINUE
1190: END IF
1191: *
1192: ELSE
1193: *
1194: * Transform A, working with the lower triangle
1195: *
1196: IF( UPDATE ) THEN
1197: *
1198: * Form inv(S(i))**H * A * inv(S(i))
1199: *
1200: BII = DBLE( BB( 1, I ) )
1201: AB( 1, I ) = ( DBLE( AB( 1, I ) ) / BII ) / BII
1202: DO 730 J = I1, I - 1
1203: AB( I-J+1, J ) = AB( I-J+1, J ) / BII
1204: 730 CONTINUE
1205: DO 740 J = I + 1, MIN( N, I+KA )
1206: AB( J-I+1, I ) = AB( J-I+1, I ) / BII
1207: 740 CONTINUE
1208: DO 770 K = I + 1, I + KBT
1209: DO 750 J = K, I + KBT
1210: AB( J-K+1, K ) = AB( J-K+1, K ) -
1211: $ BB( J-I+1, I )*DCONJG( AB( K-I+1,
1212: $ I ) ) - DCONJG( BB( K-I+1, I ) )*
1213: $ AB( J-I+1, I ) + DBLE( AB( 1, I ) )*
1214: $ BB( J-I+1, I )*DCONJG( BB( K-I+1,
1215: $ I ) )
1216: 750 CONTINUE
1217: DO 760 J = I + KBT + 1, MIN( N, I+KA )
1218: AB( J-K+1, K ) = AB( J-K+1, K ) -
1219: $ DCONJG( BB( K-I+1, I ) )*
1220: $ AB( J-I+1, I )
1221: 760 CONTINUE
1222: 770 CONTINUE
1223: DO 790 J = I1, I
1224: DO 780 K = I + 1, MIN( J+KA, I+KBT )
1225: AB( K-J+1, J ) = AB( K-J+1, J ) -
1226: $ BB( K-I+1, I )*AB( I-J+1, J )
1227: 780 CONTINUE
1228: 790 CONTINUE
1229: *
1230: IF( WANTX ) THEN
1231: *
1232: * post-multiply X by inv(S(i))
1233: *
1234: CALL ZDSCAL( NX, ONE / BII, X( 1, I ), 1 )
1235: IF( KBT.GT.0 )
1236: $ CALL ZGERC( NX, KBT, -CONE, X( 1, I ), 1, BB( 2, I ),
1237: $ 1, X( 1, I+1 ), LDX )
1238: END IF
1239: *
1240: * store a(i,i1) in RA1 for use in next loop over K
1241: *
1242: RA1 = AB( I-I1+1, I1 )
1243: END IF
1244: *
1245: * Generate and apply vectors of rotations to chase all the
1246: * existing bulges KA positions up toward the top of the band
1247: *
1248: DO 840 K = 1, KB - 1
1249: IF( UPDATE ) THEN
1250: *
1251: * Determine the rotations which would annihilate the bulge
1252: * which has in theory just been created
1253: *
1254: IF( I+K-KA1.GT.0 .AND. I+K.LT.M ) THEN
1255: *
1256: * generate rotation to annihilate a(i,i+k-ka-1)
1257: *
1258: CALL ZLARTG( AB( KA1-K, I+K-KA ), RA1,
1259: $ RWORK( I+K-KA ), WORK( I+K-KA ), RA )
1260: *
1261: * create nonzero element a(i+k,i+k-ka-1) outside the
1262: * band and store it in WORK(m-kb+i+k)
1263: *
1264: T = -BB( K+1, I )*RA1
1265: WORK( M-KB+I+K ) = RWORK( I+K-KA )*T -
1266: $ DCONJG( WORK( I+K-KA ) )*
1267: $ AB( KA1, I+K-KA )
1268: AB( KA1, I+K-KA ) = WORK( I+K-KA )*T +
1269: $ RWORK( I+K-KA )*AB( KA1, I+K-KA )
1270: RA1 = RA
1271: END IF
1272: END IF
1273: J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
1274: NR = ( J2+KA-1 ) / KA1
1275: J1 = J2 - ( NR-1 )*KA1
1276: IF( UPDATE ) THEN
1277: J2T = MIN( J2, I-2*KA+K-1 )
1278: ELSE
1279: J2T = J2
1280: END IF
1281: NRT = ( J2T+KA-1 ) / KA1
1282: DO 800 J = J1, J2T, KA1
1283: *
1284: * create nonzero element a(j+ka,j-1) outside the band
1285: * and store it in WORK(j)
1286: *
1287: WORK( J ) = WORK( J )*AB( KA1, J-1 )
1288: AB( KA1, J-1 ) = RWORK( J )*AB( KA1, J-1 )
1289: 800 CONTINUE
1290: *
1291: * generate rotations in 1st set to annihilate elements which
1292: * have been created outside the band
1293: *
1294: IF( NRT.GT.0 )
1295: $ CALL ZLARGV( NRT, AB( KA1, J1 ), INCA, WORK( J1 ), KA1,
1296: $ RWORK( J1 ), KA1 )
1297: IF( NR.GT.0 ) THEN
1298: *
1299: * apply rotations in 1st set from the right
1300: *
1301: DO 810 L = 1, KA - 1
1302: CALL ZLARTV( NR, AB( L+1, J1 ), INCA, AB( L+2, J1-1 ),
1303: $ INCA, RWORK( J1 ), WORK( J1 ), KA1 )
1304: 810 CONTINUE
1305: *
1306: * apply rotations in 1st set from both sides to diagonal
1307: * blocks
1308: *
1309: CALL ZLAR2V( NR, AB( 1, J1 ), AB( 1, J1-1 ),
1310: $ AB( 2, J1-1 ), INCA, RWORK( J1 ),
1311: $ WORK( J1 ), KA1 )
1312: *
1313: CALL ZLACGV( NR, WORK( J1 ), KA1 )
1314: END IF
1315: *
1316: * start applying rotations in 1st set from the left
1317: *
1318: DO 820 L = KA - 1, KB - K + 1, -1
1319: NRT = ( J2+L-1 ) / KA1
1320: J1T = J2 - ( NRT-1 )*KA1
1321: IF( NRT.GT.0 )
1322: $ CALL ZLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,
1323: $ AB( KA1-L, J1T-KA1+L ), INCA,
1324: $ RWORK( J1T ), WORK( J1T ), KA1 )
1325: 820 CONTINUE
1326: *
1327: IF( WANTX ) THEN
1328: *
1329: * post-multiply X by product of rotations in 1st set
1330: *
1331: DO 830 J = J1, J2, KA1
1332: CALL ZROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
1333: $ RWORK( J ), DCONJG( WORK( J ) ) )
1334: 830 CONTINUE
1335: END IF
1336: 840 CONTINUE
1337: *
1338: IF( UPDATE ) THEN
1339: IF( I2.GT.0 .AND. KBT.GT.0 ) THEN
1340: *
1341: * create nonzero element a(i+kbt,i+kbt-ka-1) outside the
1342: * band and store it in WORK(m-kb+i+kbt)
1343: *
1344: WORK( M-KB+I+KBT ) = -BB( KBT+1, I )*RA1
1345: END IF
1346: END IF
1347: *
1348: DO 880 K = KB, 1, -1
1349: IF( UPDATE ) THEN
1350: J2 = I + K + 1 - MAX( 2, K+I0-M )*KA1
1351: ELSE
1352: J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
1353: END IF
1354: *
1355: * finish applying rotations in 2nd set from the left
1356: *
1357: DO 850 L = KB - K, 1, -1
1358: NRT = ( J2+KA+L-1 ) / KA1
1359: J1T = J2 - ( NRT-1 )*KA1
1360: IF( NRT.GT.0 )
1361: $ CALL ZLARTV( NRT, AB( KA1-L+1, J1T+L-1 ), INCA,
1362: $ AB( KA1-L, J1T+L-1 ), INCA,
1363: $ RWORK( M-KB+J1T+KA ),
1364: $ WORK( M-KB+J1T+KA ), KA1 )
1365: 850 CONTINUE
1366: NR = ( J2+KA-1 ) / KA1
1367: J1 = J2 - ( NR-1 )*KA1
1368: DO 860 J = J1, J2, KA1
1369: WORK( M-KB+J ) = WORK( M-KB+J+KA )
1370: RWORK( M-KB+J ) = RWORK( M-KB+J+KA )
1371: 860 CONTINUE
1372: DO 870 J = J1, J2, KA1
1373: *
1374: * create nonzero element a(j+ka,j-1) outside the band
1375: * and store it in WORK(m-kb+j)
1376: *
1377: WORK( M-KB+J ) = WORK( M-KB+J )*AB( KA1, J-1 )
1378: AB( KA1, J-1 ) = RWORK( M-KB+J )*AB( KA1, J-1 )
1379: 870 CONTINUE
1380: IF( UPDATE ) THEN
1381: IF( I+K.GT.KA1 .AND. K.LE.KBT )
1382: $ WORK( M-KB+I+K-KA ) = WORK( M-KB+I+K )
1383: END IF
1384: 880 CONTINUE
1385: *
1386: DO 920 K = KB, 1, -1
1387: J2 = I + K + 1 - MAX( 1, K+I0-M )*KA1
1388: NR = ( J2+KA-1 ) / KA1
1389: J1 = J2 - ( NR-1 )*KA1
1390: IF( NR.GT.0 ) THEN
1391: *
1392: * generate rotations in 2nd set to annihilate elements
1393: * which have been created outside the band
1394: *
1395: CALL ZLARGV( NR, AB( KA1, J1 ), INCA, WORK( M-KB+J1 ),
1396: $ KA1, RWORK( M-KB+J1 ), KA1 )
1397: *
1398: * apply rotations in 2nd set from the right
1399: *
1400: DO 890 L = 1, KA - 1
1401: CALL ZLARTV( NR, AB( L+1, J1 ), INCA, AB( L+2, J1-1 ),
1402: $ INCA, RWORK( M-KB+J1 ), WORK( M-KB+J1 ),
1403: $ KA1 )
1404: 890 CONTINUE
1405: *
1406: * apply rotations in 2nd set from both sides to diagonal
1407: * blocks
1408: *
1409: CALL ZLAR2V( NR, AB( 1, J1 ), AB( 1, J1-1 ),
1410: $ AB( 2, J1-1 ), INCA, RWORK( M-KB+J1 ),
1411: $ WORK( M-KB+J1 ), KA1 )
1412: *
1413: CALL ZLACGV( NR, WORK( M-KB+J1 ), KA1 )
1414: END IF
1415: *
1416: * start applying rotations in 2nd set from the left
1417: *
1418: DO 900 L = KA - 1, KB - K + 1, -1
1419: NRT = ( J2+L-1 ) / KA1
1420: J1T = J2 - ( NRT-1 )*KA1
1421: IF( NRT.GT.0 )
1422: $ CALL ZLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,
1423: $ AB( KA1-L, J1T-KA1+L ), INCA,
1424: $ RWORK( M-KB+J1T ), WORK( M-KB+J1T ),
1425: $ KA1 )
1426: 900 CONTINUE
1427: *
1428: IF( WANTX ) THEN
1429: *
1430: * post-multiply X by product of rotations in 2nd set
1431: *
1432: DO 910 J = J1, J2, KA1
1433: CALL ZROT( NX, X( 1, J ), 1, X( 1, J-1 ), 1,
1434: $ RWORK( M-KB+J ), DCONJG( WORK( M-KB+J ) ) )
1435: 910 CONTINUE
1436: END IF
1437: 920 CONTINUE
1438: *
1439: DO 940 K = 1, KB - 1
1440: J2 = I + K + 1 - MAX( 1, K+I0-M+1 )*KA1
1441: *
1442: * finish applying rotations in 1st set from the left
1443: *
1444: DO 930 L = KB - K, 1, -1
1445: NRT = ( J2+L-1 ) / KA1
1446: J1T = J2 - ( NRT-1 )*KA1
1447: IF( NRT.GT.0 )
1448: $ CALL ZLARTV( NRT, AB( KA1-L+1, J1T-KA1+L ), INCA,
1449: $ AB( KA1-L, J1T-KA1+L ), INCA,
1450: $ RWORK( J1T ), WORK( J1T ), KA1 )
1451: 930 CONTINUE
1452: 940 CONTINUE
1453: *
1454: IF( KB.GT.1 ) THEN
1455: DO 950 J = 2, I2 - KA
1456: RWORK( J ) = RWORK( J+KA )
1457: WORK( J ) = WORK( J+KA )
1458: 950 CONTINUE
1459: END IF
1460: *
1461: END IF
1462: *
1463: GO TO 490
1464: *
1465: * End of ZHBGST
1466: *
1467: END