Split g96 I/O routines from confio.cpp
[gromacs.git] / src / gromacs / linearalgebra / gmx_lapack / sstegr.c
blobf2d0cfcb917a885c91751599183457f84baf5ce2
1 #include <math.h>
2 #include "../gmx_blas.h"
3 #include "../gmx_lapack.h"
4 #include "lapack_limits.h"
6 #include "gromacs/utility/real.h"
8 void
9 F77_FUNC(sstegr,SSTEGR)(const char *jobz,
10 const char *range,
11 int *n,
12 float *d__,
13 float *e,
14 float *vl,
15 float *vu,
16 int *il,
17 int *iu,
18 float *abstol,
19 int *m,
20 float *w,
21 float *z__,
22 int *ldz,
23 int *isuppz,
24 float *work,
25 int *lwork,
26 int *iwork,
27 int *liwork,
28 int *info)
30 int z_dim1, z_offset, i__1, i__2;
31 float d__1, d__2;
32 int c__1 = 1;
34 int i__, j;
35 int jj;
36 float eps, tol, tmp, rmin, rmax;
37 int itmp;
38 float tnrm;
39 float scale;
40 int iinfo, iindw;
41 int lwmin;
42 int wantz;
43 int iindbl;
44 int valeig,alleig,indeig;
45 float safmin,minval;
46 float bignum;
47 int iindwk, indgrs;
48 float thresh;
49 int iinspl, indwrk, liwmin, nsplit;
50 float smlnum;
51 int lquery;
54 --d__;
55 --e;
56 --w;
57 z_dim1 = *ldz;
58 z_offset = 1 + z_dim1;
59 z__ -= z_offset;
60 --isuppz;
61 --work;
62 --iwork;
64 wantz = (*jobz=='V' || *jobz=='v');
65 alleig = (*range=='A' || *range=='a');
66 valeig = (*range=='V' || *range=='v');
67 indeig = (*range=='I' || *range=='i');
69 lquery = *lwork == -1 || *liwork == -1;
70 lwmin = *n * 17;
71 liwmin = *n * 10;
73 *info = 0;
74 if (! (wantz || (*jobz=='N' || *jobz=='n'))) {
75 *info = -1;
76 } else if (! (alleig || valeig || indeig)) {
77 *info = -2;
78 } else if (*n < 0) {
79 *info = -3;
80 } else if (valeig && *n > 0 && *vu <= *vl) {
81 *info = -7;
82 } else if (indeig && (*il < 1 || *il > *n)) {
83 *info = -8;
84 } else if (indeig && (*iu < *il || *iu > *n)) {
85 *info = -9;
86 } else if (*ldz < 1 || (wantz && *ldz < *n)) {
87 *info = -14;
88 } else if (*lwork < lwmin && ! lquery) {
89 *info = -17;
90 } else if (*liwork < liwmin && ! lquery) {
91 *info = -19;
93 if (*info == 0) {
94 work[1] = (float) lwmin;
95 iwork[1] = liwmin;
98 if (*info != 0) {
99 i__1 = -(*info);
100 return;
101 } else if (lquery) {
102 return;
105 *m = 0;
106 if (*n == 0) {
107 return;
110 if (*n == 1) {
111 if (alleig || indeig) {
112 *m = 1;
113 w[1] = d__[1];
114 } else {
115 if (*vl < d__[1] && *vu >= d__[1]) {
116 *m = 1;
117 w[1] = d__[1];
120 if (wantz) {
121 z__[z_dim1 + 1] = 1.;
123 return;
126 minval = GMX_FLOAT_MIN;
127 safmin = minval*(1.0+GMX_FLOAT_EPS);
128 eps = GMX_FLOAT_EPS;
129 smlnum = safmin / eps;
130 bignum = 1. / smlnum;
131 rmin = sqrt(smlnum);
132 d__1 = sqrt(bignum), d__2 = 1. / sqrt(sqrt(safmin));
133 rmax = (d__1<d__2) ? d__1 : d__2;
134 scale = 1.;
135 tnrm = F77_FUNC(slanst,SLANST)("M", n, &d__[1], &e[1]);
136 if (tnrm > 0. && tnrm < rmin) {
137 scale = rmin / tnrm;
138 } else if (tnrm > rmax) {
139 scale = rmax / tnrm;
141 if ( fabs(scale-1.0)>GMX_FLOAT_EPS) {
142 F77_FUNC(sscal,SSCAL)(n, &scale, &d__[1], &c__1);
143 i__1 = *n - 1;
144 F77_FUNC(sscal,SSCAL)(&i__1, &scale, &e[1], &c__1);
145 tnrm *= scale;
147 indgrs = 1;
148 indwrk = (*n << 1) + 1;
150 iinspl = 1;
151 iindbl = *n + 1;
152 iindw = (*n << 1) + 1;
153 iindwk = *n * 3 + 1;
155 thresh = eps * tnrm;
156 F77_FUNC(slarrex,SLARREX)(range, n, vl, vu, il, iu, &d__[1], &e[1], &thresh, &nsplit, &
157 iwork[iinspl], m, &w[1], &iwork[iindbl], &iwork[iindw], &work[
158 indgrs], &work[indwrk], &iwork[iindwk], &iinfo);
160 if (iinfo != 0) {
161 *info = 1;
162 return;
165 if (wantz) {
166 d__1 = *abstol, d__2 = (float) (*n) * eps;
167 tol = (d__1>d__2) ? d__1 : d__2;
168 F77_FUNC(slarrvx,SLARRVX)(n, &d__[1], &e[1], &iwork[iinspl], m, &w[1], &iwork[iindbl], &
169 iwork[iindw], &work[indgrs], &tol, &z__[z_offset], ldz, &
170 isuppz[1], &work[indwrk], &iwork[iindwk], &iinfo);
171 if (iinfo != 0) {
172 *info = 2;
173 return;
177 i__1 = *m;
178 for (j = 1; j <= i__1; ++j) {
179 itmp = iwork[iindbl + j - 1];
180 w[j] += e[iwork[iinspl + itmp - 1]];
183 if (fabs(scale-1.0)>GMX_FLOAT_EPS) {
184 d__1 = 1. / scale;
185 F77_FUNC(sscal,SSCAL)(m, &d__1, &w[1], &c__1);
187 if (nsplit > 1) {
188 i__1 = *m - 1;
189 for (j = 1; j <= i__1; ++j) {
190 i__ = 0;
191 tmp = w[j];
192 i__2 = *m;
193 for (jj = j + 1; jj <= i__2; ++jj) {
194 if (w[jj] < tmp) {
195 i__ = jj;
196 tmp = w[jj];
199 if (i__ != 0) {
200 w[i__] = w[j];
201 w[j] = tmp;
202 if (wantz) {
203 F77_FUNC(sswap,SSWAP)(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[j * z_dim1
204 + 1], &c__1);
205 itmp = isuppz[(i__ << 1) - 1];
206 isuppz[(i__ << 1) - 1] = isuppz[(j << 1) - 1];
207 isuppz[(j << 1) - 1] = itmp;
208 itmp = isuppz[i__ * 2];
209 isuppz[i__ * 2] = isuppz[j * 2];
210 isuppz[j * 2] = itmp;
216 work[1] = (float) lwmin;
217 iwork[1] = liwmin;
218 return;