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