LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ dsteqr()

subroutine dsteqr ( character compz,
integer n,
double precision, dimension( * ) d,
double precision, dimension( * ) e,
double precision, dimension( ldz, * ) z,
integer ldz,
double precision, dimension( * ) work,
integer info )

DSTEQR

Download DSTEQR + dependencies [TGZ] [ZIP] [TXT]

Purpose:
!>
!> DSTEQR computes all eigenvalues and, optionally, eigenvectors of a
!> symmetric tridiagonal matrix using the implicit QL or QR method.
!> The eigenvectors of a full or band symmetric matrix can also be found
!> if DSYTRD or DSPTRD or DSBTRD has been used to reduce this matrix to
!> tridiagonal form.
!> 
Parameters
[in]COMPZ
!>          COMPZ is CHARACTER*1
!>          = 'N':  Compute eigenvalues only.
!>          = 'V':  Compute eigenvalues and eigenvectors of the original
!>                  symmetric matrix.  On entry, Z must contain the
!>                  orthogonal matrix used to reduce the original matrix
!>                  to tridiagonal form.
!>          = 'I':  Compute eigenvalues and eigenvectors of the
!>                  tridiagonal matrix.  Z is initialized to the identity
!>                  matrix.
!> 
[in]N
!>          N is INTEGER
!>          The order of the matrix.  N >= 0.
!> 
[in,out]D
!>          D is DOUBLE PRECISION array, dimension (N)
!>          On entry, the diagonal elements of the tridiagonal matrix.
!>          On exit, if INFO = 0, the eigenvalues in ascending order.
!> 
[in,out]E
!>          E is DOUBLE PRECISION array, dimension (N-1)
!>          On entry, the (n-1) subdiagonal elements of the tridiagonal
!>          matrix.
!>          On exit, E has been destroyed.
!> 
[in,out]Z
!>          Z is DOUBLE PRECISION array, dimension (LDZ, N)
!>          On entry, if  COMPZ = 'V', then Z contains the orthogonal
!>          matrix used in the reduction to tridiagonal form.
!>          On exit, if INFO = 0, then if  COMPZ = 'V', Z contains the
!>          orthonormal eigenvectors of the original symmetric matrix,
!>          and if COMPZ = 'I', Z contains the orthonormal eigenvectors
!>          of the symmetric tridiagonal matrix.
!>          If COMPZ = 'N', then Z is not referenced.
!> 
[in]LDZ
!>          LDZ is INTEGER
!>          The leading dimension of the array Z.  LDZ >= 1, and if
!>          eigenvectors are desired, then  LDZ >= max(1,N).
!> 
[out]WORK
!>          WORK is DOUBLE PRECISION array, dimension (max(1,2*N-2))
!>          If COMPZ = 'N', then WORK is not referenced.
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0:  successful exit
!>          < 0:  if INFO = -i, the i-th argument had an illegal value
!>          > 0:  the algorithm has failed to find all the eigenvalues in
!>                a total of 30*N iterations; if INFO = i, then i
!>                elements of E have not converged to zero; on exit, D
!>                and E contain the elements of a symmetric tridiagonal
!>                matrix which is orthogonally similar to the original
!>                matrix.
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 128 of file dsteqr.f.

