# Eigenvalues of a tridiagonal matrix

1. Dec 28, 2007

### petr1243

Could some one please explain the logic behind the subroutine tqli(d,e,z) found on pg.1228 of numerical recipes in fortran. For this subroutine, d and e are one dimensional arrays and z is an optional multi-dimensional array(only used if also seeking for eigenvectors of matrix). The 3 modules, and the whole jacobi rotation technique has me confused. Thank you very much.

2. Dec 28, 2007

### mda

It looks like you're looking at the F90 version...
Have you looked at the online F77 version that provides some explanation?

3. Dec 28, 2007

### petr1243

Are you referring to the explanation from indiana university? If it isn't, then could you please send me the link.

4. Dec 29, 2007

### Maxwell

Can you post the contents of the subroutine?

I've actually worked on this problem before - in C, however - but maybe I can help provide some input.

5. Dec 29, 2007

### petr1243

I'm actually working on a tridiagonal matrix in which the diagonal term is some forumla in terms of integer n, and the super and sub diagonal terms are equivalent to one another(constant, independent of n). I would like to implement this subroutine into my program. I would prefer an explanation in f90, but if you can explain it in f77 then thats fine. Here is the f77 program: http://www.physics.louisville.edu/help/nr/bookfpdf/f11-3.pdf [Broken] (on pg.474)

I am not too skilled in f77, so could you please be explicit in your explanation. Thank you for your time.
Here is the subroutine in f90, where the 3 modules are easily accessible on the net:

SUBROUTINE tqli(d,e,z)

USE nrtype; USE nrutil, ONLY : assert_eq, nrerror
USE nr, ONLY : pythag

IMPLICIT NONE

REAL(sp), DIMENSION(:), INTENT(inout) :: d, e
!REAL(sp), DIMENSION(:,:), OPTIONAL, INTENT(inout) :: z

INTEGER(i4b) :: i, iter, l, m, n, ndum
REAL(sp) :: b, c, dd, f, g, p, r, s
REAL(sp), DIMENSION(SIZE(e)) :: ff

n = assert_eq(SIZE(d), SIZE(e), 'tqli: n')
!IF(PRESENT(z)) ndum=assert_eq(n, SIZE(z, 1), SIZE(z, 2), 'tqli: ndum')
e(:)=EOSHIFT(e(:),1)
DO l=1, n
iter=0
iterate: DO
DO m=l, n-1
dd=ABS(d(m)) + ABS(d(m+1))
IF(ABS(e(m))+dd == dd) EXIT
END DO
IF (m==l) EXIT iterate
IF(iter == 30) CALL nrerror('too many iterations in tqli')
iter = iter+1
g=(d(l+1)-d(l))/(2.0_sp*e(l))
r = pythag(g, 1.0_sp)
g = d(m) - d(l) + e(l) / (g + SIGN(r, g))
s = 1.0
c = 1.0
p = 0.0
DO i = m-1, l, -1
f = s*e(i)
b = c*e(i)
r = pythag(f, g)
e(i+1) = r
IF(r == 0.0) THEN
d(i+1) = d(i+1) - p
e(m) = 0.0
CYCLE iterate
END IF
s = f/r
c = g/r
g = d(i + 1) - p
r = (d(i) - g) * s + 2.0_sp * c * b
p = s * r
d(i + 1) = g + p
g = c * r - b
!IF(PRESENT(z)) THEN
!ff(1:n) = z(1:n,i+1)
!z(1:n, i+1) = s*z(1:n,i) + c*ff(1:n)
!z(1:n,i) = c*z(1:n, i) - s*ff(1:n)
!END IF
END DO
d(l) = d(l) - p
e(l) = g
e(m) = 0.0
END DO iterate
END DO
END SUBROUTINE tqli

!I have commented z out, since i'm only interested in the eigenvalues of this matrix.

Last edited by a moderator: May 3, 2017