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

◆ zsteqr()

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

ZSTEQR

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

Purpose:
!>
!> ZSTEQR 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 complex Hermitian matrix can also
!> be found if ZHETRD or ZHPTRD or ZHBTRD 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
!>                  Hermitian matrix.  On entry, Z must contain the
!>                  unitary 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 COMPLEX*16 array, dimension (LDZ, N)
!>          On entry, if  COMPZ = 'V', then Z contains the unitary
!>          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 Hermitian 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 unitarily similar to the original
!>                matrix.
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 129 of file zsteqr.f.

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