303 SUBROUTINE dlarre( RANGE, N, VL, VU, IL, IU, D, E, E2,
304 $ RTOL1, RTOL2, SPLTOL, NSPLIT, ISPLIT, M,
305 $ W, WERR, WGAP, IBLOCK, INDEXW, GERS, PIVMIN,
306 $ WORK, IWORK, INFO )
315 INTEGER IL, INFO, IU, M, N, NSPLIT
316 DOUBLE PRECISION PIVMIN, RTOL1, RTOL2, SPLTOL, VL, VU
319 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * ),
321 DOUBLE PRECISION D( * ), E( * ), E2( * ), GERS( * ),
322 $ w( * ),werr( * ), wgap( * ), work( * )
328 DOUBLE PRECISION FAC, FOUR, FOURTH, FUDGE, HALF, HNDRD,
329 $ maxgrowth, one, pert, two, zero
330 parameter( zero = 0.0d0, one = 1.0d0,
331 $ two = 2.0d0, four=4.0d0,
334 $ half = one/two, fourth = one/four, fac= half,
335 $ maxgrowth = 64.0d0, fudge = 2.0d0 )
336 INTEGER MAXTRY, ALLRNG, INDRNG, VALRNG
337 parameter( maxtry = 6, allrng = 1, indrng = 2,
341 LOGICAL FORCEB, NOREP, USEDQD
342 INTEGER CNT, CNT1, CNT2, I, IBEGIN, IDUM, IEND, IINFO,
343 $ in, indl, indu, irange, j, jblk, mb, mm,
345 DOUBLE PRECISION AVGAP, BSRTOL, CLWDTH, DMAX, DPIVOT, EABS,
346 $ emax, eold, eps, gl, gu, isleft, isrght, rtl,
347 $ rtol, s1, s2, safmin, sgndef, sigma, spdiam,
357 DOUBLE PRECISION DLAMCH
358 EXTERNAL dlamch, lsame
366 INTRINSIC abs, max, min
382 IF( lsame( range,
'A' ) )
THEN 384 ELSE IF( lsame( range,
'V' ) )
THEN 386 ELSE IF( lsame( range,
'I' ) )
THEN 393 safmin = dlamch(
'S' )
402 IF( (irange.EQ.allrng).OR.
403 $ ((irange.EQ.valrng).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
404 $ ((irange.EQ.indrng).AND.(il.EQ.1).AND.(iu.EQ.1)) )
THEN 433 IF( eabs .GE. emax )
THEN 437 gers( 2*i-1) = d(i) - tmp1
438 gl = min( gl, gers( 2*i - 1))
439 gers( 2*i ) = d(i) + tmp1
440 gu = max( gu, gers(2*i) )
444 pivmin = safmin * max( one, emax**2 )
450 CALL dlarra( n, d, e, e2, spltol, spdiam,
451 $ nsplit, isplit, iinfo )
459 usedqd = (( irange.EQ.allrng ) .AND. (.NOT.forceb))
461 IF( (irange.EQ.allrng) .AND. (.NOT. forceb) )
THEN 472 CALL dlarrd( range,
'B', n, vl, vu, il, iu, gers,
473 $ bsrtol, d, e, e2, pivmin, nsplit, isplit,
474 $ mm, w, werr, vl, vu, iblock, indexw,
475 $ work, iwork, iinfo )
476 IF( iinfo.NE.0 )
THEN 494 DO 170 jblk = 1, nsplit
495 iend = isplit( jblk )
496 in = iend - ibegin + 1
500 IF( (irange.EQ.allrng).OR.( (irange.EQ.valrng).AND.
501 $ ( d( ibegin ).GT.vl ).AND.( d( ibegin ).LE.vu ) )
502 $ .OR. ( (irange.EQ.indrng).AND.(iblock(wbegin).EQ.jblk))
528 DO 15 i = ibegin , iend
529 gl = min( gers( 2*i-1 ), gl )
530 gu = max( gers( 2*i ), gu )
534 IF(.NOT. ((irange.EQ.allrng).AND.(.NOT.forceb)) )
THEN 538 IF( iblock(i).EQ.jblk )
THEN 555 usedqd = ( (mb .GT. fac*in) .AND. (.NOT.forceb) )
556 wend = wbegin + mb - 1
561 DO 30 i = wbegin, wend - 1
562 wgap( i ) = max( zero,
563 $ w(i+1)-werr(i+1) - (w(i)+werr(i)) )
565 wgap( wend ) = max( zero,
566 $ vu - sigma - (w( wend )+werr( wend )))
568 indl = indexw(wbegin)
569 indu = indexw( wend )
572 IF(( (irange.EQ.allrng) .AND. (.NOT. forceb) ).OR.usedqd)
THEN 575 CALL dlarrk( in, 1, gl, gu, d(ibegin),
576 $ e2(ibegin), pivmin, rtl, tmp, tmp1, iinfo )
577 IF( iinfo.NE.0 )
THEN 581 isleft = max(gl, tmp - tmp1
582 $ - hndrd * eps* abs(tmp - tmp1))
584 CALL dlarrk( in, in, gl, gu, d(ibegin),
585 $ e2(ibegin), pivmin, rtl, tmp, tmp1, iinfo )
586 IF( iinfo.NE.0 )
THEN 590 isrght = min(gu, tmp + tmp1
591 $ + hndrd * eps * abs(tmp + tmp1))
593 spdiam = isrght - isleft
597 isleft = max(gl, w(wbegin) - werr(wbegin)
598 $ - hndrd * eps*abs(w(wbegin)- werr(wbegin) ))
599 isrght = min(gu,w(wend) + werr(wend)
600 $ + hndrd * eps * abs(w(wend)+ werr(wend)))
612 IF( ( irange.EQ.allrng ) .AND. (.NOT.forceb) )
THEN 620 wend = wbegin + mb - 1
622 s1 = isleft + fourth * spdiam
623 s2 = isrght - fourth * spdiam
629 s1 = isleft + fourth * spdiam
630 s2 = isrght - fourth * spdiam
632 tmp = min(isrght,vu) - max(isleft,vl)
633 s1 = max(isleft,vl) + fourth * tmp
634 s2 = min(isrght,vu) - fourth * tmp
640 CALL dlarrc(
'T', in, s1, s2, d(ibegin),
641 $ e(ibegin), pivmin, cnt, cnt1, cnt2, iinfo)
647 ELSEIF( cnt1 - indl .GE. indu - cnt2 )
THEN 648 IF( ( irange.EQ.allrng ) .AND. (.NOT.forceb) )
THEN 649 sigma = max(isleft,gl)
650 ELSEIF( usedqd )
THEN 657 sigma = max(isleft,vl)
661 IF( ( irange.EQ.allrng ) .AND. (.NOT.forceb) )
THEN 662 sigma = min(isrght,gu)
663 ELSEIF( usedqd )
THEN 670 sigma = min(isrght,vu)
684 tau = spdiam*eps*n + two*pivmin
685 tau = max( tau,two*eps*abs(sigma) )
688 clwdth = w(wend) + werr(wend) - w(wbegin) - werr(wbegin)
689 avgap = abs(clwdth / dble(wend-wbegin))
690 IF( sgndef.EQ.one )
THEN 691 tau = half*max(wgap(wbegin),avgap)
692 tau = max(tau,werr(wbegin))
694 tau = half*max(wgap(wend-1),avgap)
695 tau = max(tau,werr(wend))
702 DO 80 idum = 1, maxtry
706 dpivot = d( ibegin ) - sigma
708 dmax = abs( work(1) )
711 work( 2*in+i ) = one / work( i )
712 tmp = e( j )*work( 2*in+i )
714 dpivot = ( d( j+1 )-sigma ) - tmp*e( j )
716 dmax = max( dmax, abs(dpivot) )
720 IF( dmax .GT. maxgrowth*spdiam )
THEN 725 IF( usedqd .AND. .NOT.norep )
THEN 729 tmp = sgndef*work( i )
730 IF( tmp.LT.zero ) norep = .true.
737 IF( idum.EQ.maxtry-1 )
THEN 738 IF( sgndef.EQ.one )
THEN 741 $ gl - fudge*spdiam*eps*n - fudge*two*pivmin
744 $ gu + fudge*spdiam*eps*n + fudge*two*pivmin
747 sigma = sigma - sgndef * tau
766 CALL dcopy( in, work, 1, d( ibegin ), 1 )
767 CALL dcopy( in-1, work( in+1 ), 1, e( ibegin ), 1 )
780 CALL dlarnv(2, iseed, 2*in-1, work(1))
782 d(ibegin+i-1) = d(ibegin+i-1)*(one+eps*pert*work(i))
783 e(ibegin+i-1) = e(ibegin+i-1)*(one+eps*pert*work(in+i))
785 d(iend) = d(iend)*(one+eps*four*work(in))
795 IF ( .NOT.usedqd )
THEN 803 werr(j) = werr(j) + abs(w(j)) * eps
807 DO 135 i = ibegin, iend-1
808 work( i ) = d( i ) * e( i )**2
811 CALL dlarrb(in, d(ibegin), work(ibegin),
812 $ indl, indu, rtol1, rtol2, indl-1,
813 $ w(wbegin), wgap(wbegin), werr(wbegin),
814 $ work( 2*n+1 ), iwork, pivmin, spdiam,
816 IF( iinfo .NE. 0 )
THEN 822 wgap( wend ) = max( zero,
823 $ ( vu-sigma ) - ( w( wend ) + werr( wend ) ) )
824 DO 138 i = indl, indu
841 rtol = log(dble(in)) * four * eps
844 work( 2*i-1 ) = abs( d( j ) )
845 work( 2*i ) = e( j )*e( j )*work( 2*i-1 )
848 work( 2*in-1 ) = abs( d( iend ) )
850 CALL dlasq2( in, work, iinfo )
851 IF( iinfo .NE. 0 )
THEN 860 IF( work( i ).LT.zero )
THEN 866 IF( sgndef.GT.zero )
THEN 867 DO 150 i = indl, indu
869 w( m ) = work( in-i+1 )
874 DO 160 i = indl, indu
882 DO 165 i = m - mb + 1, m
884 werr( i ) = rtol * abs( w(i) )
886 DO 166 i = m - mb + 1, m - 1
888 wgap( i ) = max( zero,
889 $ w(i+1)-werr(i+1) - (w(i)+werr(i)) )
891 wgap( m ) = max( zero,
892 $ ( vu-sigma ) - ( w( m ) + werr( m ) ) )
subroutine dcopy(N, DX, INCX, DY, INCY)
DCOPY
subroutine dlarrk(N, IW, GL, GU, D, E2, PIVMIN, RELTOL, W, WERR, INFO)
DLARRK computes one eigenvalue of a symmetric tridiagonal matrix T to suitable accuracy.
subroutine dlarrc(JOBT, N, VL, VU, D, E, PIVMIN, EIGCNT, LCNT, RCNT, INFO)
DLARRC computes the number of eigenvalues of the symmetric tridiagonal matrix.
subroutine dlarnv(IDIST, ISEED, N, X)
DLARNV returns a vector of random numbers from a uniform or normal distribution.
subroutine dlarra(N, D, E, E2, SPLTOL, TNRM, NSPLIT, ISPLIT, INFO)
DLARRA computes the splitting points with the specified threshold.
subroutine dlarre(RANGE, N, VL, VU, IL, IU, D, E, E2, RTOL1, RTOL2, SPLTOL, NSPLIT, ISPLIT, M, W, WERR, WGAP, IBLOCK, INDEXW, GERS, PIVMIN, WORK, IWORK, INFO)
DLARRE given the tridiagonal matrix T, sets small off-diagonal elements to zero and for each unreduce...
subroutine dlasq2(N, Z, INFO)
DLASQ2 computes all the eigenvalues of the symmetric positive definite tridiagonal matrix associated ...
subroutine dlarrd(RANGE, ORDER, N, VL, VU, IL, IU, GERS, RELTOL, D, E, E2, PIVMIN, NSPLIT, ISPLIT, M, W, WERR, WL, WU, IBLOCK, INDEXW, WORK, IWORK, INFO)
DLARRD computes the eigenvalues of a symmetric tridiagonal matrix to suitable accuracy.
subroutine dlarrb(N, D, LLD, IFIRST, ILAST, RTOL1, RTOL2, OFFSET, W, WGAP, WERR, WORK, IWORK, PIVMIN, SPDIAM, TWIST, INFO)
DLARRB provides limited bisection to locate eigenvalues for more accuracy.