Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / gmxlib / gmx_lapack / dsterf.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 #include <math.h>
36 #include "gmx_lapack.h"
37 #include "lapack_limits.h"
38
39 #include <types/simple.h>
40
41 void
42 F77_FUNC(dsterf,DSTERF)(int *n, 
43         double *d__, 
44         double *e, 
45         int *info)
46 {
47     int i__1;
48     double d__1;
49
50     double c__;
51     int i__, l, m;
52     double p, r__, s;
53     int l1;
54     double bb, rt1, rt2, eps, rte;
55     int lsv;
56     double eps2, oldc;
57     int lend, jtot;
58     double gamma, alpha, sigma, anorm;
59       int iscale;
60     double oldgam;
61     double safmax;
62     int lendsv;
63     double ssfmin;
64     int nmaxit;
65     double ssfmax;
66     int c__0 = 0;
67     int c__1 = 1;
68     double c_b32 = 1.;
69     const double safmin = GMX_DOUBLE_MIN*(1.0+GMX_DOUBLE_EPS);
70
71     --e;
72     --d__;
73
74     *info = 0;
75
76     if (*n < 0) {
77         *info = -1;
78         i__1 = -(*info);
79         return;
80     }
81     if (*n <= 1) {
82         return;
83     }
84
85     eps = GMX_DOUBLE_EPS;
86     d__1 = eps;
87     eps2 = d__1 * d__1;
88     safmax = 1. / safmin;
89     ssfmax = sqrt(safmax) / 3.;
90     ssfmin = sqrt(safmin) / eps2;
91
92     nmaxit = *n * 30;
93     sigma = 0.;
94     jtot = 0;
95
96     l1 = 1;
97
98 L10:
99     if (l1 > *n) {
100       F77_FUNC(dlasrt,DLASRT)("I", n, &d__[1], info);
101       return;
102     }
103     if (l1 > 1) {
104         e[l1 - 1] = 0.;
105     }
106     i__1 = *n - 1;
107     for (m = l1; m <= i__1; ++m) {
108         if (fabs(e[m]) <= sqrt(fabs(d__[m])) * 
109                 sqrt(fabs(d__[m + 1])) * eps) {
110             e[m] = 0.;
111             goto L30;
112         }
113     }
114     m = *n;
115
116 L30:
117     l = l1;
118     lsv = l;
119     lend = m;
120     lendsv = lend;
121     l1 = m + 1;
122     if (lend == l) {
123         goto L10;
124     }
125
126     i__1 = lend - l + 1;
127     anorm = F77_FUNC(dlanst,DLANST)("I", &i__1, &d__[l], &e[l]);
128     iscale = 0;
129     if (anorm > ssfmax) {
130         iscale = 1;
131         i__1 = lend - l + 1;
132         F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &d__[l], n, 
133                 info);
134         i__1 = lend - l;
135         F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &e[l], n, 
136                 info);
137     } else if (anorm < ssfmin) {
138         iscale = 2;
139         i__1 = lend - l + 1;
140         F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &d__[l], n, 
141                 info);
142         i__1 = lend - l;
143         F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &e[l], n, 
144                 info);
145     }
146
147     i__1 = lend - 1;
148     for (i__ = l; i__ <= i__1; ++i__) {
149         d__1 = e[i__];
150         e[i__] = d__1 * d__1;
151     }
152
153     if (fabs(d__[lend]) < fabs(d__[l])) {
154         lend = lsv;
155         l = lendsv;
156     }
157
158     if (lend >= l) {
159
160 L50:
161         if (l != lend) {
162             i__1 = lend - 1;
163             for (m = l; m <= i__1; ++m) {
164                 if (fabs(e[m]) <= eps2 * fabs(d__[m] * d__[m + 1])) {
165                     goto L70;
166                 }
167             }
168         }
169         m = lend;
170
171 L70:
172         if (m < lend) {
173             e[m] = 0.;
174         }
175         p = d__[l];
176         if (m == l) {
177             goto L90;
178         }
179         if (m == l + 1) {
180             rte = sqrt(e[l]);
181             F77_FUNC(dlae2,DLAE2)(&d__[l], &rte, &d__[l + 1], &rt1, &rt2);
182             d__[l] = rt1;
183             d__[l + 1] = rt2;
184             e[l] = 0.;
185             l += 2;
186             if (l <= lend) {
187                 goto L50;
188             }
189             goto L150;
190         }
191
192         if (jtot == nmaxit) {
193             goto L150;
194         }
195         ++jtot;
196
197         rte = sqrt(e[l]);
198         sigma = (d__[l + 1] - p) / (rte * 2.);
199         r__ = F77_FUNC(dlapy2,DLAPY2)(&sigma, &c_b32);
200         sigma = p - rte / (sigma + ( (sigma>0) ? r__ : -r__));
201
202         c__ = 1.;
203         s = 0.;
204         gamma = d__[m] - sigma;
205         p = gamma * gamma;
206
207         i__1 = l;
208         for (i__ = m - 1; i__ >= i__1; --i__) {
209             bb = e[i__];
210             r__ = p + bb;
211             if (i__ != m - 1) {
212                 e[i__ + 1] = s * r__;
213             }
214             oldc = c__;
215             c__ = p / r__;
216             s = bb / r__;
217             oldgam = gamma;
218             alpha = d__[i__];
219             gamma = c__ * (alpha - sigma) - s * oldgam;
220             d__[i__ + 1] = oldgam + (alpha - gamma);
221             if (fabs(c__)>GMX_DOUBLE_MIN) {
222                 p = gamma * gamma / c__;
223             } else {
224                 p = oldc * bb;
225             }
226         }
227
228         e[l] = s * p;
229         d__[l] = sigma + gamma;
230         goto L50;
231
232 L90:
233         d__[l] = p;
234
235         ++l;
236         if (l <= lend) {
237             goto L50;
238         }
239         goto L150;
240
241     } else {
242
243 L100:
244         i__1 = lend + 1;
245         for (m = l; m >= i__1; --m) {
246             if (fabs(e[m - 1]) <= eps2 * fabs(d__[m] * d__[m - 1])) {
247                 goto L120;
248             }
249         }
250         m = lend;
251
252 L120:
253         if (m > lend) {
254             e[m - 1] = 0.;
255         }
256         p = d__[l];
257         if (m == l) {
258             goto L140;
259         }
260
261         if (m == l - 1) {
262             rte = sqrt(e[l - 1]);
263             F77_FUNC(dlae2,DLAE2)(&d__[l], &rte, &d__[l - 1], &rt1, &rt2);
264             d__[l] = rt1;
265             d__[l - 1] = rt2;
266             e[l - 1] = 0.;
267             l += -2;
268             if (l >= lend) {
269                 goto L100;
270             }
271             goto L150;
272         }
273
274         if (jtot == nmaxit) {
275             goto L150;
276         }
277         ++jtot;
278
279         rte = sqrt(e[l - 1]);
280         sigma = (d__[l - 1] - p) / (rte * 2.);
281         r__ = F77_FUNC(dlapy2,DLAPY2)(&sigma, &c_b32);
282         sigma = p - rte / (sigma + ( (sigma>0) ? r__ : -r__));
283
284         c__ = 1.;
285         s = 0.;
286         gamma = d__[m] - sigma;
287         p = gamma * gamma;
288
289         i__1 = l - 1;
290         for (i__ = m; i__ <= i__1; ++i__) {
291             bb = e[i__];
292             r__ = p + bb;
293             if (i__ != m) {
294                 e[i__ - 1] = s * r__;
295             }
296             oldc = c__;
297             c__ = p / r__;
298             s = bb / r__;
299             oldgam = gamma;
300             alpha = d__[i__ + 1];
301             gamma = c__ * (alpha - sigma) - s * oldgam;
302             d__[i__] = oldgam + (alpha - gamma);
303             if (fabs(c__)>GMX_DOUBLE_MIN) {
304                 p = gamma * gamma / c__;
305             } else {
306                 p = oldc * bb;
307             }
308         }
309
310         e[l - 1] = s * p;
311         d__[l] = sigma + gamma;
312         goto L100;
313
314 L140:
315         d__[l] = p;
316
317         --l;
318         if (l >= lend) {
319             goto L100;
320         }
321         goto L150;
322
323     }
324
325 L150:
326     if (iscale == 1) {
327         i__1 = lendsv - lsv + 1;
328         F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &d__[lsv], 
329                 n, info);
330     }
331     if (iscale == 2) {
332         i__1 = lendsv - lsv + 1;
333         F77_FUNC(dlascl,DLASCL)("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &d__[lsv], 
334                 n, info);
335     }
336
337     if (jtot < nmaxit) {
338         goto L10;
339     }
340     i__1 = *n - 1;
341     for (i__ = 1; i__ <= i__1; ++i__) {
342         if (fabs(e[i__])>GMX_DOUBLE_MIN) {
343             ++(*info);
344         }
345     }
346     return;
347 }
348
349