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