3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download DSBTRD + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dsbtrd.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dsbtrd.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dsbtrd.f">
21 * SUBROUTINE DSBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ,
24 * .. Scalar Arguments ..
25 * CHARACTER UPLO, VECT
26 * INTEGER INFO, KD, LDAB, LDQ, N
28 * .. Array Arguments ..
29 * DOUBLE PRECISION AB( LDAB, * ), D( * ), E( * ), Q( LDQ, * ),
39 *> DSBTRD reduces a real symmetric band matrix A to symmetric
40 *> tridiagonal form T by an orthogonal similarity transformation:
49 *> VECT is CHARACTER*1
50 *> = 'N': do not form Q;
52 *> = 'U': update a matrix X, by forming X*Q.
57 *> UPLO is CHARACTER*1
58 *> = 'U': Upper triangle of A is stored;
59 *> = 'L': Lower triangle of A is stored.
65 *> The order of the matrix A. N >= 0.
71 *> The number of superdiagonals of the matrix A if UPLO = 'U',
72 *> or the number of subdiagonals if UPLO = 'L'. KD >= 0.
77 *> AB is DOUBLE PRECISION array, dimension (LDAB,N)
78 *> On entry, the upper or lower triangle of the symmetric band
79 *> matrix A, stored in the first KD+1 rows of the array. The
80 *> j-th column of A is stored in the j-th column of the array AB
82 *> if UPLO = 'U', AB(kd+1+i-j,j) = A(i,j) for max(1,j-kd)<=i<=j;
83 *> if UPLO = 'L', AB(1+i-j,j) = A(i,j) for j<=i<=min(n,j+kd).
84 *> On exit, the diagonal elements of AB are overwritten by the
85 *> diagonal elements of the tridiagonal matrix T; if KD > 0, the
86 *> elements on the first superdiagonal (if UPLO = 'U') or the
87 *> first subdiagonal (if UPLO = 'L') are overwritten by the
88 *> off-diagonal elements of T; the rest of AB is overwritten by
89 *> values generated during the reduction.
95 *> The leading dimension of the array AB. LDAB >= KD+1.
100 *> D is DOUBLE PRECISION array, dimension (N)
101 *> The diagonal elements of the tridiagonal matrix T.
106 *> E is DOUBLE PRECISION array, dimension (N-1)
107 *> The off-diagonal elements of the tridiagonal matrix T:
108 *> E(i) = T(i,i+1) if UPLO = 'U'; E(i) = T(i+1,i) if UPLO = 'L'.
113 *> Q is DOUBLE PRECISION array, dimension (LDQ,N)
114 *> On entry, if VECT = 'U', then Q must contain an N-by-N
115 *> matrix X; if VECT = 'N' or 'V', then Q need not be set.
118 *> if VECT = 'V', Q contains the N-by-N orthogonal matrix Q;
119 *> if VECT = 'U', Q contains the product X*Q;
120 *> if VECT = 'N', the array Q is not referenced.
126 *> The leading dimension of the array Q.
127 *> LDQ >= 1, and LDQ >= N if VECT = 'V' or 'U'.
132 *> WORK is DOUBLE PRECISION array, dimension (N)
138 *> = 0: successful exit
139 *> < 0: if INFO = -i, the i-th argument had an illegal value
145 *> \author Univ. of Tennessee
146 *> \author Univ. of California Berkeley
147 *> \author Univ. of Colorado Denver
150 *> \date November 2011
152 *> \ingroup doubleOTHERcomputational
154 *> \par Further Details:
155 * =====================
159 *> Modified by Linda Kaufman, Bell Labs.
162 * =====================================================================
163 SUBROUTINE DSBTRD( VECT, UPLO, N, KD, AB, LDAB, D, E, Q, LDQ,
166 * -- LAPACK computational routine (version 3.4.0) --
167 * -- LAPACK is a software package provided by Univ. of Tennessee, --
168 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
171 * .. Scalar Arguments ..
173 INTEGER INFO, KD, LDAB, LDQ, N
175 * .. Array Arguments ..
176 DOUBLE PRECISION AB( LDAB, * ), D( * ), E( * ), Q( LDQ, * ),
180 * =====================================================================
183 DOUBLE PRECISION ZERO, ONE
184 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 )
186 * .. Local Scalars ..
187 LOGICAL INITQ, UPPER, WANTQ
188 INTEGER I, I2, IBL, INCA, INCX, IQAEND, IQB, IQEND, J,
189 $ J1, J1END, J1INC, J2, JEND, JIN, JINC, K, KD1,
190 $ KDM1, KDN, L, LAST, LEND, NQ, NR, NRT
191 DOUBLE PRECISION TEMP
193 * .. External Subroutines ..
194 EXTERNAL DLAR2V, DLARGV, DLARTG, DLARTV, DLASET, DROT,
197 * .. Intrinsic Functions ..
200 * .. External Functions ..
204 * .. Executable Statements ..
206 * Test the input parameters
208 INITQ = LSAME( VECT, 'V' )
209 WANTQ = INITQ .OR. LSAME( VECT, 'U' )
210 UPPER = LSAME( UPLO, 'U' )
217 IF( .NOT.WANTQ .AND. .NOT.LSAME( VECT, 'N' ) ) THEN
219 ELSE IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
221 ELSE IF( N.LT.0 ) THEN
223 ELSE IF( KD.LT.0 ) THEN
225 ELSE IF( LDAB.LT.KD1 ) THEN
227 ELSE IF( LDQ.LT.MAX( 1, N ) .AND. WANTQ ) THEN
231 CALL XERBLA( 'DSBTRD', -INFO )
235 * Quick return if possible
240 * Initialize Q to the unit matrix, if needed
243 $ CALL DLASET( 'Full', N, N, ZERO, ONE, Q, LDQ )
245 * Wherever possible, plane rotations are generated and applied in
246 * vector operations of length NR over the index set J1:J2:KD1.
248 * The cosines and sines of the plane rotations are stored in the
257 * Reduce to tridiagonal form, working with upper triangle
265 * Reduce i-th row of matrix to tridiagonal form
267 DO 80 K = KDN + 1, 2, -1
273 * generate plane rotations to annihilate nonzero
274 * elements which have been created outside the band
276 CALL DLARGV( NR, AB( 1, J1-1 ), INCA, WORK( J1 ),
277 $ KD1, D( J1 ), KD1 )
279 * apply rotations from the right
282 * Dependent on the the number of diagonals either
283 * DLARTV or DROT is used
285 IF( NR.GE.2*KD-1 ) THEN
287 CALL DLARTV( NR, AB( L+1, J1-1 ), INCA,
288 $ AB( L, J1 ), INCA, D( J1 ),
293 JEND = J1 + ( NR-1 )*KD1
294 DO 20 JINC = J1, JEND, KD1
295 CALL DROT( KDM1, AB( 2, JINC-1 ), 1,
296 $ AB( 1, JINC ), 1, D( JINC ),
304 IF( K.LE.N-I+1 ) THEN
306 * generate plane rotation to annihilate a(i,i+k-1)
309 CALL DLARTG( AB( KD-K+3, I+K-2 ),
310 $ AB( KD-K+2, I+K-1 ), D( I+K-1 ),
311 $ WORK( I+K-1 ), TEMP )
312 AB( KD-K+3, I+K-2 ) = TEMP
314 * apply rotation from the right
316 CALL DROT( K-3, AB( KD-K+4, I+K-2 ), 1,
317 $ AB( KD-K+3, I+K-1 ), 1, D( I+K-1 ),
324 * apply plane rotations from both sides to diagonal
328 $ CALL DLAR2V( NR, AB( KD1, J1-1 ), AB( KD1, J1 ),
329 $ AB( KD, J1 ), INCA, D( J1 ),
332 * apply plane rotations from the left
335 IF( 2*KD-1.LT.NR ) THEN
337 * Dependent on the the number of diagonals either
338 * DLARTV or DROT is used
347 $ CALL DLARTV( NRT, AB( KD-L, J1+L ), INCA,
348 $ AB( KD-L+1, J1+L ), INCA,
349 $ D( J1 ), WORK( J1 ), KD1 )
352 J1END = J1 + KD1*( NR-2 )
353 IF( J1END.GE.J1 ) THEN
354 DO 40 JIN = J1, J1END, KD1
355 CALL DROT( KD-1, AB( KD-1, JIN+1 ), INCX,
356 $ AB( KD, JIN+1 ), INCX,
357 $ D( JIN ), WORK( JIN ) )
360 LEND = MIN( KDM1, N-J2 )
363 $ CALL DROT( LEND, AB( KD-1, LAST+1 ), INCX,
364 $ AB( KD, LAST+1 ), INCX, D( LAST ),
371 * accumulate product of plane rotations in Q
375 * take advantage of the fact that Q was
376 * initially the Identity matrix
378 IQEND = MAX( IQEND, J2 )
382 $ IQAEND = IQAEND + KD
383 IQAEND = MIN( IQAEND, IQEND )
384 DO 50 J = J1, J2, KD1
387 IQB = MAX( 1, J-IBL )
388 NQ = 1 + IQAEND - IQB
389 IQAEND = MIN( IQAEND+KD, IQEND )
390 CALL DROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
391 $ 1, D( J ), WORK( J ) )
395 DO 60 J = J1, J2, KD1
396 CALL DROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
397 $ D( J ), WORK( J ) )
403 IF( J2+KDN.GT.N ) THEN
405 * adjust J2 to keep within the bounds of the matrix
411 DO 70 J = J1, J2, KD1
413 * create nonzero element a(j-1,j+kd) outside the band
414 * and store it in WORK
416 WORK( J+KD ) = WORK( J )*AB( 1, J+KD )
417 AB( 1, J+KD ) = D( J )*AB( 1, J+KD )
425 * copy off-diagonal elements to E
428 E( I ) = AB( KD, I+1 )
432 * set E to zero if original matrix was diagonal
439 * copy diagonal elements to D
442 D( I ) = AB( KD1, I )
449 * Reduce to tridiagonal form, working with lower triangle
457 * Reduce i-th column of matrix to tridiagonal form
459 DO 200 K = KDN + 1, 2, -1
465 * generate plane rotations to annihilate nonzero
466 * elements which have been created outside the band
468 CALL DLARGV( NR, AB( KD1, J1-KD1 ), INCA,
469 $ WORK( J1 ), KD1, D( J1 ), KD1 )
471 * apply plane rotations from one side
474 * Dependent on the the number of diagonals either
475 * DLARTV or DROT is used
477 IF( NR.GT.2*KD-1 ) THEN
479 CALL DLARTV( NR, AB( KD1-L, J1-KD1+L ), INCA,
480 $ AB( KD1-L+1, J1-KD1+L ), INCA,
481 $ D( J1 ), WORK( J1 ), KD1 )
484 JEND = J1 + KD1*( NR-1 )
485 DO 140 JINC = J1, JEND, KD1
486 CALL DROT( KDM1, AB( KD, JINC-KD ), INCX,
487 $ AB( KD1, JINC-KD ), INCX,
488 $ D( JINC ), WORK( JINC ) )
495 IF( K.LE.N-I+1 ) THEN
497 * generate plane rotation to annihilate a(i+k-1,i)
500 CALL DLARTG( AB( K-1, I ), AB( K, I ),
501 $ D( I+K-1 ), WORK( I+K-1 ), TEMP )
504 * apply rotation from the left
506 CALL DROT( K-3, AB( K-2, I+1 ), LDAB-1,
507 $ AB( K-1, I+1 ), LDAB-1, D( I+K-1 ),
514 * apply plane rotations from both sides to diagonal
518 $ CALL DLAR2V( NR, AB( 1, J1-1 ), AB( 1, J1 ),
519 $ AB( 2, J1-1 ), INCA, D( J1 ),
522 * apply plane rotations from the right
525 * Dependent on the the number of diagonals either
526 * DLARTV or DROT is used
529 IF( NR.GT.2*KD-1 ) THEN
537 $ CALL DLARTV( NRT, AB( L+2, J1-1 ), INCA,
538 $ AB( L+1, J1 ), INCA, D( J1 ),
542 J1END = J1 + KD1*( NR-2 )
543 IF( J1END.GE.J1 ) THEN
544 DO 160 J1INC = J1, J1END, KD1
545 CALL DROT( KDM1, AB( 3, J1INC-1 ), 1,
546 $ AB( 2, J1INC ), 1, D( J1INC ),
550 LEND = MIN( KDM1, N-J2 )
553 $ CALL DROT( LEND, AB( 3, LAST-1 ), 1,
554 $ AB( 2, LAST ), 1, D( LAST ),
563 * accumulate product of plane rotations in Q
567 * take advantage of the fact that Q was
568 * initially the Identity matrix
570 IQEND = MAX( IQEND, J2 )
574 $ IQAEND = IQAEND + KD
575 IQAEND = MIN( IQAEND, IQEND )
576 DO 170 J = J1, J2, KD1
579 IQB = MAX( 1, J-IBL )
580 NQ = 1 + IQAEND - IQB
581 IQAEND = MIN( IQAEND+KD, IQEND )
582 CALL DROT( NQ, Q( IQB, J-1 ), 1, Q( IQB, J ),
583 $ 1, D( J ), WORK( J ) )
587 DO 180 J = J1, J2, KD1
588 CALL DROT( N, Q( 1, J-1 ), 1, Q( 1, J ), 1,
589 $ D( J ), WORK( J ) )
594 IF( J2+KDN.GT.N ) THEN
596 * adjust J2 to keep within the bounds of the matrix
602 DO 190 J = J1, J2, KD1
604 * create nonzero element a(j+kd,j-1) outside the
605 * band and store it in WORK
607 WORK( J+KD ) = WORK( J )*AB( KD1, J )
608 AB( KD1, J ) = D( J )*AB( KD1, J )
616 * copy off-diagonal elements to E
623 * set E to zero if original matrix was diagonal
630 * copy diagonal elements to D