home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
eispack-1.0-src.tgz
/
tar.out
/
contrib
/
eispack
/
tridib.f
< prev
next >
Wrap
Text File
|
1996-09-28
|
8KB
|
269 lines
subroutine tridib(n,eps1,d,e,e2,lb,ub,m11,m,w,ind,ierr,rv4,rv5)
c
integer i,j,k,l,m,n,p,q,r,s,ii,m1,m2,m11,m22,tag,ierr,isturm
double precision d(n),e(n),e2(n),w(m),rv4(n),rv5(n)
double precision u,v,lb,t1,t2,ub,xu,x0,x1,eps1,tst1,tst2,epslon
integer ind(m)
c
c this subroutine is a translation of the algol procedure bisect,
c num. math. 9, 386-393(1967) by barth, martin, and wilkinson.
c handbook for auto. comp., vol.ii-linear algebra, 249-256(1971).
c
c this subroutine finds those eigenvalues of a tridiagonal
c symmetric matrix between specified boundary indices,
c using bisection.
c
c on input
c
c n is the order of the matrix.
c
c eps1 is an absolute error tolerance for the computed
c eigenvalues. if the input eps1 is non-positive,
c it is reset for each submatrix to a default value,
c namely, minus the product of the relative machine
c precision and the 1-norm of the submatrix.
c
c d contains the diagonal elements of the input matrix.
c
c e contains the subdiagonal elements of the input matrix
c in its last n-1 positions. e(1) is arbitrary.
c
c e2 contains the squares of the corresponding elements of e.
c e2(1) is arbitrary.
c
c m11 specifies the lower boundary index for the desired
c eigenvalues.
c
c m specifies the number of eigenvalues desired. the upper
c boundary index m22 is then obtained as m22=m11+m-1.
c
c on output
c
c eps1 is unaltered unless it has been reset to its
c (last) default value.
c
c d and e are unaltered.
c
c elements of e2, corresponding to elements of e regarded
c as negligible, have been replaced by zero causing the
c matrix to split into a direct sum of submatrices.
c e2(1) is also set to zero.
c
c lb and ub define an interval containing exactly the desired
c eigenvalues.
c
c w contains, in its first m positions, the eigenvalues
c between indices m11 and m22 in ascending order.
c
c ind contains in its first m positions the submatrix indices
c associated with the corresponding eigenvalues in w --
c 1 for eigenvalues belonging to the first submatrix from
c the top, 2 for those belonging to the second submatrix, etc..
c
c ierr is set to
c zero for normal return,
c 3*n+1 if multiple eigenvalues at index m11 make
c unique selection impossible,
c 3*n+2 if multiple eigenvalues at index m22 make
c unique selection impossible.
c
c rv4 and rv5 are temporary storage arrays.
c
c note that subroutine tql1, imtql1, or tqlrat is generally faster
c than tridib, if more than n/4 eigenvalues are to be found.
c
c questions and comments should be directed to burton s. garbow,
c mathematics and computer science div, argonne national laboratory
c
c this version dated august 1983.
c
c ------------------------------------------------------------------
c
ierr = 0
tag = 0
xu = d(1)
x0 = d(1)
u = 0.0d0
c .......... look for small sub-diagonal entries and determine an
c interval containing all the eigenvalues ..........
do 40 i = 1, n
x1 = u
u = 0.0d0
if (i .ne. n) u = dabs(e(i+1))
xu = dmin1(d(i)-(x1+u),xu)
x0 = dmax1(d(i)+(x1+u),x0)
if (i .eq. 1) go to 20
tst1 = dabs(d(i)) + dabs(d(i-1))
tst2 = tst1 + dabs(e(i))
if (tst2 .gt. tst1) go to 40
20 e2(i) = 0.0d0
40 continue
c
x1 = n
x1 = x1 * epslon(dmax1(dabs(xu),dabs(x0)))
xu = xu - x1
t1 = xu
x0 = x0 + x1
t2 = x0
c .......... determine an interval containing exactly
c the desired eigenvalues ..........
p = 1
q = n
m1 = m11 - 1
if (m1 .eq. 0) go to 75
isturm = 1
50 v = x1
x1 = xu + (x0 - xu) * 0.5d0
if (x1 .eq. v) go to 980
go to 320
60 if (s - m1) 65, 73, 70
65 xu = x1
go to 50
70 x0 = x1
go to 50
73 xu = x1
t1 = x1
75 m22 = m1 + m
if (m22 .eq. n) go to 90
x0 = t2
isturm = 2
go to 50
80 if (s - m22) 65, 85, 70
85 t2 = x1
90 q = 0
r = 0
c .......... establish and process next submatrix, refining
c interval by the gerschgorin bounds ..........
100 if (r .eq. m) go to 1001
tag = tag + 1
p = q + 1
xu = d(p)
x0 = d(p)
u = 0.0d0
c
do 120 q = p, n
x1 = u
u = 0.0d0
v = 0.0d0
if (q .eq. n) go to 110
u = dabs(e(q+1))
v = e2(q+1)
110 xu = dmin1(d(q)-(x1+u),xu)
x0 = dmax1(d(q)+(x1+u),x0)
if (v .eq. 0.0d0) go to 140
120 continue
c
140 x1 = epslon(dmax1(dabs(xu),dabs(x0)))
if (eps1 .le. 0.0d0) eps1 = -x1
if (p .ne. q) go to 180
c .......... check for isolated root within interval ..........
if (t1 .gt. d(p) .or. d(p) .ge. t2) go to 940
m1 = p
m2 = p
rv5(p) = d(p)
go to 900
180 x1 = x1 * (q - p + 1)
lb = dmax1(t1,xu-x1)
ub = dmin1(t2,x0+x1)
x1 = lb
isturm = 3
go to 320
200 m1 = s + 1
x1 = ub
isturm = 4
go to 320
220 m2 = s
if (m1 .gt. m2) go to 940
c .......... find roots by bisection ..........
x0 = ub
isturm = 5
c
do 240 i = m1, m2
rv5(i) = ub
rv4(i) = lb
240 continue
c .......... loop for k-th eigenvalue
c for k=m2 step -1 until m1 do --
c (-do- not used to legalize -computed go to-) ..........
k = m2
250 xu = lb
c .......... for i=k step -1 until m1 do -- ..........
do 260 ii = m1, k
i = m1 + k - ii
if (xu .ge. rv4(i)) go to 260
xu = rv4(i)
go to 280
260 continue
c
280 if (x0 .gt. rv5(k)) x0 = rv5(k)
c .......... next bisection step ..........
300 x1 = (xu + x0) * 0.5d0
if ((x0 - xu) .le. dabs(eps1)) go to 420
tst1 = 2.0d0 * (dabs(xu) + dabs(x0))
tst2 = tst1 + (x0 - xu)
if (tst2 .eq. tst1) go to 420
c .......... in-line procedure for sturm sequence ..........
320 s = p - 1
u = 1.0d0
c
do 340 i = p, q
if (u .ne. 0.0d0) go to 325
v = dabs(e(i)) / epslon(1.0d0)
if (e2(i) .eq. 0.0d0) v = 0.0d0
go to 330
325 v = e2(i) / u
330 u = d(i) - x1 - v
if (u .lt. 0.0d0) s = s + 1
340 continue
c
go to (60,80,200,220,360), isturm
c .......... refine intervals ..........
360 if (s .ge. k) go to 400
xu = x1
if (s .ge. m1) go to 380
rv4(m1) = x1
go to 300
380 rv4(s+1) = x1
if (rv5(s) .gt. x1) rv5(s) = x1
go to 300
400 x0 = x1
go to 300
c .......... k-th eigenvalue found ..........
420 rv5(k) = x1
k = k - 1
if (k .ge. m1) go to 250
c .......... order eigenvalues tagged with their
c submatrix associations ..........
900 s = r
r = r + m2 - m1 + 1
j = 1
k = m1
c
do 920 l = 1, r
if (j .gt. s) go to 910
if (k .gt. m2) go to 940
if (rv5(k) .ge. w(l)) go to 915
c
do 905 ii = j, s
i = l + s - ii
w(i+1) = w(i)
ind(i+1) = ind(i)
905 continue
c
910 w(l) = rv5(k)
ind(l) = tag
k = k + 1
go to 920
915 j = j + 1
920 continue
c
940 if (q .lt. n) go to 100
go to 1001
c .......... set error -- interval cannot be found containing
c exactly the desired eigenvalues ..........
980 ierr = 3 * n + isturm
1001 lb = t1
ub = t2
return
end