1
c-----------------------------------------------------------------------
7
c Computes all eigenvalues and the last component of the eigenvectors
8
c of a symmetric tridiagonal matrix using the implicit QL or QR method.
10
c This is mostly a modification of the LAPACK routine dsteqr.
15
c ( N, D, E, Z, WORK, INFO )
19
c The number of rows and columns in the matrix. N >= 0.
21
c D Double precision array, dimension (N). (INPUT/OUTPUT)
22
c On entry, D contains the diagonal elements of the
24
c On exit, D contains the eigenvalues, in ascending order.
25
c If an error exit is made, the eigenvalues are correct
26
c for indices 1,2,...,INFO-1, but they are unordered and
27
c may not be the smallest eigenvalues of the matrix.
29
c E Double precision array, dimension (N-1). (INPUT/OUTPUT)
30
c On entry, E contains the subdiagonal elements of the
31
c tridiagonal matrix in positions 1 through N-1.
32
c On exit, E has been destroyed.
34
c Z Double precision array, dimension (N). (OUTPUT)
35
c On exit, Z contains the last row of the orthonormal
36
c eigenvector matrix of the symmetric tridiagonal matrix.
37
c If an error exit is made, Z contains the last row of the
38
c eigenvector matrix associated with the stored eigenvalues.
40
c WORK Double precision array, dimension (max(1,2*N-2)). (WORKSPACE)
41
c Workspace used in accumulating the transformation for
42
c computing the last components of the eigenvectors.
44
c INFO Integer. (OUTPUT)
46
c < 0: if INFO = -i, the i-th argument had an illegal value.
47
c > 0: if INFO = +i, the i-th eigenvalue has not converged
48
c after a total of 30*N iterations.
53
c-----------------------------------------------------------------------
61
c daxpy Level 1 BLAS that computes a vector triad.
62
c dcopy Level 1 BLAS that copies one vector to another.
63
c dswap Level 1 BLAS that swaps the contents of two vectors.
64
c lsame LAPACK character comparison routine.
65
c dlae2 LAPACK routine that computes the eigenvalues of a 2-by-2
67
c dlaev2 LAPACK routine that eigendecomposition of a 2-by-2 symmetric
69
c dlamch LAPACK routine that determines machine constants.
70
c dlanst LAPACK routine that computes the norm of a matrix.
71
c dlapy2 LAPACK routine to compute sqrt(x**2+y**2) carefully.
72
c dlartg LAPACK Givens rotation construction routine.
73
c dlascl LAPACK routine for careful scaling of a matrix.
74
c dlaset LAPACK matrix initialization routine.
75
c dlasr LAPACK routine that applies an orthogonal transformation to
77
c dlasrt LAPACK sorting routine.
78
c dsteqr LAPACK routine that computes eigenvalues and eigenvectors
79
c of a symmetric tridiagonal matrix.
80
c xerbla LAPACK error handler routine.
83
c Danny Sorensen Phuong Vu
84
c Richard Lehoucq CRPC / Rice University
85
c Dept. of Computational & Houston, Texas
90
c\SCCS Information: @(#)
91
c FILE: stqrb.F SID: 2.5 DATE OF SID: 8/27/96 RELEASE: 2
94
c 1. Starting with version 2.5, this routine is a modified version
95
c of LAPACK version 2.0 subroutine SSTEQR. No lines are deleted,
96
c only commeted out and new lines inserted.
97
c All lines commented out have "c$$$" at the beginning.
98
c Note that the LAPACK version 1.0 subroutine SSTEQR contained
103
c-----------------------------------------------------------------------
105
subroutine dstqrb ( n, d, e, z, work, info )
107
c %------------------%
108
c | Scalar Arguments |
109
c %------------------%
113
c %-----------------%
114
c | Array Arguments |
115
c %-----------------%
118
& d( n ), e( n-1 ), z( n ), work( 2*n-2 )
122
& zero, one, two, three
123
parameter ( zero = 0.0D+0, one = 1.0D+0,
124
& two = 2.0D+0, three = 3.0D+0 )
126
parameter ( maxit = 30 )
128
c .. local scalars ..
129
integer i, icompz, ii, iscale, j, jtot, k, l, l1, lend,
130
& lendm1, lendp1, lendsv, lm1, lsv, m, mm, mm1,
133
& anorm, b, c, eps, eps2, f, g, p, r, rt1, rt2,
134
& s, safmax, safmin, ssfmax, ssfmin, tst
136
c .. external functions ..
139
& dlamch, dlanst, dlapy2
140
external lsame, dlamch, dlanst, dlapy2
142
c .. external subroutines ..
143
external dlae2, dlaev2, dlartg, dlascl, dlaset, dlasr,
144
& dlasrt, dswap, xerbla
146
c .. intrinsic functions ..
147
intrinsic abs, max, sign, sqrt
149
c .. executable statements ..
151
c test the input parameters.
155
c$$$ IF( LSAME( COMPZ, 'N' ) ) THEN
157
c$$$ ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
159
c$$$ ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
164
c$$$ IF( ICOMPZ.LT.0 ) THEN
166
c$$$ ELSE IF( N.LT.0 ) THEN
168
c$$$ ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
172
c$$$ IF( INFO.NE.0 ) THEN
173
c$$$ CALL XERBLA( 'SSTEQR', -INFO )
177
c *** New starting with version 2.5 ***
180
c *************************************
182
c quick return if possible
188
if( icompz.eq.2 ) z( 1 ) = one
192
c determine the unit roundoff and over/underflow thresholds.
196
safmin = dlamch( 's' )
197
safmax = one / safmin
198
ssfmax = sqrt( safmax ) / three
199
ssfmin = sqrt( safmin ) / eps2
201
c compute the eigenvalues and eigenvectors of the tridiagonal
204
c$$ if( icompz.eq.2 )
205
c$$$ $ call dlaset( 'full', n, n, zero, one, z, ldz )
207
c *** New starting with version 2.5 ***
209
if ( icompz .eq. 2 ) then
215
c *************************************
220
c determine where the matrix splits and choose ql or qr iteration
221
c for each block, according to whether top or bottom diagonal
222
c element is smaller.
237
if( tst.le.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
238
$ 1 ) ) ) )*eps ) then
255
c scale submatrix in rows and columns l to lend
257
anorm = dlanst( 'i', lend-l+1, d( l ), e( l ) )
261
if( anorm.gt.ssfmax ) then
263
call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ), n,
265
call dlascl( 'g', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
267
else if( anorm.lt.ssfmin ) then
269
call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ), n,
271
call dlascl( 'g', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
275
c choose between ql and qr iteration
277
if( abs( d( lend ) ).lt.abs( d( l ) ) ) then
286
c look for small subdiagonal element.
292
tst = abs( e( m ) )**2
293
if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+
307
c if remaining matrix is 2-by-2, use dlae2 or dlaev2
308
c to compute its eigensystem.
311
if( icompz.gt.0 ) then
312
call dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c, s )
315
c$$$ call dlasr( 'r', 'v', 'b', n, 2, work( l ),
316
c$$$ $ work( n-1+l ), z( 1, l ), ldz )
318
c *** New starting with version 2.5 ***
321
z(l+1) = c*tst - s*z(l)
322
z(l) = s*tst + c*z(l)
323
c *************************************
325
call dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 )
342
g = ( d( l+1 )-p ) / ( two*e( l ) )
344
g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) )
356
call dlartg( g, f, c, s, r )
360
r = ( d( i )-g )*s + two*c*b
365
c if eigenvectors are desired, then save rotations.
367
if( icompz.gt.0 ) then
374
c if eigenvectors are desired, then apply saved rotations.
376
if( icompz.gt.0 ) then
378
c$$$ call dlasr( 'r', 'v', 'b', n, mm, work( l ), work( n-1+l ),
379
c$$$ $ z( 1, l ), ldz )
381
c *** New starting with version 2.5 ***
383
call dlasr( 'r', 'v', 'b', 1, mm, work( l ),
384
& work( n-1+l ), z( l ), 1 )
385
c *************************************
406
c look for small superdiagonal element.
411
do 100 m = l, lendp1, -1
412
tst = abs( e( m-1 ) )**2
413
if( tst.le.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+
427
c if remaining matrix is 2-by-2, use dlae2 or dlaev2
428
c to compute its eigensystem.
431
if( icompz.gt.0 ) then
432
call dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c, s )
434
c$$$ work( n-1+m ) = s
435
c$$$ call dlasr( 'r', 'v', 'f', n, 2, work( m ),
436
c$$$ $ work( n-1+m ), z( 1, l-1 ), ldz )
438
c *** New starting with version 2.5 ***
441
z(l) = c*tst - s*z(l-1)
442
z(l-1) = s*tst + c*z(l-1)
443
c *************************************
445
call dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 )
462
g = ( d( l-1 )-p ) / ( two*e( l-1 ) )
464
g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) )
476
call dlartg( g, f, c, s, r )
480
r = ( d( i+1 )-g )*s + two*c*b
485
c if eigenvectors are desired, then save rotations.
487
if( icompz.gt.0 ) then
494
c if eigenvectors are desired, then apply saved rotations.
496
if( icompz.gt.0 ) then
498
c$$$ call dlasr( 'r', 'v', 'f', n, mm, work( m ), work( n-1+m ),
499
c$$$ $ z( 1, m ), ldz )
501
c *** New starting with version 2.5 ***
503
call dlasr( 'r', 'v', 'f', 1, mm, work( m ), work( n-1+m ),
505
c *************************************
524
c undo scaling if necessary
527
if( iscale.eq.1 ) then
528
call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1,
529
$ d( lsv ), n, info )
530
call dlascl( 'g', 0, 0, ssfmax, anorm, lendsv-lsv, 1, e( lsv ),
532
else if( iscale.eq.2 ) then
533
call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1,
534
$ d( lsv ), n, info )
535
call dlascl( 'g', 0, 0, ssfmin, anorm, lendsv-lsv, 1, e( lsv ),
539
c check for no convergence to an eigenvalue after a total
540
c of n*maxit iterations.
550
c order eigenvalues and eigenvectors.
553
if( icompz.eq.0 ) then
557
call dlasrt( 'i', n, d, info )
561
c use selection sort to minimize swaps of eigenvectors
568
if( d( j ).lt.p ) then
576
c$$$ call dswap( n, z( 1, i ), 1, z( 1, k ), 1 )
577
c *** New starting with version 2.5 ***
582
c *************************************