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