4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_ql77_c
= "$Id$";
36 void ql77 (int n
,real
*x
,real
*d
)
38 c matrix diagonalization routine
40 c code derived from eispack
41 c update : fmp 16.2.86 (conversion to fortran 77)
42 c update : fmp 09.3.89 (get rid of double precision)
44 c update : bh 16.5.99 (now works, real C code iso f2c)
49 c n order of the matrix, not larger than nmax
50 c x(n*n) the real symmetric matrix to be diagonalized as a
51 c two-indexed square array of which only the lower left
52 c triangle is used and need be supplied
56 c d(n) computed eigenvalues in descending order
57 c x(n*n) eigenvectors (in columns) in the same order as the
63 real
*e
,h
,g
,f
,b
,s
,p
,r
,c
,absp
;
66 #define pr_pr(a,b,c) fprintf(stderr,"\rreduction: %g%% accumulation: %g%% accumulation: %g%%",a,b,c)
68 const real eps
=7.e
-14,tol
=1.e
-30;
73 * householder reduction to tridiagonal form
78 totwork
+= pow(n
-ni
,3);
82 for(ni
=1; (ni
< n
); ni
++) {
101 for(j
=0; (j
<l
); j
++) {
104 for(k
=0; (k
<=j
); k
++)
105 s
=s
+x
[j
+n
*k
]*x
[i
+n
*k
];
106 for(k
=j
+1; (k
<l
); k
++)
107 s
=s
+x
[k
+n
*j
]*x
[i
+n
*k
];
113 e
[j
]=e
[j
]-f
*x
[i
+n
*j
];
114 for(j
=0; (j
<l
); j
++) {
117 for(k
=0; (k
<=j
); k
++)
118 x
[j
+n
*k
]=x
[j
+n
*k
]-f
*e
[k
]-x
[i
+n
*k
]*s
;
127 pr_pr(floor(100*work
/totwork
+0.5),0.,0.);
131 * accumulation of transformation matrix and intermediate d vector
139 for(i
=1; (i
<n
); i
++) {
141 for(j
=0; (j
<i
); j
++) {
144 s
=s
+x
[i
+n
*k
]*x
[k
+n
*j
];
146 x
[k
+n
*j
]=x
[k
+n
*j
]-s
*x
[k
+n
*i
];
151 for(j
=0; (j
<i
); j
++) {
157 pr_pr(100.,floor(100*work
/totwork
+0.5),0.);
170 for(l
=0; (l
<n
); l
++) {
171 h
=eps
*(fabs(d
[l
])+fabs(e
[l
]));
174 for(j
=l
; (j
<n
); j
++) {
181 p
=(d
[l
+1]-g
)*0.5/e
[l
];
189 for(i
=l
+1; (i
<n
); i
++)
195 for(ni
=l
; (ni
<j
); ni
++) {
199 if(fabs(p
) >= fabs(e
[i
])) {
213 d
[i
+1]=h
+s
*(c
*g
+s
*d
[i
]);
214 for(k
=0; (k
<n
); k
++) {
216 x
[k
+n
*(i
+1)]=x
[k
+n
*i
]*s
+h
*c
;
217 x
[k
+n
*i
]=x
[k
+n
*i
]*c
-h
*s
;
222 } while (fabs(e
[l
]) > b
);
228 pr_pr(100.,100.,floor(100*work
/totwork
+0.5));
230 fprintf(stderr
,"\n");
233 * put eigenvalues and eigenvectors in
234 * desired ascending order
237 for(i
=0; (i
<n
-1); i
++) {
241 for(j
=i
+1; (j
<n
); j
++) {
242 if(fabs(d
[j
]) < absp
) {
251 for(j
=0; (j
<n
); j
++) {
263 c last but not least i have to confess that there is an original
264 c g. binsch remark on this routine: 'ql is purported to be one of
265 c the fastest and most compact routines of its kind presently known