129*
130* -- LAPACK computational routine --
131* -- LAPACK is a software package provided by Univ. of Tennessee, --
132* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
133*
134* .. Scalar Arguments ..
135 CHARACTER COMPZ
136 INTEGER INFO, LDZ, N
137* ..
138* .. Array Arguments ..
139 DOUBLE PRECISION D( * ), E( * ), WORK( * ), Z( LDZ, * )
140* ..
141*
142* =====================================================================
143*
144* .. Parameters ..
145 DOUBLE PRECISION ZERO, ONE, TWO, THREE
146 parameter( zero = 0.0d0, one = 1.0d0, two = 2.0d0,
147 $ three = 3.0d0 )
148 INTEGER MAXIT
149 parameter( maxit = 30 )
150* ..
151* .. Local Scalars ..
152 INTEGER I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND,
153 $ LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1,
154 $ NM1, NMAXIT
155 DOUBLE PRECISION ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2,
156 $ S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST
157* ..
158* .. External Functions ..
159 LOGICAL LSAME
160 DOUBLE PRECISION DLAMCH, DLANST, DLAPY2
161 EXTERNAL lsame, dlamch, dlanst, dlapy2
162* ..
163* .. External Subroutines ..
164 EXTERNAL dlae2, dlaev2, dlartg, dlascl, dlaset,
165 $ dlasr,
167* ..
168* .. Intrinsic Functions ..
169 INTRINSIC abs, max, sign, sqrt
170* ..
171* .. Executable Statements ..
172*
173* Test the input parameters.
174*
175 info = 0
176*
177 IF( lsame( compz, 'N' ) ) THEN
178 icompz = 0
179 ELSE IF( lsame( compz, 'V' ) ) THEN
180 icompz = 1
181 ELSE IF( lsame( compz, 'I' ) ) THEN
182 icompz = 2
183 ELSE
184 icompz = -1
185 END IF
186 IF( icompz.LT.0 ) THEN
187 info = -1
188 ELSE IF( n.LT.0 ) THEN
189 info = -2
190 ELSE IF( ( ldz.LT.1 ) .OR. ( icompz.GT.0 .AND. ldz.LT.max( 1,
191 $ n ) ) ) THEN
192 info = -6
193 END IF
194 IF( info.NE.0 ) THEN
195 CALL xerbla( 'DSTEQR', -info )
196 RETURN
197 END IF
198*
199* Quick return if possible
200*
201 IF( n.EQ.0 )
202 $ RETURN
203*
204 IF( n.EQ.1 ) THEN
205 IF( icompz.EQ.2 )
206 $ z( 1, 1 ) = one
207 RETURN
208 END IF
209*
210* Determine the unit roundoff and over/underflow thresholds.
211*
212 eps = dlamch( 'E' )
213 eps2 = eps**2
214 safmin = dlamch( 'S' )
215 safmax = one / safmin
216 ssfmax = sqrt( safmax ) / three
217 ssfmin = sqrt( safmin ) / eps2
218*
219* Compute the eigenvalues and eigenvectors of the tridiagonal
220* matrix.
221*
222 IF( icompz.EQ.2 )
223 $ CALL dlaset( 'Full', n, n, zero, one, z, ldz )
224*
225 nmaxit = n*maxit
226 jtot = 0
227*
228* Determine where the matrix splits and choose QL or QR iteration
229* for each block, according to whether top or bottom diagonal
230* element is smaller.
231*
232 l1 = 1
233 nm1 = n - 1
234*
235 10 CONTINUE
236 IF( l1.GT.n )
237 $ GO TO 160
238 IF( l1.GT.1 )
239 $ e( l1-1 ) = zero
240 IF( l1.LE.nm1 ) THEN
241 DO 20 m = l1, nm1
242 tst = abs( e( m ) )
243 IF( tst.EQ.zero )
244 $ GO TO 30
245 IF( tst.LE.( sqrt( abs( d( m ) ) )*sqrt( abs( d( m+
246 $ 1 ) ) ) )*eps ) THEN
247 e( m ) = zero
248 GO TO 30
249 END IF
250 20 CONTINUE
251 END IF
252 m = n
253*
254 30 CONTINUE
255 l = l1
256 lsv = l
257 lend = m
258 lendsv = lend
259 l1 = m + 1
260 IF( lend.EQ.l )
261 $ GO TO 10
262*
263* Scale submatrix in rows and columns L to LEND
264*
265 anorm = dlanst( 'M', lend-l+1, d( l ), e( l ) )
266 iscale = 0
267 IF( anorm.EQ.zero )
268 $ GO TO 10
269 IF( anorm.GT.ssfmax ) THEN
270 iscale = 1
271 CALL dlascl( 'G', 0, 0, anorm, ssfmax, lend-l+1, 1, d( l ),
272 $ n,
273 $ info )
274 CALL dlascl( 'G', 0, 0, anorm, ssfmax, lend-l, 1, e( l ), n,
275 $ info )
276 ELSE IF( anorm.LT.ssfmin ) THEN
277 iscale = 2
278 CALL dlascl( 'G', 0, 0, anorm, ssfmin, lend-l+1, 1, d( l ),
279 $ n,
280 $ info )
281 CALL dlascl( 'G', 0, 0, anorm, ssfmin, lend-l, 1, e( l ), n,
282 $ info )
283 END IF
284*
285* Choose between QL and QR iteration
286*
287 IF( abs( d( lend ) ).LT.abs( d( l ) ) ) THEN
288 lend = lsv
289 l = lendsv
290 END IF
291*
292 IF( lend.GT.l ) THEN
293*
294* QL Iteration
295*
296* Look for small subdiagonal element.
297*
298 40 CONTINUE
299 IF( l.NE.lend ) THEN
300 lendm1 = lend - 1
301 DO 50 m = l, lendm1
302 tst = abs( e( m ) )**2
303 IF( tst.LE.( eps2*abs( d( m ) ) )*abs( d( m+1 ) )+
304 $ safmin )GO TO 60
305 50 CONTINUE
306 END IF
307*
308 m = lend
309*
310 60 CONTINUE
311 IF( m.LT.lend )
312 $ e( m ) = zero
313 p = d( l )
314 IF( m.EQ.l )
315 $ GO TO 80
316*
317* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
318* to compute its eigensystem.
319*
320 IF( m.EQ.l+1 ) THEN
321 IF( icompz.GT.0 ) THEN
322 CALL dlaev2( d( l ), e( l ), d( l+1 ), rt1, rt2, c,
323 $ s )
324 work( l ) = c
325 work( n-1+l ) = s
326 CALL dlasr( 'R', 'V', 'B', n, 2, work( l ),
327 $ work( n-1+l ), z( 1, l ), ldz )
328 ELSE
329 CALL dlae2( d( l ), e( l ), d( l+1 ), rt1, rt2 )
330 END IF
331 d( l ) = rt1
332 d( l+1 ) = rt2
333 e( l ) = zero
334 l = l + 2
335 IF( l.LE.lend )
336 $ GO TO 40
337 GO TO 140
338 END IF
339*
340 IF( jtot.EQ.nmaxit )
341 $ GO TO 140
342 jtot = jtot + 1
343*
344* Form shift.
345*
346 g = ( d( l+1 )-p ) / ( two*e( l ) )
347 r = dlapy2( g, one )
348 g = d( m ) - p + ( e( l ) / ( g+sign( r, g ) ) )
349*
350 s = one
351 c = one
352 p = zero
353*
354* Inner loop
355*
356 mm1 = m - 1
357 DO 70 i = mm1, l, -1
358 f = s*e( i )
359 b = c*e( i )
360 CALL dlartg( g, f, c, s, r )
361 IF( i.NE.m-1 )
362 $ e( i+1 ) = r
363 g = d( i+1 ) - p
364 r = ( d( i )-g )*s + two*c*b
365 p = s*r
366 d( i+1 ) = g + p
367 g = c*r - b
368*
369* If eigenvectors are desired, then save rotations.
370*
371 IF( icompz.GT.0 ) THEN
372 work( i ) = c
373 work( n-1+i ) = -s
374 END IF
375*
376 70 CONTINUE
377*
378* If eigenvectors are desired, then apply saved rotations.
379*
380 IF( icompz.GT.0 ) THEN
381 mm = m - l + 1
382 CALL dlasr( 'R', 'V', 'B', n, mm, work( l ),
383 $ work( n-1+l ),
384 $ z( 1, l ), ldz )
385 END IF
386*
387 d( l ) = d( l ) - p
388 e( l ) = g
389 GO TO 40
390*
391* Eigenvalue found.
392*
393 80 CONTINUE
394 d( l ) = p
395*
396 l = l + 1
397 IF( l.LE.lend )
398 $ GO TO 40
399 GO TO 140
400*
401 ELSE
402*
403* QR Iteration
404*
405* Look for small superdiagonal element.
406*
407 90 CONTINUE
408 IF( l.NE.lend ) THEN
409 lendp1 = lend + 1
410 DO 100 m = l, lendp1, -1
411 tst = abs( e( m-1 ) )**2
412 IF( tst.LE.( eps2*abs( d( m ) ) )*abs( d( m-1 ) )+
413 $ safmin )GO TO 110
414 100 CONTINUE
415 END IF
416*
417 m = lend
418*
419 110 CONTINUE
420 IF( m.GT.lend )
421 $ e( m-1 ) = zero
422 p = d( l )
423 IF( m.EQ.l )
424 $ GO TO 130
425*
426* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
427* to compute its eigensystem.
428*
429 IF( m.EQ.l-1 ) THEN
430 IF( icompz.GT.0 ) THEN
431 CALL dlaev2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2, c,
432 $ s )
433 work( m ) = c
434 work( n-1+m ) = s
435 CALL dlasr( 'R', 'V', 'F', n, 2, work( m ),
436 $ work( n-1+m ), z( 1, l-1 ), ldz )
437 ELSE
438 CALL dlae2( d( l-1 ), e( l-1 ), d( l ), rt1, rt2 )
439 END IF
440 d( l-1 ) = rt1
441 d( l ) = rt2
442 e( l-1 ) = zero
443 l = l - 2
444 IF( l.GE.lend )
445 $ GO TO 90
446 GO TO 140
447 END IF
448*
449 IF( jtot.EQ.nmaxit )
450 $ GO TO 140
451 jtot = jtot + 1
452*
453* Form shift.
454*
455 g = ( d( l-1 )-p ) / ( two*e( l-1 ) )
456 r = dlapy2( g, one )
457 g = d( m ) - p + ( e( l-1 ) / ( g+sign( r, g ) ) )
458*
459 s = one
460 c = one
461 p = zero
462*
463* Inner loop
464*
465 lm1 = l - 1
466 DO 120 i = m, lm1
467 f = s*e( i )
468 b = c*e( i )
469 CALL dlartg( g, f, c, s, r )
470 IF( i.NE.m )
471 $ e( i-1 ) = r
472 g = d( i ) - p
473 r = ( d( i+1 )-g )*s + two*c*b
474 p = s*r
475 d( i ) = g + p
476 g = c*r - b
477*
478* If eigenvectors are desired, then save rotations.
479*
480 IF( icompz.GT.0 ) THEN
481 work( i ) = c
482 work( n-1+i ) = s
483 END IF
484*
485 120 CONTINUE
486*
487* If eigenvectors are desired, then apply saved rotations.
488*
489 IF( icompz.GT.0 ) THEN
490 mm = l - m + 1
491 CALL dlasr( 'R', 'V', 'F', n, mm, work( m ),
492 $ work( n-1+m ),
493 $ z( 1, m ), ldz )
494 END IF
495*
496 d( l ) = d( l ) - p
497 e( lm1 ) = g
498 GO TO 90
499*
500* Eigenvalue found.
501*
502 130 CONTINUE
503 d( l ) = p
504*
505 l = l - 1
506 IF( l.GE.lend )
507 $ GO TO 90
508 GO TO 140
509*
510 END IF
511*
512* Undo scaling if necessary
513*
514 140 CONTINUE
515 IF( iscale.EQ.1 ) THEN
516 CALL dlascl( 'G', 0, 0, ssfmax, anorm, lendsv-lsv+1, 1,
517 $ d( lsv ), n, info )
518 CALL dlascl( 'G', 0, 0, ssfmax, anorm, lendsv-lsv, 1,
519 $ e( lsv ),
520 $ n, info )
521 ELSE IF( iscale.EQ.2 ) THEN
522 CALL dlascl( 'G', 0, 0, ssfmin, anorm, lendsv-lsv+1, 1,
523 $ d( lsv ), n, info )
524 CALL dlascl( 'G', 0, 0, ssfmin, anorm, lendsv-lsv, 1,
525 $ e( lsv ),
526 $ n, info )
527 END IF
528*
529* Check for no convergence to an eigenvalue after a total
530* of N*MAXIT iterations.
531*
532 IF( jtot.LT.nmaxit )
533 $ GO TO 10
534 DO 150 i = 1, n - 1
535 IF( e( i ).NE.zero )
536 $ info = info + 1
537 150 CONTINUE
538 GO TO 190
539*
540* Order eigenvalues and eigenvectors.
541*
542 160 CONTINUE
543 IF( icompz.EQ.0 ) THEN
544*
545* Use Quick Sort
546*
547 CALL dlasrt( 'I', n, d, info )
548*
549 ELSE
550*
551* Use Selection Sort to minimize swaps of eigenvectors
552*
553 DO 180 ii = 2, n
554 i = ii - 1
555 k = i
556 p = d( i )
557 DO 170 j = ii, n
558 IF( d( j ).LT.p ) THEN
559 k = j
560 p = d( j )
561 END IF
562 170 CONTINUE
563 IF( k.NE.i ) THEN
564 d( k ) = d( i )
565 d( i ) = p
566 CALL dswap( n, z( 1, i ), 1, z( 1, k ), 1 )
567 END IF
568 180 CONTINUE
569 END IF
570*
571 190 CONTINUE
572 RETURN
573*
574* End of DSTEQR
575*
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine dlae2(a, b, c, rt1, rt2)
DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix.
Definition dlae2.f:100
subroutine dlaev2(a, b, c, rt1, rt2, cs1, sn1)
DLAEV2 computes the eigenvalues and eigenvectors of a 2-by-2 symmetric/Hermitian matrix.
Definition dlaev2.f:118
double precision function dlamch(cmach)
DLAMCH
Definition dlamch.f:69
double precision function dlanst(norm, n, d, e)
DLANST returns the value of the 1-norm, or the Frobenius norm, or the infinity norm,...
Definition dlanst.f:98
double precision function dlapy2(x, y)
DLAPY2 returns sqrt(x2+y2).
Definition dlapy2.f:61
subroutine dlartg(f, g, c, s, r)
DLARTG generates a plane rotation with real cosine and real sine.
Definition dlartg.f90:111
subroutine dlascl(type, kl, ku, cfrom, cto, m, n, a, lda, info)
DLASCL multiplies a general rectangular matrix by a real scalar defined as cto/cfrom.
Definition dlascl.f:142
subroutine dlaset(uplo, m, n, alpha, beta, a, lda)
DLASET initializes the off-diagonal elements and the diagonal elements of a matrix to given values.
Definition dlaset.f:108
subroutine dlasr(side, pivot, direct, m, n, c, s, a, lda)
DLASR applies a sequence of plane rotations to a general rectangular matrix.
Definition dlasr.f:197
subroutine dlasrt(id, n, d, info)
DLASRT sorts numbers in increasing or decreasing order.
Definition dlasrt.f:86
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
subroutine dswap(n, dx, incx, dy, incy)
DSWAP
Definition dswap.f:82
Here is the call graph for this function:
Here is the caller graph for this function: