Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / gmxlib / gmx_lapack / dlaebz.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
38 void
39 F77_FUNC(dlaebz,DLAEBZ)(int *ijob,
40         int *nitmax,
41         int *n, 
42         int *mmax,
43         int *minp,
44         int *nbmin,
45         double *abstol, 
46         double *reltol, 
47         double *pivmin, 
48         double *d__,
49         double *e,
50         double *e2, 
51         int *nval,
52         double *ab, 
53         double *c__, 
54         int *mout, 
55         int *nab,
56         double *work,
57         int *iwork, 
58         int *info)
59 {
60     int nab_dim1, nab_offset, ab_dim1, ab_offset, i__1, i__2, i__3, i__4, 
61             i__5, i__6;
62     double d__1, d__2, d__3, d__4;
63
64     int j, kf, ji, kl, jp, jit;
65     double tmp1, tmp2;
66     int itmp1, itmp2, kfnew, klnew;
67
68     nab_dim1 = *mmax;
69     nab_offset = 1 + nab_dim1;
70     nab -= nab_offset;
71     ab_dim1 = *mmax;
72     ab_offset = 1 + ab_dim1;
73     ab -= ab_offset;
74     --d__;
75     --e;
76     --e2;
77     --nval;
78     --c__;
79     --work;
80     --iwork;
81
82     *info = 0;
83     if (*ijob < 1 || *ijob > 3) {
84         *info = -1;
85         return;
86     }
87
88     if (*ijob == 1) {
89
90         *mout = 0;
91
92         i__1 = *minp;
93         for (ji = 1; ji <= i__1; ++ji) {
94             for (jp = 1; jp <= 2; ++jp) {
95                 tmp1 = d__[1] - ab[ji + jp * ab_dim1];
96                 if (fabs(tmp1) < *pivmin) {
97                     tmp1 = -(*pivmin);
98                 }
99                 nab[ji + jp * nab_dim1] = 0;
100                 if (tmp1 <= 0.) {
101                     nab[ji + jp * nab_dim1] = 1;
102                 }
103
104                 i__2 = *n;
105                 for (j = 2; j <= i__2; ++j) {
106                     tmp1 = d__[j] - e2[j - 1] / tmp1 - ab[ji + jp * ab_dim1];
107                     if (fabs(tmp1) < *pivmin) {
108                         tmp1 = -(*pivmin);
109                     }
110                     if (tmp1 <= 0.) {
111                         ++nab[ji + jp * nab_dim1];
112                     }
113                 }
114             }
115             *mout = *mout + nab[ji + (nab_dim1 << 1)] - nab[ji + nab_dim1];
116         }
117         return;
118     }
119
120     kf = 1;
121     kl = *minp;
122
123     if (*ijob == 2) {
124         i__1 = *minp;
125         for (ji = 1; ji <= i__1; ++ji) {
126             c__[ji] = (ab[ji + ab_dim1] + ab[ji + (ab_dim1 << 1)]) * .5;
127         }
128     }
129
130     i__1 = *nitmax;
131     for (jit = 1; jit <= i__1; ++jit) {
132
133         if (kl - kf + 1 >= *nbmin && *nbmin > 0) {
134
135             i__2 = kl;
136             for (ji = kf; ji <= i__2; ++ji) {
137
138                 work[ji] = d__[1] - c__[ji];
139                 iwork[ji] = 0;
140                 if (work[ji] <= *pivmin) {
141                     iwork[ji] = 1;
142                     d__1 = work[ji], d__2 = -(*pivmin);
143                     work[ji] = (d__1<d__2) ? d__1 : d__2;
144                 }
145
146                 i__3 = *n;
147                 for (j = 2; j <= i__3; ++j) {
148                     work[ji] = d__[j] - e2[j - 1] / work[ji] - c__[ji];
149                     if (work[ji] <= *pivmin) {
150                         ++iwork[ji];
151                         d__1 = work[ji], d__2 = -(*pivmin);
152                         work[ji] = (d__1<d__2) ? d__1 : d__2;
153                     }
154                 }
155             }
156
157             if (*ijob <= 2) {
158
159                 klnew = kl;
160                 i__2 = kl;
161                 for (ji = kf; ji <= i__2; ++ji) {
162
163                   i__5 = nab[ji + nab_dim1];
164                   i__6 = iwork[ji];
165                   i__3 = nab[ji + (nab_dim1 << 1)];
166                   i__4 = (i__5>i__6) ? i__5 : i__6;
167                     iwork[ji] = (i__3<i__4) ? i__3 : i__4;
168
169                     if (iwork[ji] == nab[ji + (nab_dim1 << 1)]) {
170
171                         ab[ji + (ab_dim1 << 1)] = c__[ji];
172
173                     } else if (iwork[ji] == nab[ji + nab_dim1]) {
174
175                         ab[ji + ab_dim1] = c__[ji];
176                     } else {
177                         ++klnew;
178                         if (klnew <= *mmax) {
179
180                             ab[klnew + (ab_dim1 << 1)] = ab[ji + (ab_dim1 << 
181                                     1)];
182                             nab[klnew + (nab_dim1 << 1)] = nab[ji + (nab_dim1 
183                                     << 1)];
184                             ab[klnew + ab_dim1] = c__[ji];
185                             nab[klnew + nab_dim1] = iwork[ji];
186                             ab[ji + (ab_dim1 << 1)] = c__[ji];
187                             nab[ji + (nab_dim1 << 1)] = iwork[ji];
188                         } else {
189                             *info = *mmax + 1;
190                         }
191                     }
192                 }
193                 if (*info != 0) {
194                     return;
195                 }
196                 kl = klnew;
197             } else {
198
199                 i__2 = kl;
200                 for (ji = kf; ji <= i__2; ++ji) {
201                     if (iwork[ji] <= nval[ji]) {
202                         ab[ji + ab_dim1] = c__[ji];
203                         nab[ji + nab_dim1] = iwork[ji];
204                     }
205                     if (iwork[ji] >= nval[ji]) {
206                         ab[ji + (ab_dim1 << 1)] = c__[ji];
207                         nab[ji + (nab_dim1 << 1)] = iwork[ji];
208                     }
209                 }
210             }
211
212         } else {
213
214             klnew = kl;
215             i__2 = kl;
216             for (ji = kf; ji <= i__2; ++ji) {
217
218                 tmp1 = c__[ji];
219                 tmp2 = d__[1] - tmp1;
220                 itmp1 = 0;
221                 if (tmp2 <= *pivmin) {
222                     itmp1 = 1;
223                     d__1 = tmp2, d__2 = -(*pivmin);
224                     tmp2 = (d__1<d__2) ? d__1 : d__2;
225                 }
226
227                 i__3 = *n;
228                 for (j = 2; j <= i__3; ++j) {
229                     tmp2 = d__[j] - e2[j - 1] / tmp2 - tmp1;
230                     if (tmp2 <= *pivmin) {
231                         ++itmp1;
232                         d__1 = tmp2, d__2 = -(*pivmin);
233                         tmp2 = (d__1<d__2) ? d__1 : d__2;
234                     }
235                 }
236
237                 if (*ijob <= 2) {
238
239                     i__5 = nab[ji + nab_dim1];
240                     i__3 = nab[ji + (nab_dim1 << 1)];
241                     i__4 = (i__5>itmp1) ? i__5 : itmp1;
242                     itmp1 = (i__3<i__4) ? i__3 : i__4;
243
244                     if (itmp1 == nab[ji + (nab_dim1 << 1)]) {
245
246                         ab[ji + (ab_dim1 << 1)] = tmp1;
247
248                     } else if (itmp1 == nab[ji + nab_dim1]) {
249
250                         ab[ji + ab_dim1] = tmp1;
251                     } else if (klnew < *mmax) {
252
253                         ++klnew;
254                         ab[klnew + (ab_dim1 << 1)] = ab[ji + (ab_dim1 << 1)];
255                         nab[klnew + (nab_dim1 << 1)] = nab[ji + (nab_dim1 << 
256                                 1)];
257                         ab[klnew + ab_dim1] = tmp1;
258                         nab[klnew + nab_dim1] = itmp1;
259                         ab[ji + (ab_dim1 << 1)] = tmp1;
260                         nab[ji + (nab_dim1 << 1)] = itmp1;
261                     } else {
262                         *info = *mmax + 1;
263                         return;
264                     }
265                 } else {
266
267                     if (itmp1 <= nval[ji]) {
268                         ab[ji + ab_dim1] = tmp1;
269                         nab[ji + nab_dim1] = itmp1;
270                     }
271                     if (itmp1 >= nval[ji]) {
272                         ab[ji + (ab_dim1 << 1)] = tmp1;
273                         nab[ji + (nab_dim1 << 1)] = itmp1;
274                     }
275                 }
276             }
277             kl = klnew;
278
279         }
280
281         kfnew = kf;
282         i__2 = kl;
283         for (ji = kf; ji <= i__2; ++ji) {
284             tmp1 = fabs(ab[ji + (ab_dim1 << 1)] - ab[ji + ab_dim1]);
285             d__3 = fabs(ab[ji + (ab_dim1 << 1)]);
286             d__4 = fabs(ab[ji + ab_dim1]);
287             tmp2 = (d__3>d__4) ? d__3 : d__4;
288             d__1 = (*abstol>*pivmin) ? *abstol : *pivmin;
289             d__2 = *reltol * tmp2;
290             if (tmp1 < ((d__1>d__2) ? d__1 : d__2) || nab[ji + nab_dim1] >= nab[ji + (
291                     nab_dim1 << 1)]) {
292
293                 if (ji > kfnew) {
294                     tmp1 = ab[ji + ab_dim1];
295                     tmp2 = ab[ji + (ab_dim1 << 1)];
296                     itmp1 = nab[ji + nab_dim1];
297                     itmp2 = nab[ji + (nab_dim1 << 1)];
298                     ab[ji + ab_dim1] = ab[kfnew + ab_dim1];
299                     ab[ji + (ab_dim1 << 1)] = ab[kfnew + (ab_dim1 << 1)];
300                     nab[ji + nab_dim1] = nab[kfnew + nab_dim1];
301                     nab[ji + (nab_dim1 << 1)] = nab[kfnew + (nab_dim1 << 1)];
302                     ab[kfnew + ab_dim1] = tmp1;
303                     ab[kfnew + (ab_dim1 << 1)] = tmp2;
304                     nab[kfnew + nab_dim1] = itmp1;
305                     nab[kfnew + (nab_dim1 << 1)] = itmp2;
306                     if (*ijob == 3) {
307                         itmp1 = nval[ji];
308                         nval[ji] = nval[kfnew];
309                         nval[kfnew] = itmp1;
310                     }
311                 }
312                 ++kfnew;
313             }
314         }
315         kf = kfnew;
316
317         i__2 = kl;
318         for (ji = kf; ji <= i__2; ++ji) {
319             c__[ji] = (ab[ji + ab_dim1] + ab[ji + (ab_dim1 << 1)]) * .5;
320         }
321
322         if (kf > kl) {
323             break;
324         }
325     }
326
327     i__1 = kl + 1 - kf;
328     if(i__1>0)
329       *info = i__1;
330
331     *mout = kl;
332
333     return;
334
335 }
336
337