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

◆ slarrd()

subroutine slarrd ( character range,
character order,
integer n,
real vl,
real vu,
integer il,
integer iu,
real, dimension( * ) gers,
real reltol,
real, dimension( * ) d,
real, dimension( * ) e,
real, dimension( * ) e2,
real pivmin,
integer nsplit,
integer, dimension( * ) isplit,
integer m,
real, dimension( * ) w,
real, dimension( * ) werr,
real wl,
real wu,
integer, dimension( * ) iblock,
integer, dimension( * ) indexw,
real, dimension( * ) work,
integer, dimension( * ) iwork,
integer info )

SLARRD computes the eigenvalues of a symmetric tridiagonal matrix to suitable accuracy.

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

Purpose:
!>
!> SLARRD computes the eigenvalues of a symmetric tridiagonal
!> matrix T to suitable accuracy. This is an auxiliary code to be
!> called from SSTEMR.
!> The user may ask for all eigenvalues, all eigenvalues
!> in the half-open interval (VL, VU], or the IL-th through IU-th
!> eigenvalues.
!>
!> To avoid overflow, the matrix must be scaled so that its
!> largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest
!> accuracy, it should not be much smaller than that.
!>
!> See W. Kahan , Report CS41, Computer Science Dept., Stanford
!> University, July 21, 1966.
!> 
Parameters
[in]RANGE
!>          RANGE is CHARACTER*1
!>          = 'A': ()   all eigenvalues will be found.
!>          = 'V': () all eigenvalues in the half-open interval
!>                           (VL, VU] will be found.
!>          = 'I': () the IL-th through IU-th eigenvalues (of the
!>                           entire matrix) will be found.
!> 
[in]ORDER
!>          ORDER is CHARACTER*1
!>          = 'B': () the eigenvalues will be grouped by
!>                              split-off block (see IBLOCK, ISPLIT) and
!>                              ordered from smallest to largest within
!>                              the block.
!>          = 'E': ()
!>                              the eigenvalues for the entire matrix
!>                              will be ordered from smallest to
!>                              largest.
!> 
[in]N
!>          N is INTEGER
!>          The order of the tridiagonal matrix T.  N >= 0.
!> 
[in]VL
!>          VL is REAL
!>          If RANGE='V', the lower bound of the interval to
!>          be searched for eigenvalues.  Eigenvalues less than or equal
!>          to VL, or greater than VU, will not be returned.  VL < VU.
!>          Not referenced if RANGE = 'A' or 'I'.
!> 
[in]VU
!>          VU is REAL
!>          If RANGE='V', the upper bound of the interval to
!>          be searched for eigenvalues.  Eigenvalues less than or equal
!>          to VL, or greater than VU, will not be returned.  VL < VU.
!>          Not referenced if RANGE = 'A' or 'I'.
!> 
[in]IL
!>          IL is INTEGER
!>          If RANGE='I', the index of the
!>          smallest eigenvalue to be returned.
!>          1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
!>          Not referenced if RANGE = 'A' or 'V'.
!> 
[in]IU
!>          IU is INTEGER
!>          If RANGE='I', the index of the
!>          largest eigenvalue to be returned.
!>          1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
!>          Not referenced if RANGE = 'A' or 'V'.
!> 
[in]GERS
!>          GERS is REAL array, dimension (2*N)
!>          The N Gerschgorin intervals (the i-th Gerschgorin interval
!>          is (GERS(2*i-1), GERS(2*i)).
!> 
[in]RELTOL
!>          RELTOL is REAL
!>          The minimum relative width of an interval.  When an interval
!>          is narrower than RELTOL times the larger (in
!>          magnitude) endpoint, then it is considered to be
!>          sufficiently small, i.e., converged.  Note: this should
!>          always be at least radix*machine epsilon.
!> 
[in]D
!>          D is REAL array, dimension (N)
!>          The n diagonal elements of the tridiagonal matrix T.
!> 
[in]E
!>          E is REAL array, dimension (N-1)
!>          The (n-1) off-diagonal elements of the tridiagonal matrix T.
!> 
[in]E2
!>          E2 is REAL array, dimension (N-1)
!>          The (n-1) squared off-diagonal elements of the tridiagonal matrix T.
!> 
[in]PIVMIN
!>          PIVMIN is REAL
!>          The minimum pivot allowed in the Sturm sequence for T.
!> 
[in]NSPLIT
!>          NSPLIT is INTEGER
!>          The number of diagonal blocks in the matrix T.
!>          1 <= NSPLIT <= N.
!> 
[in]ISPLIT
!>          ISPLIT is INTEGER array, dimension (N)
!>          The splitting points, at which T breaks up into submatrices.
!>          The first submatrix consists of rows/columns 1 to ISPLIT(1),
!>          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
!>          etc., and the NSPLIT-th consists of rows/columns
!>          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
!>          (Only the first NSPLIT elements will actually be used, but
!>          since the user cannot know a priori what value NSPLIT will
!>          have, N words must be reserved for ISPLIT.)
!> 
[out]M
!>          M is INTEGER
!>          The actual number of eigenvalues found. 0 <= M <= N.
!>          (See also the description of INFO=2,3.)
!> 
[out]W
!>          W is REAL array, dimension (N)
!>          On exit, the first M elements of W will contain the
!>          eigenvalue approximations. SLARRD computes an interval
!>          I_j = (a_j, b_j] that includes eigenvalue j. The eigenvalue
!>          approximation is given as the interval midpoint
!>          W(j)= ( a_j + b_j)/2. The corresponding error is bounded by
!>          WERR(j) = abs( a_j - b_j)/2
!> 
[out]WERR
!>          WERR is REAL array, dimension (N)
!>          The error bound on the corresponding eigenvalue approximation
!>          in W.
!> 
[out]WL
!>          WL is REAL
!> 
[out]WU
!>          WU is REAL
!>          The interval (WL, WU] contains all the wanted eigenvalues.
!>          If RANGE='V', then WL=VL and WU=VU.
!>          If RANGE='A', then WL and WU are the global Gerschgorin bounds
!>                        on the spectrum.
!>          If RANGE='I', then WL and WU are computed by SLAEBZ from the
!>                        index range specified.
!> 
[out]IBLOCK
!>          IBLOCK is INTEGER array, dimension (N)
!>          At each row/column j where E(j) is zero or small, the
!>          matrix T is considered to split into a block diagonal
!>          matrix.  On exit, if INFO = 0, IBLOCK(i) specifies to which
!>          block (from 1 to the number of blocks) the eigenvalue W(i)
!>          belongs.  (SLARRD may use the remaining N-M elements as
!>          workspace.)
!> 
[out]INDEXW
!>          INDEXW is INTEGER array, dimension (N)
!>          The indices of the eigenvalues within each block (submatrix);
!>          for example, INDEXW(i)= j and IBLOCK(i)=k imply that the
!>          i-th eigenvalue W(i) is the j-th eigenvalue in block k.
!> 
[out]WORK
!>          WORK is REAL array, dimension (4*N)
!> 
[out]IWORK
!>          IWORK is INTEGER array, dimension (3*N)
!> 
[out]INFO
!>          INFO is INTEGER
!>          = 0:  successful exit
!>          < 0:  if INFO = -i, the i-th argument had an illegal value
!>          > 0:  some or all of the eigenvalues failed to converge or
!>                were not computed:
!>                =1 or 3: Bisection failed to converge for some
!>                        eigenvalues; these eigenvalues are flagged by a
!>                        negative block number.  The effect is that the
!>                        eigenvalues may not be as accurate as the
!>                        absolute and relative tolerances.  This is
!>                        generally caused by unexpectedly inaccurate
!>                        arithmetic.
!>                =2 or 3: RANGE='I' only: Not all of the eigenvalues
!>                        IL:IU were found.
!>                        Effect: M < IU+1-IL
!>                        Cause:  non-monotonic arithmetic, causing the
!>                                Sturm sequence to be non-monotonic.
!>                        Cure:   recalculate, using RANGE='A', and pick
!>                                out eigenvalues IL:IU.  In some cases,
!>                                increasing the PARAMETER  may
!>                                make things work.
!>                = 4:    RANGE='I', and the Gershgorin interval
!>                        initially used was too small.  No eigenvalues
!>                        were computed.
!>                        Probable cause: your machine has sloppy
!>                                        floating-point arithmetic.
!>                        Cure: Increase the PARAMETER ,
!>                              recompile, and try again.
!> 
Internal Parameters:
!>  FUDGE   REAL, default = 2
!>          A  to widen the Gershgorin intervals.  Ideally,
!>          a value of 1 should work, but on machines with sloppy
!>          arithmetic, this needs to be larger.  The default for
!>          publicly released versions should be large enough to handle
!>          the worst machine around.  Note that this has no effect
!>          on accuracy of the solution.
!> 
Contributors:
W. Kahan, University of California, Berkeley, USA
Beresford Parlett, University of California, Berkeley, USA
Jim Demmel, University of California, Berkeley, USA
Inderjit Dhillon, University of Texas, Austin, USA
Osni Marques, LBNL/NERSC, USA
Christof Voemel, University of California, Berkeley, USA
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.

Definition at line 323 of file slarrd.f.

327*
328* -- LAPACK auxiliary routine --
329* -- LAPACK is a software package provided by Univ. of Tennessee, --
330* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
331*
332* .. Scalar Arguments ..
333 CHARACTER ORDER, RANGE
334 INTEGER IL, INFO, IU, M, N, NSPLIT
335 REAL PIVMIN, RELTOL, VL, VU, WL, WU
336* ..
337* .. Array Arguments ..
338 INTEGER IBLOCK( * ), INDEXW( * ),
339 $ ISPLIT( * ), IWORK( * )
340 REAL D( * ), E( * ), E2( * ),
341 $ GERS( * ), W( * ), WERR( * ), WORK( * )
342* ..
343*
344* =====================================================================
345*
346* .. Parameters ..
347 REAL ZERO, ONE, TWO, HALF, FUDGE
348 parameter( zero = 0.0e0, one = 1.0e0,
349 $ two = 2.0e0, half = one/two,
350 $ fudge = two )
351 INTEGER ALLRNG, VALRNG, INDRNG
352 parameter( allrng = 1, valrng = 2, indrng = 3 )
353* ..
354* .. Local Scalars ..
355 LOGICAL NCNVRG, TOOFEW
356 INTEGER I, IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
357 $ IM, IN, IOFF, IOUT, IRANGE, ITMAX, ITMP1,
358 $ ITMP2, IW, IWOFF, J, JBLK, JDISC, JE, JEE, NB,
359 $ NWL, NWU
360 REAL ATOLI, EPS, GL, GU, RTOLI, TMP1, TMP2,
361 $ TNORM, UFLOW, WKILL, WLU, WUL
362
363* ..
364* .. Local Arrays ..
365 INTEGER IDUMMA( 1 )
366* ..
367* .. External Functions ..
368 LOGICAL LSAME
369 INTEGER ILAENV
370 REAL SLAMCH
371 EXTERNAL lsame, ilaenv, slamch
372* ..
373* .. External Subroutines ..
374 EXTERNAL slaebz
375* ..
376* .. Intrinsic Functions ..
377 INTRINSIC abs, int, log, max, min
378* ..
379* .. Executable Statements ..
380*
381 info = 0
382 m = 0
383*
384* Quick return if possible
385*
386 IF( n.LE.0 ) THEN
387 RETURN
388 END IF
389*
390* Decode RANGE
391*
392 IF( lsame( range, 'A' ) ) THEN
393 irange = allrng
394 ELSE IF( lsame( range, 'V' ) ) THEN
395 irange = valrng
396 ELSE IF( lsame( range, 'I' ) ) THEN
397 irange = indrng
398 ELSE
399 irange = 0
400 END IF
401*
402* Check for Errors
403*
404 IF( irange.LE.0 ) THEN
405 info = -1
406 ELSE IF( .NOT.(lsame(order,'B').OR.lsame(order,'E')) ) THEN
407 info = -2
408 ELSE IF( n.LT.0 ) THEN
409 info = -3
410 ELSE IF( irange.EQ.valrng ) THEN
411 IF( vl.GE.vu )
412 $ info = -5
413 ELSE IF( irange.EQ.indrng .AND.
414 $ ( il.LT.1 .OR. il.GT.max( 1, n ) ) ) THEN
415 info = -6
416 ELSE IF( irange.EQ.indrng .AND.
417 $ ( iu.LT.min( n, il ) .OR. iu.GT.n ) ) THEN
418 info = -7
419 END IF
420*
421 IF( info.NE.0 ) THEN
422 RETURN
423 END IF
424
425* Initialize error flags
426 ncnvrg = .false.
427 toofew = .false.
428
429* Simplification:
430 IF( irange.EQ.indrng .AND. il.EQ.1 .AND. iu.EQ.n ) irange = 1
431
432* Get machine constants
433 eps = slamch( 'P' )
434 uflow = slamch( 'U' )
435
436
437* Special Case when N=1
438* Treat case of 1x1 matrix for quick return
439 IF( n.EQ.1 ) THEN
440 IF( (irange.EQ.allrng).OR.
441 $ ((irange.EQ.valrng).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
442 $ ((irange.EQ.indrng).AND.(il.EQ.1).AND.(iu.EQ.1)) ) THEN
443 m = 1
444 w(1) = d(1)
445* The computation error of the eigenvalue is zero
446 werr(1) = zero
447 iblock( 1 ) = 1
448 indexw( 1 ) = 1
449 ENDIF
450 RETURN
451 END IF
452
453* NB is the minimum vector length for vector bisection, or 0
454* if only scalar is to be done.
455 nb = ilaenv( 1, 'SSTEBZ', ' ', n, -1, -1, -1 )
456 IF( nb.LE.1 ) nb = 0
457
458* Find global spectral radius
459 gl = d(1)
460 gu = d(1)
461 DO 5 i = 1,n
462 gl = min( gl, gers( 2*i - 1))
463 gu = max( gu, gers(2*i) )
464 5 CONTINUE
465* Compute global Gerschgorin bounds and spectral diameter
466 tnorm = max( abs( gl ), abs( gu ) )
467 gl = gl - fudge*tnorm*eps*real( n ) - fudge*two*pivmin
468 gu = gu + fudge*tnorm*eps*real( n ) + fudge*two*pivmin
469* [JAN/28/2009] remove the line below since SPDIAM variable not use
470* SPDIAM = GU - GL
471* Input arguments for SLAEBZ:
472* The relative tolerance. An interval (a,b] lies within
473* "relative tolerance" if b-a < RELTOL*max(|a|,|b|),
474 rtoli = reltol
475* Set the absolute tolerance for interval convergence to zero to force
476* interval convergence based on relative size of the interval.
477* This is dangerous because intervals might not converge when RELTOL is
478* small. But at least a very small number should be selected so that for
479* strongly graded matrices, the code can get relatively accurate
480* eigenvalues.
481 atoli = fudge*two*uflow + fudge*two*pivmin
482
483 IF( irange.EQ.indrng ) THEN
484
485* RANGE='I': Compute an interval containing eigenvalues
486* IL through IU. The initial interval [GL,GU] from the global
487* Gerschgorin bounds GL and GU is refined by SLAEBZ.
488 itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /
489 $ log( two ) ) + 2
490 work( n+1 ) = gl
491 work( n+2 ) = gl
492 work( n+3 ) = gu
493 work( n+4 ) = gu
494 work( n+5 ) = gl
495 work( n+6 ) = gu
496 iwork( 1 ) = -1
497 iwork( 2 ) = -1
498 iwork( 3 ) = n + 1
499 iwork( 4 ) = n + 1
500 iwork( 5 ) = il - 1
501 iwork( 6 ) = iu
502*
503 CALL slaebz( 3, itmax, n, 2, 2, nb, atoli, rtoli, pivmin,
504 $ d, e, e2, iwork( 5 ), work( n+1 ), work( n+5 ), iout,
505 $ iwork, w, iblock, iinfo )
506 IF( iinfo .NE. 0 ) THEN
507 info = iinfo
508 RETURN
509 END IF
510* On exit, output intervals may not be ordered by ascending negcount
511 IF( iwork( 6 ).EQ.iu ) THEN
512 wl = work( n+1 )
513 wlu = work( n+3 )
514 nwl = iwork( 1 )
515 wu = work( n+4 )
516 wul = work( n+2 )
517 nwu = iwork( 4 )
518 ELSE
519 wl = work( n+2 )
520 wlu = work( n+4 )
521 nwl = iwork( 2 )
522 wu = work( n+3 )
523 wul = work( n+1 )
524 nwu = iwork( 3 )
525 END IF
526* On exit, the interval [WL, WLU] contains a value with negcount NWL,
527* and [WUL, WU] contains a value with negcount NWU.
528 IF( nwl.LT.0 .OR. nwl.GE.n .OR. nwu.LT.1 .OR. nwu.GT.n ) THEN
529 info = 4
530 RETURN
531 END IF
532
533 ELSEIF( irange.EQ.valrng ) THEN
534 wl = vl
535 wu = vu
536
537 ELSEIF( irange.EQ.allrng ) THEN
538 wl = gl
539 wu = gu
540 ENDIF
541
542
543
544* Find Eigenvalues -- Loop Over blocks and recompute NWL and NWU.
545* NWL accumulates the number of eigenvalues .le. WL,
546* NWU accumulates the number of eigenvalues .le. WU
547 m = 0
548 iend = 0
549 info = 0
550 nwl = 0
551 nwu = 0
552*
553 DO 70 jblk = 1, nsplit
554 ioff = iend
555 ibegin = ioff + 1
556 iend = isplit( jblk )
557 in = iend - ioff
558*
559 IF( in.EQ.1 ) THEN
560* 1x1 block
561 IF( wl.GE.d( ibegin )-pivmin )
562 $ nwl = nwl + 1
563 IF( wu.GE.d( ibegin )-pivmin )
564 $ nwu = nwu + 1
565 IF( irange.EQ.allrng .OR.
566 $ ( wl.LT.d( ibegin )-pivmin
567 $ .AND. wu.GE. d( ibegin )-pivmin ) ) THEN
568 m = m + 1
569 w( m ) = d( ibegin )
570 werr(m) = zero
571* The gap for a single block doesn't matter for the later
572* algorithm and is assigned an arbitrary large value
573 iblock( m ) = jblk
574 indexw( m ) = 1
575 END IF
576
577* Disabled 2x2 case because of a failure on the following matrix
578* RANGE = 'I', IL = IU = 4
579* Original Tridiagonal, d = [
580* -0.150102010615740E+00
581* -0.849897989384260E+00
582* -0.128208148052635E-15
583* 0.128257718286320E-15
584* ];
585* e = [
586* -0.357171383266986E+00
587* -0.180411241501588E-15
588* -0.175152352710251E-15
589* ];
590*
591* ELSE IF( IN.EQ.2 ) THEN
592** 2x2 block
593* DISC = SQRT( (HALF*(D(IBEGIN)-D(IEND)))**2 + E(IBEGIN)**2 )
594* TMP1 = HALF*(D(IBEGIN)+D(IEND))
595* L1 = TMP1 - DISC
596* IF( WL.GE. L1-PIVMIN )
597* $ NWL = NWL + 1
598* IF( WU.GE. L1-PIVMIN )
599* $ NWU = NWU + 1
600* IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L1-PIVMIN .AND. WU.GE.
601* $ L1-PIVMIN ) ) THEN
602* M = M + 1
603* W( M ) = L1
604** The uncertainty of eigenvalues of a 2x2 matrix is very small
605* WERR( M ) = EPS * ABS( W( M ) ) * TWO
606* IBLOCK( M ) = JBLK
607* INDEXW( M ) = 1
608* ENDIF
609* L2 = TMP1 + DISC
610* IF( WL.GE. L2-PIVMIN )
611* $ NWL = NWL + 1
612* IF( WU.GE. L2-PIVMIN )
613* $ NWU = NWU + 1
614* IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L2-PIVMIN .AND. WU.GE.
615* $ L2-PIVMIN ) ) THEN
616* M = M + 1
617* W( M ) = L2
618** The uncertainty of eigenvalues of a 2x2 matrix is very small
619* WERR( M ) = EPS * ABS( W( M ) ) * TWO
620* IBLOCK( M ) = JBLK
621* INDEXW( M ) = 2
622* ENDIF
623 ELSE
624* General Case - block of size IN >= 2
625* Compute local Gerschgorin interval and use it as the initial
626* interval for SLAEBZ
627 gu = d( ibegin )
628 gl = d( ibegin )
629 tmp1 = zero
630
631 DO 40 j = ibegin, iend
632 gl = min( gl, gers( 2*j - 1))
633 gu = max( gu, gers(2*j) )
634 40 CONTINUE
635* [JAN/28/2009]
636* change SPDIAM by TNORM in lines 2 and 3 thereafter
637* line 1: remove computation of SPDIAM (not useful anymore)
638* SPDIAM = GU - GL
639* GL = GL - FUDGE*SPDIAM*EPS*IN - FUDGE*PIVMIN
640* GU = GU + FUDGE*SPDIAM*EPS*IN + FUDGE*PIVMIN
641 gl = gl - fudge*tnorm*eps*real( in ) - fudge*pivmin
642 gu = gu + fudge*tnorm*eps*real( in ) + fudge*pivmin
643*
644 IF( irange.GT.1 ) THEN
645 IF( gu.LT.wl ) THEN
646* the local block contains none of the wanted eigenvalues
647 nwl = nwl + in
648 nwu = nwu + in
649 GO TO 70
650 END IF
651* refine search interval if possible, only range (WL,WU] matters
652 gl = max( gl, wl )
653 gu = min( gu, wu )
654 IF( gl.GE.gu )
655 $ GO TO 70
656 END IF
657
658* Find negcount of initial interval boundaries GL and GU
659 work( n+1 ) = gl
660 work( n+in+1 ) = gu
661 CALL slaebz( 1, 0, in, in, 1, nb, atoli, rtoli, pivmin,
662 $ d( ibegin ), e( ibegin ), e2( ibegin ),
663 $ idumma, work( n+1 ), work( n+2*in+1 ), im,
664 $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
665 IF( iinfo .NE. 0 ) THEN
666 info = iinfo
667 RETURN
668 END IF
669*
670 nwl = nwl + iwork( 1 )
671 nwu = nwu + iwork( in+1 )
672 iwoff = m - iwork( 1 )
673
674* Compute Eigenvalues
675 itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /
676 $ log( two ) ) + 2
677 CALL slaebz( 2, itmax, in, in, 1, nb, atoli, rtoli,
678 $ pivmin,
679 $ d( ibegin ), e( ibegin ), e2( ibegin ),
680 $ idumma, work( n+1 ), work( n+2*in+1 ), iout,
681 $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
682 IF( iinfo .NE. 0 ) THEN
683 info = iinfo
684 RETURN
685 END IF
686*
687* Copy eigenvalues into W and IBLOCK
688* Use -JBLK for block number for unconverged eigenvalues.
689* Loop over the number of output intervals from SLAEBZ
690 DO 60 j = 1, iout
691* eigenvalue approximation is middle point of interval
692 tmp1 = half*( work( j+n )+work( j+in+n ) )
693* semi length of error interval
694 tmp2 = half*abs( work( j+n )-work( j+in+n ) )
695 IF( j.GT.iout-iinfo ) THEN
696* Flag non-convergence.
697 ncnvrg = .true.
698 ib = -jblk
699 ELSE
700 ib = jblk
701 END IF
702 DO 50 je = iwork( j ) + 1 + iwoff,
703 $ iwork( j+in ) + iwoff
704 w( je ) = tmp1
705 werr( je ) = tmp2
706 indexw( je ) = je - iwoff
707 iblock( je ) = ib
708 50 CONTINUE
709 60 CONTINUE
710*
711 m = m + im
712 END IF
713 70 CONTINUE
714
715* If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
716* If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
717 IF( irange.EQ.indrng ) THEN
718 idiscl = il - 1 - nwl
719 idiscu = nwu - iu
720*
721 IF( idiscl.GT.0 ) THEN
722 im = 0
723 DO 80 je = 1, m
724* Remove some of the smallest eigenvalues from the left so that
725* at the end IDISCL =0. Move all eigenvalues up to the left.
726 IF( w( je ).LE.wlu .AND. idiscl.GT.0 ) THEN
727 idiscl = idiscl - 1
728 ELSE
729 im = im + 1
730 w( im ) = w( je )
731 werr( im ) = werr( je )
732 indexw( im ) = indexw( je )
733 iblock( im ) = iblock( je )
734 END IF
735 80 CONTINUE
736 m = im
737 END IF
738 IF( idiscu.GT.0 ) THEN
739* Remove some of the largest eigenvalues from the right so that
740* at the end IDISCU =0. Move all eigenvalues up to the left.
741 im=m+1
742 DO 81 je = m, 1, -1
743 IF( w( je ).GE.wul .AND. idiscu.GT.0 ) THEN
744 idiscu = idiscu - 1
745 ELSE
746 im = im - 1
747 w( im ) = w( je )
748 werr( im ) = werr( je )
749 indexw( im ) = indexw( je )
750 iblock( im ) = iblock( je )
751 END IF
752 81 CONTINUE
753 jee = 0
754 DO 82 je = im, m
755 jee = jee + 1
756 w( jee ) = w( je )
757 werr( jee ) = werr( je )
758 indexw( jee ) = indexw( je )
759 iblock( jee ) = iblock( je )
760 82 CONTINUE
761 m = m-im+1
762 END IF
763
764 IF( idiscl.GT.0 .OR. idiscu.GT.0 ) THEN
765* Code to deal with effects of bad arithmetic. (If N(w) is
766* monotone non-decreasing, this should never happen.)
767* Some low eigenvalues to be discarded are not in (WL,WLU],
768* or high eigenvalues to be discarded are not in (WUL,WU]
769* so just kill off the smallest IDISCL/largest IDISCU
770* eigenvalues, by marking the corresponding IBLOCK = 0
771 IF( idiscl.GT.0 ) THEN
772 wkill = wu
773 DO 100 jdisc = 1, idiscl
774 iw = 0
775 DO 90 je = 1, m
776 IF( iblock( je ).NE.0 .AND.
777 $ ( w( je ).LT.wkill .OR. iw.EQ.0 ) ) THEN
778 iw = je
779 wkill = w( je )
780 END IF
781 90 CONTINUE
782 iblock( iw ) = 0
783 100 CONTINUE
784 END IF
785 IF( idiscu.GT.0 ) THEN
786 wkill = wl
787 DO 120 jdisc = 1, idiscu
788 iw = 0
789 DO 110 je = 1, m
790 IF( iblock( je ).NE.0 .AND.
791 $ ( w( je ).GE.wkill .OR. iw.EQ.0 ) ) THEN
792 iw = je
793 wkill = w( je )
794 END IF
795 110 CONTINUE
796 iblock( iw ) = 0
797 120 CONTINUE
798 END IF
799* Now erase all eigenvalues with IBLOCK set to zero
800 im = 0
801 DO 130 je = 1, m
802 IF( iblock( je ).NE.0 ) THEN
803 im = im + 1
804 w( im ) = w( je )
805 werr( im ) = werr( je )
806 indexw( im ) = indexw( je )
807 iblock( im ) = iblock( je )
808 END IF
809 130 CONTINUE
810 m = im
811 END IF
812 IF( idiscl.LT.0 .OR. idiscu.LT.0 ) THEN
813 toofew = .true.
814 END IF
815 END IF
816*
817 IF(( irange.EQ.allrng .AND. m.NE.n ).OR.
818 $ ( irange.EQ.indrng .AND. m.NE.iu-il+1 ) ) THEN
819 toofew = .true.
820 END IF
821
822* If ORDER='B', do nothing the eigenvalues are already sorted by
823* block.
824* If ORDER='E', sort the eigenvalues from smallest to largest
825
826 IF( lsame(order,'E') .AND. nsplit.GT.1 ) THEN
827 DO 150 je = 1, m - 1
828 ie = 0
829 tmp1 = w( je )
830 DO 140 j = je + 1, m
831 IF( w( j ).LT.tmp1 ) THEN
832 ie = j
833 tmp1 = w( j )
834 END IF
835 140 CONTINUE
836 IF( ie.NE.0 ) THEN
837 tmp2 = werr( ie )
838 itmp1 = iblock( ie )
839 itmp2 = indexw( ie )
840 w( ie ) = w( je )
841 werr( ie ) = werr( je )
842 iblock( ie ) = iblock( je )
843 indexw( ie ) = indexw( je )
844 w( je ) = tmp1
845 werr( je ) = tmp2
846 iblock( je ) = itmp1
847 indexw( je ) = itmp2
848 END IF
849 150 CONTINUE
850 END IF
851*
852 info = 0
853 IF( ncnvrg )
854 $ info = info + 1
855 IF( toofew )
856 $ info = info + 2
857 RETURN
858*
859* End of SLARRD
860*
integer function ilaenv(ispec, name, opts, n1, n2, n3, n4)
ILAENV
Definition ilaenv.f:160
subroutine slaebz(ijob, nitmax, n, mmax, minp, nbmin, abstol, reltol, pivmin, d, e, e2, nval, ab, c, mout, nab, work, iwork, info)
SLAEBZ computes the number of eigenvalues of a real symmetric tridiagonal matrix which are less than ...
Definition slaebz.f:317
real function slamch(cmach)
SLAMCH
Definition slamch.f:68
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
Here is the call graph for this function:
Here is the caller graph for this function: