function [D,E,Z,IERR]=TQL2(NM,N,D,E,Z)
%
% INTEGER I,J,K,L,M,N,II,L1,NM,MML,IERR
% REAL D(N),E(N),Z(NM,N)
% REAL B,C,F,G,H,P,R,S,MACHEP
% REAL SQRT,ABS,SIGN
%
% THIS SUBROUTINE IS A TRANSLATION OF THE ALGOL PROCEDURE TQL2,
% NUM. MATH. 11, 293-306(1968) BY BOWDLER, MARTIN, REINSCH, AND
% WILKINSON.
% HANDBOOK FOR AUTO. COMP., VOL.II-LINEAR ALGEBRA, 227-240(1971).
%
% THIS SUBROUTINE FINDS THE EIGENVALUES AND EIGENVECTORS
% OF A SYMMETRIC TRIDIAGONAL MATRIX BY THE QL METHOD.
% THE EIGENVECTORS OF A FULL SYMMETRIC MATRIX CAN ALSO
% BE FOUND IF TRED2 HAS BEEN USED TO REDUCE THIS
% FULL MATRIX TO TRIDIAGONAL FORM.
%
% ON INPUT-
%
% NM MUST BE SET TO THE ROW DIMENSION OF TWO-DIMENSIONAL
% ARRAY PARAMETERS AS DECLARED IN THE CALLING PROGRAM
% DIMENSION STATEMENT,
%
% N IS THE ORDER OF THE MATRIX,
%
% D CONTAINS THE DIAGONAL ELEMENTS OF THE INPUT MATRIX,
%
% E CONTAINS THE SUBDIAGONAL ELEMENTS OF THE INPUT MATRIX
% IN ITS LAST N-1 POSITIONS. E(1) IS ARBITRARY,
%
% Z CONTAINS THE TRANSFORMATION MATRIX PRODUCED IN THE
% REDUCTION BY TRED2, IF PERFORMED. IF THE EIGENVECTORS
% OF THE TRIDIAGONAL MATRIX ARE DESIRED, Z MUST CONTAIN
% THE IDENTITY MATRIX.
%
% ON OUTPUT-
%
% D CONTAINS THE EIGENVALUES IN ASCENDING ORDER. IF AN
% ERROR EXIT IS MADE, THE EIGENVALUES ARE CORRECT BUT
% UNORDERED FOR INDICES 1,2,...,IERR-1,
%
% E HAS BEEN DESTROYED,
%
% Z CONTAINS ORTHONORMAL EIGENVECTORS OF THE SYMMETRI%
% TRIDIAGONAL (OR FULL) MATRIX. IF AN ERROR EXIT IS MADE,
% Z CONTAINS THE EIGENVECTORS ASSOCIATED WITH THE STORED
% EIGENVALUES,
%
% IERR IS SET TO
% ZERO FOR NORMAL RETURN,
% J IF THE J-TH EIGENVALUE HAS NOT BEEN
% DETERMINED AFTER 30 ITERATIONS.
%
% QUESTIONS AND COMMENTS SHOULD BE DIRECTED TO B. S. GARBOW,
% APPLIED MATHEMATICS DIVISION, ARGONNE NATIONAL LABORATORY
% ------------------------------------------------------------------ TQL2
%
% ********** MACHEP IS A MACHINE DEPENDENT PARAMETER SPECIFYING
% THE RELATIVE PRECISION OF FLOATING POINT ARITHMETIC.
%
% **********
MACHEP = 2.^(-32);
IERR = 0;
%IF (N .EQ. 1) GO TO 1001
if N==1
return;
end
for I = 2: N
E(I-1) = E(I);
end
F = 0.0;
B = 0.0;
E(N) = 0.0;
% DO 240 L = 1, N
for L = 1: N
J = 0;
H = MACHEP * (abs(D(L)) + abs(E(L)));
if B < H
B = H;
end
% ********** LOOK FOR SMALL SUB-DIAGONAL ELEMENT **********
for M = L: N
%IF (ABS(E(M)) .LE. B) GO TO 120
if abs(E(M))<=B
break;
end
% ********** E(N) IS ALWAYS ZERO, SO THERE IS NO EXIT
% THROUGH THE BOTTOM OF THE LOOP **********
end
%120 IF (M .EQ. L) GO TO 220
if M==L
D(L) = D(L) + F;
continue;
end
%130 IF (J .EQ. 30) GO TO 1000
while(1)
if J==30
IERR = L;
return;
end
J = J + 1;
% ********** FORM SHIFT **********
L1 = L + 1;
G = D(L);
P = (D(L1) - G) / (2.0 * E(L));
R = sqrt(P*P+1.0);
D(L) = E(L) / (P + abs(R)*sign(P));
H = G - D(L);
for I = L1: N
D(I) = D(I) - H;
end
F = F + H;
% ********** QL TRANSFORMATION **********
P = D(M);
C = 1.0;
S = 0.0;
MML = M - L;
% ********** FOR I=M-1 STEP -1 UNTIL L DO -- **********
for II = 1: MML
I = M - II;
G = C * E(I);
H = C * P;
%IF (ABS(P) .LT. ABS(E(I))) GO TO 150
if abs(P)>=abs(E(I))
C = E(I) / P;
R = sqrt(C*C+1.0);
E(I+1) = S * P * R;
S = C / R;
C = 1.0 / R;
else
C = P / E(I);
R = sqrt(C*C+1.0);
E(I+1) = S * E(I) * R;
S = 1.0 / R;
C = C * S;
end
P = C * D(I) - S * G;
D(I+1) = H + S * (C * G + S * D(I));
% ********** FORM VECTOR **********
for K = 1: N
H = Z(K,I+1);
Z(K,I+1) = S * Z(K,I) + C * H;
Z(K,I) = C * Z(K,I) - S * H;
end
end
E(L) = S * P;
D(L) = C * P;
%IF (ABS(E(L)) .GT. B) GO TO 130
if abs(E(L))<=B
break;
end
end
D(L) = D(L) + F;
end
% ********** ORDER EIGENVALUES AND EIGENVECTORS **********
for II = 2: N
I = II - 1;
K = I;
P = D(I);
for J = II: N
%IF (D(J) .GE. P) GO TO 260
if D(J)<=P
continue;
end
K = J;
P = D(J);
end
%IF (K .EQ. I) GO TO 300
if K==I
continue;
end
D(K) = D(I);
D(I) = P;
for J = 1: N
P = Z(J,I);
Z(J,I) = Z(J,K);
Z(J,K) = P;
end
end