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