matthiasm@13
|
1 // $Id: nnls.cc,v 1.1.1.1 2003/04/02 22:06:19 suvrit Exp $
|
matthiasm@5
|
2 // File: nnls.cc
|
matthiasm@5
|
3 // Implements the Lawson-Hanson NNLS algorithm
|
matthiasm@5
|
4
|
matthiasm@5
|
5 #include "nnls.h"
|
matthiasm@5
|
6
|
matthiasm@5
|
7 float d_sign(float& a, float& b)
|
matthiasm@5
|
8 {
|
matthiasm@5
|
9 float x;
|
matthiasm@5
|
10 x = (a >= 0 ? a : - a);
|
matthiasm@5
|
11 return (b >= 0 ? x : -x);
|
matthiasm@5
|
12 }
|
matthiasm@13
|
13
|
matthiasm@5
|
14 /* Table of constant values */
|
matthiasm@13
|
15
|
matthiasm@5
|
16 int c__1 = 1;
|
matthiasm@5
|
17 int c__0 = 0;
|
matthiasm@5
|
18 int c__2 = 2;
|
matthiasm@5
|
19
|
matthiasm@5
|
20
|
matthiasm@13
|
21 int nnls(float* a, int mda, int m, int n, float* b,
|
matthiasm@13
|
22 float* x, float* rnorm, float* w, float* zz, int* index,
|
matthiasm@13
|
23 int* mode)
|
matthiasm@5
|
24 {
|
matthiasm@5
|
25 /* System generated locals */
|
matthiasm@5
|
26 int a_dim1, a_offset, idx1, idx2;
|
matthiasm@5
|
27 float d1, d2;
|
matthiasm@13
|
28
|
matthiasm@13
|
29
|
matthiasm@5
|
30 /* Local variables */
|
matthiasm@5
|
31 static int iter;
|
matthiasm@5
|
32 static float temp, wmax;
|
matthiasm@5
|
33 static int i__, j, l;
|
matthiasm@5
|
34 static float t, alpha, asave;
|
matthiasm@5
|
35 static int itmax, izmax, nsetp;
|
matthiasm@5
|
36 static float unorm, ztest, cc;
|
matthiasm@5
|
37 float dummy[2];
|
matthiasm@5
|
38 static int ii, jj, ip;
|
matthiasm@5
|
39 static float sm;
|
matthiasm@5
|
40 static int iz, jz;
|
matthiasm@5
|
41 static float up, ss;
|
matthiasm@5
|
42 static int rtnkey, iz1, iz2, npp1;
|
matthiasm@13
|
43
|
matthiasm@13
|
44 /* ------------------------------------------------------------------
|
matthiasm@5
|
45 */
|
matthiasm@5
|
46 /* int INDEX(N) */
|
matthiasm@5
|
47 /* float precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */
|
matthiasm@13
|
48 /* ------------------------------------------------------------------
|
matthiasm@5
|
49 */
|
matthiasm@5
|
50 /* Parameter adjustments */
|
matthiasm@5
|
51 a_dim1 = mda;
|
matthiasm@5
|
52 a_offset = a_dim1 + 1;
|
matthiasm@5
|
53 a -= a_offset;
|
matthiasm@5
|
54 --b;
|
matthiasm@5
|
55 --x;
|
matthiasm@5
|
56 --w;
|
matthiasm@5
|
57 --zz;
|
matthiasm@5
|
58 --index;
|
matthiasm@13
|
59
|
matthiasm@5
|
60 /* Function Body */
|
matthiasm@5
|
61 *mode = 1;
|
matthiasm@5
|
62 if (m <= 0 || n <= 0) {
|
matthiasm@5
|
63 *mode = 2;
|
matthiasm@5
|
64 return 0;
|
matthiasm@5
|
65 }
|
matthiasm@5
|
66 iter = 0;
|
matthiasm@5
|
67 itmax = n * 3;
|
matthiasm@13
|
68
|
matthiasm@5
|
69 /* INITIALIZE THE ARRAYS INDEX() AND X(). */
|
matthiasm@13
|
70
|
matthiasm@5
|
71 idx1 = n;
|
matthiasm@5
|
72 for (i__ = 1; i__ <= idx1; ++i__) {
|
matthiasm@5
|
73 x[i__] = 0.;
|
matthiasm@5
|
74 /* L20: */
|
matthiasm@5
|
75 index[i__] = i__;
|
matthiasm@5
|
76 }
|
matthiasm@13
|
77
|
matthiasm@5
|
78 iz2 = n;
|
matthiasm@5
|
79 iz1 = 1;
|
matthiasm@5
|
80 nsetp = 0;
|
matthiasm@5
|
81 npp1 = 1;
|
matthiasm@5
|
82 /* ****** MAIN LOOP BEGINS HERE ****** */
|
matthiasm@5
|
83 L30:
|
matthiasm@13
|
84 /* QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION.
|
matthiasm@5
|
85 */
|
matthiasm@5
|
86 /* OR IF M COLS OF A HAVE BEEN TRIANGULARIZED. */
|
matthiasm@13
|
87
|
matthiasm@5
|
88 if (iz1 > iz2 || nsetp >= m) {
|
matthiasm@5
|
89 goto L350;
|
matthiasm@5
|
90 }
|
matthiasm@13
|
91
|
matthiasm@13
|
92 /* COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W().
|
matthiasm@5
|
93 */
|
matthiasm@13
|
94
|
matthiasm@5
|
95 idx1 = iz2;
|
matthiasm@5
|
96 for (iz = iz1; iz <= idx1; ++iz) {
|
matthiasm@5
|
97 j = index[iz];
|
matthiasm@5
|
98 sm = 0.;
|
matthiasm@5
|
99 idx2 = m;
|
matthiasm@5
|
100 for (l = npp1; l <= idx2; ++l) {
|
matthiasm@5
|
101 /* L40: */
|
matthiasm@5
|
102 sm += a[l + j * a_dim1] * b[l];
|
matthiasm@5
|
103 }
|
matthiasm@5
|
104 w[j] = sm;
|
matthiasm@5
|
105 /* L50: */
|
matthiasm@5
|
106 }
|
matthiasm@5
|
107 /* FIND LARGEST POSITIVE W(J). */
|
matthiasm@5
|
108 L60:
|
matthiasm@5
|
109 wmax = 0.;
|
matthiasm@5
|
110 idx1 = iz2;
|
matthiasm@5
|
111 for (iz = iz1; iz <= idx1; ++iz) {
|
matthiasm@5
|
112 j = index[iz];
|
matthiasm@5
|
113 if (w[j] > wmax) {
|
matthiasm@5
|
114 wmax = w[j];
|
matthiasm@5
|
115 izmax = iz;
|
matthiasm@5
|
116 }
|
matthiasm@5
|
117 /* L70: */
|
matthiasm@5
|
118 }
|
matthiasm@13
|
119
|
matthiasm@5
|
120 /* IF WMAX .LE. 0. GO TO TERMINATION. */
|
matthiasm@13
|
121 /* THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS.
|
matthiasm@5
|
122 */
|
matthiasm@13
|
123
|
matthiasm@5
|
124 if (wmax <= 0.) {
|
matthiasm@5
|
125 goto L350;
|
matthiasm@5
|
126 }
|
matthiasm@5
|
127 iz = izmax;
|
matthiasm@5
|
128 j = index[iz];
|
matthiasm@13
|
129
|
matthiasm@5
|
130 /* THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P. */
|
matthiasm@5
|
131 /* BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID */
|
matthiasm@5
|
132 /* NEAR LINEAR DEPENDENCE. */
|
matthiasm@13
|
133
|
matthiasm@5
|
134 asave = a[npp1 + j * a_dim1];
|
matthiasm@5
|
135 idx1 = npp1 + 1;
|
matthiasm@5
|
136 h12(c__1, &npp1, &idx1, m, &a[j * a_dim1 + 1], &c__1, &up, dummy, &
|
matthiasm@5
|
137 c__1, &c__1, &c__0);
|
matthiasm@5
|
138 unorm = 0.;
|
matthiasm@5
|
139 if (nsetp != 0) {
|
matthiasm@5
|
140 idx1 = nsetp;
|
matthiasm@5
|
141 for (l = 1; l <= idx1; ++l) {
|
matthiasm@5
|
142 /* L90: */
|
matthiasm@5
|
143 /* Computing 2nd power */
|
matthiasm@5
|
144 d1 = a[l + j * a_dim1];
|
matthiasm@5
|
145 unorm += d1 * d1;
|
matthiasm@5
|
146 }
|
matthiasm@5
|
147 }
|
matthiasm@5
|
148 unorm = sqrt(unorm);
|
matthiasm@5
|
149 d2 = unorm + (d1 = a[npp1 + j * a_dim1], nnls_abs(d1)) * .01;
|
matthiasm@5
|
150 if ((d2- unorm) > 0.) {
|
matthiasm@13
|
151
|
matthiasm@5
|
152 /* COL J IS SUFFICIENTLY INDEPENDENT. COPY B INTO ZZ, UPDATE Z
|
matthiasm@13
|
153 Z */
|
matthiasm@5
|
154 /* AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */
|
matthiasm@13
|
155
|
matthiasm@5
|
156 idx1 = m;
|
matthiasm@5
|
157 for (l = 1; l <= idx1; ++l) {
|
matthiasm@5
|
158 /* L120: */
|
matthiasm@5
|
159 zz[l] = b[l];
|
matthiasm@5
|
160 }
|
matthiasm@5
|
161 idx1 = npp1 + 1;
|
matthiasm@5
|
162 h12(c__2, &npp1, &idx1, m, &a[j * a_dim1 + 1], &c__1, &up, (zz+1), &
|
matthiasm@13
|
163 c__1, &c__1, &c__1);
|
matthiasm@5
|
164 ztest = zz[npp1] / a[npp1 + j * a_dim1];
|
matthiasm@13
|
165
|
matthiasm@5
|
166 /* SEE IF ZTEST IS POSITIVE */
|
matthiasm@13
|
167
|
matthiasm@5
|
168 if (ztest > 0.) {
|
matthiasm@5
|
169 goto L140;
|
matthiasm@5
|
170 }
|
matthiasm@5
|
171 }
|
matthiasm@13
|
172
|
matthiasm@5
|
173 /* REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P. */
|
matthiasm@5
|
174 /* RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL */
|
matthiasm@5
|
175 /* COEFFS AGAIN. */
|
matthiasm@13
|
176
|
matthiasm@5
|
177 a[npp1 + j * a_dim1] = asave;
|
matthiasm@5
|
178 w[j] = 0.;
|
matthiasm@5
|
179 goto L60;
|
matthiasm@13
|
180
|
matthiasm@5
|
181 /* THE INDEX J=INDEX(IZ) HAS BEEN SELECTED TO BE MOVED FROM */
|
matthiasm@5
|
182 /* SET Z TO SET P. UPDATE B, UPDATE INDICES, APPLY HOUSEHOLDER */
|
matthiasm@5
|
183 /* TRANSFORMATIONS TO COLS IN NEW SET Z, ZERO SUBDIAGONAL ELTS IN */
|
matthiasm@5
|
184 /* COL J, SET W(J)=0. */
|
matthiasm@13
|
185
|
matthiasm@5
|
186 L140:
|
matthiasm@5
|
187 idx1 = m;
|
matthiasm@5
|
188 for (l = 1; l <= idx1; ++l) {
|
matthiasm@5
|
189 /* L150: */
|
matthiasm@5
|
190 b[l] = zz[l];
|
matthiasm@5
|
191 }
|
matthiasm@13
|
192
|
matthiasm@5
|
193 index[iz] = index[iz1];
|
matthiasm@5
|
194 index[iz1] = j;
|
matthiasm@5
|
195 ++iz1;
|
matthiasm@5
|
196 nsetp = npp1;
|
matthiasm@5
|
197 ++npp1;
|
matthiasm@13
|
198
|
matthiasm@5
|
199 if (iz1 <= iz2) {
|
matthiasm@5
|
200 idx1 = iz2;
|
matthiasm@5
|
201 for (jz = iz1; jz <= idx1; ++jz) {
|
matthiasm@5
|
202 jj = index[jz];
|
matthiasm@13
|
203 h12(c__2, &nsetp, &npp1, m,
|
matthiasm@13
|
204 &a[j * a_dim1 + 1], &c__1, &up,
|
matthiasm@13
|
205 &a[jj * a_dim1 + 1], &c__1, &mda, &c__1);
|
matthiasm@5
|
206 /* L160: */
|
matthiasm@5
|
207 }
|
matthiasm@5
|
208 }
|
matthiasm@13
|
209
|
matthiasm@5
|
210 if (nsetp != m) {
|
matthiasm@5
|
211 idx1 = m;
|
matthiasm@5
|
212 for (l = npp1; l <= idx1; ++l) {
|
matthiasm@5
|
213 /* L180: */
|
matthiasm@5
|
214 // SS: CHECK THIS DAMAGE....
|
matthiasm@5
|
215 a[l + j * a_dim1] = 0.;
|
matthiasm@5
|
216 }
|
matthiasm@5
|
217 }
|
matthiasm@13
|
218
|
matthiasm@5
|
219 w[j] = 0.;
|
matthiasm@5
|
220 /* SOLVE THE TRIANGULAR SYSTEM. */
|
matthiasm@13
|
221 /* STORE THE SOLUTION TEMPORARILY IN ZZ().
|
matthiasm@5
|
222 */
|
matthiasm@5
|
223 rtnkey = 1;
|
matthiasm@5
|
224 goto L400;
|
matthiasm@5
|
225 L200:
|
matthiasm@13
|
226
|
matthiasm@5
|
227 /* ****** SECONDARY LOOP BEGINS HERE ****** */
|
matthiasm@13
|
228
|
matthiasm@5
|
229 /* ITERATION COUNTER. */
|
matthiasm@13
|
230
|
matthiasm@5
|
231 L210:
|
matthiasm@5
|
232 ++iter;
|
matthiasm@5
|
233 if (iter > itmax) {
|
matthiasm@5
|
234 *mode = 3;
|
matthiasm@5
|
235 /* The following lines were replaced after the f2c translation */
|
matthiasm@5
|
236 /* s_wsfe(&io___22); */
|
matthiasm@5
|
237 /* do_fio(&c__1, " NNLS quitting on iteration count.", 34L); */
|
matthiasm@5
|
238 /* e_wsfe(); */
|
matthiasm@5
|
239 fprintf(stdout, "\n NNLS quitting on iteration count.\n");
|
matthiasm@5
|
240 fflush(stdout);
|
matthiasm@5
|
241 goto L350;
|
matthiasm@5
|
242 }
|
matthiasm@13
|
243
|
matthiasm@5
|
244 /* SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */
|
matthiasm@5
|
245 /* IF NOT COMPUTE ALPHA. */
|
matthiasm@13
|
246
|
matthiasm@5
|
247 alpha = 2.;
|
matthiasm@5
|
248 idx1 = nsetp;
|
matthiasm@5
|
249 for (ip = 1; ip <= idx1; ++ip) {
|
matthiasm@5
|
250 l = index[ip];
|
matthiasm@5
|
251 if (zz[ip] <= 0.) {
|
matthiasm@5
|
252 t = -x[l] / (zz[ip] - x[l]);
|
matthiasm@5
|
253 if (alpha > t) {
|
matthiasm@13
|
254 alpha = t;
|
matthiasm@13
|
255 jj = ip;
|
matthiasm@5
|
256 }
|
matthiasm@5
|
257 }
|
matthiasm@5
|
258 /* L240: */
|
matthiasm@5
|
259 }
|
matthiasm@13
|
260
|
matthiasm@5
|
261 /* IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL */
|
matthiasm@5
|
262 /* STILL = 2. IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP. */
|
matthiasm@13
|
263
|
matthiasm@5
|
264 if (alpha == 2.) {
|
matthiasm@5
|
265 goto L330;
|
matthiasm@5
|
266 }
|
matthiasm@13
|
267
|
matthiasm@5
|
268 /* OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO */
|
matthiasm@5
|
269 /* INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ. */
|
matthiasm@13
|
270
|
matthiasm@5
|
271 idx1 = nsetp;
|
matthiasm@5
|
272 for (ip = 1; ip <= idx1; ++ip) {
|
matthiasm@5
|
273 l = index[ip];
|
matthiasm@5
|
274 x[l] += alpha * (zz[ip] - x[l]);
|
matthiasm@5
|
275 /* L250: */
|
matthiasm@5
|
276 }
|
matthiasm@13
|
277
|
matthiasm@5
|
278 /* MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I */
|
matthiasm@5
|
279 /* FROM SET P TO SET Z. */
|
matthiasm@13
|
280
|
matthiasm@5
|
281 i__ = index[jj];
|
matthiasm@5
|
282 L260:
|
matthiasm@5
|
283 x[i__] = 0.;
|
matthiasm@13
|
284
|
matthiasm@5
|
285 if (jj != nsetp) {
|
matthiasm@5
|
286 ++jj;
|
matthiasm@5
|
287 idx1 = nsetp;
|
matthiasm@5
|
288 for (j = jj; j <= idx1; ++j) {
|
matthiasm@5
|
289 ii = index[j];
|
matthiasm@5
|
290 index[j - 1] = ii;
|
matthiasm@13
|
291 g1(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1],
|
matthiasm@13
|
292 &cc, &ss, &a[j - 1 + ii * a_dim1]);
|
matthiasm@5
|
293 // SS: CHECK THIS DAMAGE...
|
matthiasm@5
|
294 a[j + ii * a_dim1] = 0.;
|
matthiasm@5
|
295 idx2 = n;
|
matthiasm@5
|
296 for (l = 1; l <= idx2; ++l) {
|
matthiasm@13
|
297 if (l != ii) {
|
matthiasm@13
|
298
|
matthiasm@13
|
299 /* Apply procedure G2 (CC,SS,A(J-1,L),A(J,
|
matthiasm@13
|
300 L)) */
|
matthiasm@13
|
301
|
matthiasm@13
|
302 temp = a[j - 1 + l * a_dim1];
|
matthiasm@13
|
303 // SS: CHECK THIS DAMAGE
|
matthiasm@13
|
304 a[j - 1 + l * a_dim1] = cc * temp + ss * a[j + l * a_dim1];
|
matthiasm@13
|
305 a[j + l * a_dim1] = -ss * temp + cc * a[j + l * a_dim1];
|
matthiasm@13
|
306 }
|
matthiasm@13
|
307 /* L270: */
|
matthiasm@5
|
308 }
|
matthiasm@13
|
309
|
matthiasm@5
|
310 /* Apply procedure G2 (CC,SS,B(J-1),B(J)) */
|
matthiasm@13
|
311
|
matthiasm@5
|
312 temp = b[j - 1];
|
matthiasm@5
|
313 b[j - 1] = cc * temp + ss * b[j];
|
matthiasm@5
|
314 b[j] = -ss * temp + cc * b[j];
|
matthiasm@5
|
315 /* L280: */
|
matthiasm@5
|
316 }
|
matthiasm@5
|
317 }
|
matthiasm@13
|
318
|
matthiasm@5
|
319 npp1 = nsetp;
|
matthiasm@5
|
320 --nsetp;
|
matthiasm@5
|
321 --iz1;
|
matthiasm@5
|
322 index[iz1] = i__;
|
matthiasm@13
|
323
|
matthiasm@13
|
324 /* SEE IF THE REMAINING COEFFS IN SET P ARE FEASIBLE. THEY SHOULD
|
matthiasm@5
|
325 */
|
matthiasm@5
|
326 /* BE BECAUSE OF THE WAY ALPHA WAS DETERMINED. */
|
matthiasm@5
|
327 /* IF ANY ARE INFEASIBLE IT IS DUE TO ROUND-OFF ERROR. ANY */
|
matthiasm@5
|
328 /* THAT ARE NONPOSITIVE WILL BE SET TO ZERO */
|
matthiasm@5
|
329 /* AND MOVED FROM SET P TO SET Z. */
|
matthiasm@13
|
330
|
matthiasm@5
|
331 idx1 = nsetp;
|
matthiasm@5
|
332 for (jj = 1; jj <= idx1; ++jj) {
|
matthiasm@5
|
333 i__ = index[jj];
|
matthiasm@5
|
334 if (x[i__] <= 0.) {
|
matthiasm@5
|
335 goto L260;
|
matthiasm@5
|
336 }
|
matthiasm@5
|
337 /* L300: */
|
matthiasm@5
|
338 }
|
matthiasm@13
|
339
|
matthiasm@5
|
340 /* COPY B( ) INTO ZZ( ). THEN SOLVE AGAIN AND LOOP BACK. */
|
matthiasm@13
|
341
|
matthiasm@5
|
342 idx1 = m;
|
matthiasm@5
|
343 for (i__ = 1; i__ <= idx1; ++i__) {
|
matthiasm@5
|
344 /* L310: */
|
matthiasm@5
|
345 zz[i__] = b[i__];
|
matthiasm@5
|
346 }
|
matthiasm@5
|
347 rtnkey = 2;
|
matthiasm@5
|
348 goto L400;
|
matthiasm@5
|
349 L320:
|
matthiasm@5
|
350 goto L210;
|
matthiasm@5
|
351 /* ****** END OF SECONDARY LOOP ****** */
|
matthiasm@13
|
352
|
matthiasm@5
|
353 L330:
|
matthiasm@5
|
354 idx1 = nsetp;
|
matthiasm@5
|
355 for (ip = 1; ip <= idx1; ++ip) {
|
matthiasm@5
|
356 i__ = index[ip];
|
matthiasm@5
|
357 /* L340: */
|
matthiasm@5
|
358 x[i__] = zz[ip];
|
matthiasm@5
|
359 }
|
matthiasm@5
|
360 /* ALL NEW COEFFS ARE POSITIVE. LOOP BACK TO BEGINNING. */
|
matthiasm@5
|
361 goto L30;
|
matthiasm@13
|
362
|
matthiasm@5
|
363 /* ****** END OF MAIN LOOP ****** */
|
matthiasm@13
|
364
|
matthiasm@5
|
365 /* COME TO HERE FOR TERMINATION. */
|
matthiasm@5
|
366 /* COMPUTE THE NORM OF THE FINAL RESIDUAL VECTOR. */
|
matthiasm@13
|
367
|
matthiasm@5
|
368 L350:
|
matthiasm@5
|
369 sm = 0.;
|
matthiasm@5
|
370 if (npp1 <= m) {
|
matthiasm@5
|
371 idx1 = m;
|
matthiasm@5
|
372 for (i__ = npp1; i__ <= idx1; ++i__) {
|
matthiasm@5
|
373 /* L360: */
|
matthiasm@5
|
374 /* Computing 2nd power */
|
matthiasm@5
|
375 d1 = b[i__];
|
matthiasm@5
|
376 sm += d1 * d1;
|
matthiasm@5
|
377 }
|
matthiasm@5
|
378 } else {
|
matthiasm@5
|
379 idx1 = n;
|
matthiasm@5
|
380 for (j = 1; j <= idx1; ++j) {
|
matthiasm@5
|
381 /* L380: */
|
matthiasm@5
|
382 w[j] = 0.;
|
matthiasm@5
|
383 }
|
matthiasm@5
|
384 }
|
matthiasm@5
|
385 *rnorm = sqrt(sm);
|
matthiasm@5
|
386 return 0;
|
matthiasm@13
|
387
|
matthiasm@5
|
388 /* THE FOLLOWING BLOCK OF CODE IS USED AS AN INTERNAL SUBROUTINE */
|
matthiasm@5
|
389 /* TO SOLVE THE TRIANGULAR SYSTEM, PUTTING THE SOLUTION IN ZZ(). */
|
matthiasm@13
|
390
|
matthiasm@5
|
391 L400:
|
matthiasm@5
|
392 idx1 = nsetp;
|
matthiasm@5
|
393 for (l = 1; l <= idx1; ++l) {
|
matthiasm@5
|
394 ip = nsetp + 1 - l;
|
matthiasm@5
|
395 if (l != 1) {
|
matthiasm@5
|
396 idx2 = ip;
|
matthiasm@5
|
397 for (ii = 1; ii <= idx2; ++ii) {
|
matthiasm@13
|
398 zz[ii] -= a[ii + jj * a_dim1] * zz[ip + 1];
|
matthiasm@13
|
399 /* L410: */
|
matthiasm@5
|
400 }
|
matthiasm@5
|
401 }
|
matthiasm@5
|
402 jj = index[ip];
|
matthiasm@5
|
403 zz[ip] /= a[ip + jj * a_dim1];
|
matthiasm@5
|
404 /* L430: */
|
matthiasm@5
|
405 }
|
matthiasm@5
|
406 switch ((int)rtnkey) {
|
matthiasm@5
|
407 case 1: goto L200;
|
matthiasm@5
|
408 case 2: goto L320;
|
matthiasm@5
|
409 }
|
matthiasm@13
|
410
|
matthiasm@5
|
411 /* The next line was added after the f2c translation to keep
|
matthiasm@5
|
412 compilers from complaining about a void return from a non-void
|
matthiasm@5
|
413 function. */
|
matthiasm@5
|
414 return 0;
|
matthiasm@13
|
415
|
matthiasm@5
|
416 } /* nnls_ */
|
matthiasm@5
|
417
|
matthiasm@5
|
418
|
matthiasm@5
|
419 int g1(float* a, float* b, float* cterm, float* sterm, float* sig)
|
matthiasm@5
|
420 {
|
matthiasm@5
|
421 /* System generated locals */
|
matthiasm@5
|
422 float d;
|
matthiasm@13
|
423
|
matthiasm@5
|
424 static float xr, yr;
|
matthiasm@13
|
425
|
matthiasm@13
|
426
|
matthiasm@5
|
427 if (nnls_abs(*a) > nnls_abs(*b)) {
|
matthiasm@5
|
428 xr = *b / *a;
|
matthiasm@5
|
429 /* Computing 2nd power */
|
matthiasm@5
|
430 d = xr;
|
matthiasm@5
|
431 yr = sqrt(d * d + 1.);
|
matthiasm@5
|
432 d = 1. / yr;
|
matthiasm@5
|
433 *cterm = d_sign(d, *a);
|
matthiasm@5
|
434 *sterm = *cterm * xr;
|
matthiasm@5
|
435 *sig = nnls_abs(*a) * yr;
|
matthiasm@5
|
436 return 0;
|
matthiasm@5
|
437 }
|
matthiasm@5
|
438 if (*b != 0.) {
|
matthiasm@5
|
439 xr = *a / *b;
|
matthiasm@5
|
440 /* Computing 2nd power */
|
matthiasm@5
|
441 d = xr;
|
matthiasm@5
|
442 yr = sqrt(d * d + 1.);
|
matthiasm@5
|
443 d = 1. / yr;
|
matthiasm@5
|
444 *sterm = d_sign(d, *b);
|
matthiasm@5
|
445 *cterm = *sterm * xr;
|
matthiasm@5
|
446 *sig = nnls_abs(*b) * yr;
|
matthiasm@5
|
447 return 0;
|
matthiasm@5
|
448 }
|
matthiasm@5
|
449 *sig = 0.;
|
matthiasm@5
|
450 *cterm = 0.;
|
matthiasm@5
|
451 *sterm = 1.;
|
matthiasm@5
|
452 return 0;
|
matthiasm@5
|
453 } /* g1_ */
|
matthiasm@13
|
454
|
matthiasm@5
|
455
|
matthiasm@5
|
456 /* See nnls.h for explanation */
|
matthiasm@13
|
457 int h12(int mode, int* lpivot, int* l1,
|
matthiasm@13
|
458 int m, float* u, int* iue, float* up, float* c__,
|
matthiasm@13
|
459 int* ice, int* icv, int* ncv)
|
matthiasm@5
|
460 {
|
matthiasm@5
|
461 /* System generated locals */
|
matthiasm@5
|
462 int u_dim1, u_offset, idx1, idx2;
|
matthiasm@5
|
463 float d, d2;
|
matthiasm@13
|
464
|
matthiasm@5
|
465 /* Builtin functions */
|
matthiasm@5
|
466 /* The following line was commented out after the f2c translation */
|
matthiasm@5
|
467 /* float sqrt(); */
|
matthiasm@13
|
468
|
matthiasm@5
|
469 /* Local variables */
|
matthiasm@5
|
470 static int incr;
|
matthiasm@5
|
471 static float b;
|
matthiasm@5
|
472 static int i__, j;
|
matthiasm@5
|
473 static float clinv;
|
matthiasm@5
|
474 static int i2, i3, i4;
|
matthiasm@5
|
475 static float cl, sm;
|
matthiasm@13
|
476
|
matthiasm@13
|
477 /* ------------------------------------------------------------------
|
matthiasm@5
|
478 */
|
matthiasm@5
|
479 /* float precision U(IUE,M) */
|
matthiasm@13
|
480 /* ------------------------------------------------------------------
|
matthiasm@5
|
481 */
|
matthiasm@5
|
482 /* Parameter adjustments */
|
matthiasm@5
|
483 u_dim1 = *iue;
|
matthiasm@5
|
484 u_offset = u_dim1 + 1;
|
matthiasm@5
|
485 u -= u_offset;
|
matthiasm@5
|
486 --c__;
|
matthiasm@13
|
487
|
matthiasm@5
|
488 /* Function Body */
|
matthiasm@5
|
489 if (0 >= *lpivot || *lpivot >= *l1 || *l1 > m) {
|
matthiasm@5
|
490 return 0;
|
matthiasm@5
|
491 }
|
matthiasm@5
|
492 cl = (d = u[*lpivot * u_dim1 + 1], nnls_abs(d));
|
matthiasm@5
|
493 if (mode == 2) {
|
matthiasm@5
|
494 goto L60;
|
matthiasm@5
|
495 }
|
matthiasm@13
|
496 /* ****** CONSTRUCT THE TRANSFORMATION. ******
|
matthiasm@5
|
497 */
|
matthiasm@5
|
498 idx1 = m;
|
matthiasm@5
|
499 for (j = *l1; j <= idx1; ++j) {
|
matthiasm@5
|
500 /* L10: */
|
matthiasm@5
|
501 /* Computing MAX */
|
matthiasm@5
|
502 d2 = (d = u[j * u_dim1 + 1], nnls_abs(d));
|
matthiasm@5
|
503 cl = nnls_max(d2,cl);
|
matthiasm@5
|
504 }
|
matthiasm@5
|
505 if (cl <= 0.) {
|
matthiasm@5
|
506 goto L130;
|
matthiasm@5
|
507 } else {
|
matthiasm@5
|
508 goto L20;
|
matthiasm@5
|
509 }
|
matthiasm@5
|
510 L20:
|
matthiasm@5
|
511 clinv = 1. / cl;
|
matthiasm@5
|
512 /* Computing 2nd power */
|
matthiasm@5
|
513 d = u[*lpivot * u_dim1 + 1] * clinv;
|
matthiasm@5
|
514 sm = d * d;
|
matthiasm@5
|
515 idx1 = m;
|
matthiasm@5
|
516 for (j = *l1; j <= idx1; ++j) {
|
matthiasm@5
|
517 /* L30: */
|
matthiasm@5
|
518 /* Computing 2nd power */
|
matthiasm@5
|
519 d = u[j * u_dim1 + 1] * clinv;
|
matthiasm@5
|
520 sm += d * d;
|
matthiasm@5
|
521 }
|
matthiasm@5
|
522 cl *= sqrt(sm);
|
matthiasm@5
|
523 if (u[*lpivot * u_dim1 + 1] <= 0.) {
|
matthiasm@5
|
524 goto L50;
|
matthiasm@5
|
525 } else {
|
matthiasm@5
|
526 goto L40;
|
matthiasm@5
|
527 }
|
matthiasm@5
|
528 L40:
|
matthiasm@5
|
529 cl = -cl;
|
matthiasm@5
|
530 L50:
|
matthiasm@5
|
531 *up = u[*lpivot * u_dim1 + 1] - cl;
|
matthiasm@5
|
532 u[*lpivot * u_dim1 + 1] = cl;
|
matthiasm@5
|
533 goto L70;
|
matthiasm@13
|
534 /* ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C. ******
|
matthiasm@5
|
535 */
|
matthiasm@13
|
536
|
matthiasm@5
|
537 L60:
|
matthiasm@5
|
538 if (cl <= 0.) {
|
matthiasm@5
|
539 goto L130;
|
matthiasm@5
|
540 } else {
|
matthiasm@5
|
541 goto L70;
|
matthiasm@5
|
542 }
|
matthiasm@5
|
543 L70:
|
matthiasm@5
|
544 if (*ncv <= 0) {
|
matthiasm@5
|
545 return 0;
|
matthiasm@5
|
546 }
|
matthiasm@5
|
547 b = *up * u[*lpivot * u_dim1 + 1];
|
matthiasm@13
|
548 /* B MUST BE NONPOSITIVE HERE. IF B = 0., RETURN.
|
matthiasm@5
|
549 */
|
matthiasm@13
|
550
|
matthiasm@5
|
551 if (b >= 0.) {
|
matthiasm@5
|
552 goto L130;
|
matthiasm@5
|
553 } else {
|
matthiasm@5
|
554 goto L80;
|
matthiasm@5
|
555 }
|
matthiasm@5
|
556 L80:
|
matthiasm@5
|
557 b = 1. / b;
|
matthiasm@5
|
558 i2 = 1 - *icv + *ice * (*lpivot - 1);
|
matthiasm@5
|
559 incr = *ice * (*l1 - *lpivot);
|
matthiasm@5
|
560 idx1 = *ncv;
|
matthiasm@5
|
561 for (j = 1; j <= idx1; ++j) {
|
matthiasm@5
|
562 i2 += *icv;
|
matthiasm@5
|
563 i3 = i2 + incr;
|
matthiasm@5
|
564 i4 = i3;
|
matthiasm@5
|
565 sm = c__[i2] * *up;
|
matthiasm@5
|
566 idx2 = m;
|
matthiasm@5
|
567 for (i__ = *l1; i__ <= idx2; ++i__) {
|
matthiasm@5
|
568 sm += c__[i3] * u[i__ * u_dim1 + 1];
|
matthiasm@5
|
569 /* L90: */
|
matthiasm@5
|
570 i3 += *ice;
|
matthiasm@5
|
571 }
|
matthiasm@5
|
572 if (sm != 0.) {
|
matthiasm@5
|
573 goto L100;
|
matthiasm@5
|
574 } else {
|
matthiasm@5
|
575 goto L120;
|
matthiasm@5
|
576 }
|
matthiasm@5
|
577 L100:
|
matthiasm@5
|
578 sm *= b;
|
matthiasm@5
|
579 c__[i2] += sm * *up;
|
matthiasm@5
|
580 idx2 = m;
|
matthiasm@5
|
581 for (i__ = *l1; i__ <= idx2; ++i__) {
|
matthiasm@5
|
582 c__[i4] += sm * u[i__ * u_dim1 + 1];
|
matthiasm@5
|
583 /* L110: */
|
matthiasm@5
|
584 i4 += *ice;
|
matthiasm@5
|
585 }
|
matthiasm@5
|
586 L120:
|
matthiasm@5
|
587 ;
|
matthiasm@5
|
588 }
|
matthiasm@5
|
589 L130:
|
matthiasm@5
|
590 return 0;
|
matthiasm@5
|
591 } /* h12 */
|