Chris@25
|
1
|
Chris@25
|
2 #include "nnls.h"
|
Chris@25
|
3
|
Chris@25
|
4 typedef int integer;
|
Chris@25
|
5 typedef unsigned int uinteger;
|
Chris@25
|
6 typedef char *address;
|
Chris@25
|
7 typedef short int shortint;
|
Chris@25
|
8 typedef float real;
|
Chris@25
|
9 typedef double doublereal;
|
Chris@25
|
10
|
Chris@25
|
11 #define abs(x) ((x) >= 0 ? (x) : -(x))
|
Chris@25
|
12 #define dabs(x) (doublereal)abs(x)
|
Chris@25
|
13 #define min(a,b) ((a) <= (b) ? (a) : (b))
|
Chris@25
|
14 #define max(a,b) ((a) >= (b) ? (a) : (b))
|
Chris@25
|
15 #define dmin(a,b) (doublereal)min(a,b)
|
Chris@25
|
16 #define dmax(a,b) (doublereal)max(a,b)
|
Chris@25
|
17 #define bit_test(a,b) ((a) >> (b) & 1)
|
Chris@25
|
18 #define bit_clear(a,b) ((a) & ~((uinteger)1 << (b)))
|
Chris@25
|
19 #define bit_set(a,b) ((a) | ((uinteger)1 << (b)))
|
Chris@25
|
20
|
Chris@25
|
21 double d_sign(doublereal *a, doublereal *b)
|
Chris@25
|
22 {
|
Chris@25
|
23 double x;
|
Chris@25
|
24 x = (*a >= 0 ? *a : - *a);
|
Chris@25
|
25 return (*b >= 0 ? x : -x);
|
Chris@25
|
26 }
|
Chris@25
|
27
|
Chris@25
|
28 /* Table of constant values */
|
Chris@25
|
29
|
Chris@25
|
30 static integer c__1 = 1;
|
Chris@25
|
31 static integer c__0 = 0;
|
Chris@25
|
32 static integer c__2 = 2;
|
Chris@25
|
33
|
Chris@25
|
34 doublereal diff_(doublereal *x, doublereal *y)
|
Chris@25
|
35 {
|
Chris@25
|
36 /* System generated locals */
|
Chris@25
|
37 doublereal ret_val;
|
Chris@25
|
38
|
Chris@25
|
39
|
Chris@25
|
40 /* Function used in tests that depend on machine precision. */
|
Chris@25
|
41
|
Chris@25
|
42 /* The original version of this code was developed by */
|
Chris@25
|
43 /* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
|
Chris@25
|
44 /* 1973 JUN 7, and published in the book */
|
Chris@25
|
45 /* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
|
Chris@25
|
46 /* Revised FEB 1995 to accompany reprinting of the book by SIAM. */
|
Chris@25
|
47
|
Chris@25
|
48 ret_val = *x - *y;
|
Chris@25
|
49 return ret_val;
|
Chris@25
|
50 } /* diff_ */
|
Chris@25
|
51
|
Chris@25
|
52 /* Subroutine */ int g1_(doublereal *a, doublereal *b, doublereal *cterm,
|
Chris@25
|
53 doublereal *sterm, doublereal *sig)
|
Chris@25
|
54 {
|
Chris@25
|
55 /* System generated locals */
|
Chris@25
|
56 doublereal d__1;
|
Chris@25
|
57
|
Chris@25
|
58 /* Builtin functions */
|
Chris@25
|
59 double sqrt(doublereal), d_sign(doublereal *, doublereal *);
|
Chris@25
|
60
|
Chris@25
|
61 /* Local variables */
|
Chris@25
|
62 static doublereal xr, yr;
|
Chris@25
|
63
|
Chris@25
|
64
|
Chris@25
|
65 /* COMPUTE ORTHOGONAL ROTATION MATRIX.. */
|
Chris@25
|
66
|
Chris@25
|
67 /* The original version of this code was developed by */
|
Chris@25
|
68 /* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
|
Chris@25
|
69 /* 1973 JUN 12, and published in the book */
|
Chris@25
|
70 /* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
|
Chris@25
|
71 /* Revised FEB 1995 to accompany reprinting of the book by SIAM. */
|
Chris@25
|
72
|
Chris@25
|
73 /* COMPUTE.. MATRIX (C, S) SO THAT (C, S)(A) = (SQRT(A**2+B**2)) */
|
Chris@25
|
74 /* (-S,C) (-S,C)(B) ( 0 ) */
|
Chris@25
|
75 /* COMPUTE SIG = SQRT(A**2+B**2) */
|
Chris@25
|
76 /* SIG IS COMPUTED LAST TO ALLOW FOR THE POSSIBILITY THAT */
|
Chris@25
|
77 /* SIG MAY BE IN THE SAME LOCATION AS A OR B . */
|
Chris@25
|
78 /* ------------------------------------------------------------------ */
|
Chris@25
|
79 /* ------------------------------------------------------------------ */
|
Chris@25
|
80 if (abs(*a) > abs(*b)) {
|
Chris@25
|
81 xr = *b / *a;
|
Chris@25
|
82 /* Computing 2nd power */
|
Chris@25
|
83 d__1 = xr;
|
Chris@25
|
84 yr = sqrt(d__1 * d__1 + 1.);
|
Chris@25
|
85 d__1 = 1. / yr;
|
Chris@25
|
86 *cterm = d_sign(&d__1, a);
|
Chris@25
|
87 *sterm = *cterm * xr;
|
Chris@25
|
88 *sig = abs(*a) * yr;
|
Chris@25
|
89 return 0;
|
Chris@25
|
90 }
|
Chris@25
|
91 if (*b != 0.) {
|
Chris@25
|
92 xr = *a / *b;
|
Chris@25
|
93 /* Computing 2nd power */
|
Chris@25
|
94 d__1 = xr;
|
Chris@25
|
95 yr = sqrt(d__1 * d__1 + 1.);
|
Chris@25
|
96 d__1 = 1. / yr;
|
Chris@25
|
97 *sterm = d_sign(&d__1, b);
|
Chris@25
|
98 *cterm = *sterm * xr;
|
Chris@25
|
99 *sig = abs(*b) * yr;
|
Chris@25
|
100 return 0;
|
Chris@25
|
101 }
|
Chris@25
|
102 *sig = 0.;
|
Chris@25
|
103 *cterm = 0.;
|
Chris@25
|
104 *sterm = 1.;
|
Chris@25
|
105 return 0;
|
Chris@25
|
106 } /* g1_ */
|
Chris@25
|
107
|
Chris@25
|
108 /* SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV) */
|
Chris@25
|
109
|
Chris@25
|
110 /* CONSTRUCTION AND/OR APPLICATION OF A SINGLE */
|
Chris@25
|
111 /* HOUSEHOLDER TRANSFORMATION.. Q = I + U*(U**T)/B */
|
Chris@25
|
112
|
Chris@25
|
113 /* The original version of this code was developed by */
|
Chris@25
|
114 /* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
|
Chris@25
|
115 /* 1973 JUN 12, and published in the book */
|
Chris@25
|
116 /* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
|
Chris@25
|
117 /* Revised FEB 1995 to accompany reprinting of the book by SIAM. */
|
Chris@25
|
118 /* ------------------------------------------------------------------ */
|
Chris@25
|
119 /* Subroutine Arguments */
|
Chris@25
|
120
|
Chris@25
|
121 /* MODE = 1 OR 2 Selects Algorithm H1 to construct and apply a */
|
Chris@25
|
122 /* Householder transformation, or Algorithm H2 to apply a */
|
Chris@25
|
123 /* previously constructed transformation. */
|
Chris@25
|
124 /* LPIVOT IS THE INDEX OF THE PIVOT ELEMENT. */
|
Chris@25
|
125 /* L1,M IF L1 .LE. M THE TRANSFORMATION WILL BE CONSTRUCTED TO */
|
Chris@25
|
126 /* ZERO ELEMENTS INDEXED FROM L1 THROUGH M. IF L1 GT. M */
|
Chris@25
|
127 /* THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION. */
|
Chris@25
|
128 /* U(),IUE,UP On entry with MODE = 1, U() contains the pivot */
|
Chris@25
|
129 /* vector. IUE is the storage increment between elements. */
|
Chris@25
|
130 /* On exit when MODE = 1, U() and UP contain quantities */
|
Chris@25
|
131 /* defining the vector U of the Householder transformation. */
|
Chris@25
|
132 /* on entry with MODE = 2, U() and UP should contain */
|
Chris@25
|
133 /* quantities previously computed with MODE = 1. These will */
|
Chris@25
|
134 /* not be modified during the entry with MODE = 2. */
|
Chris@25
|
135 /* C() ON ENTRY with MODE = 1 or 2, C() CONTAINS A MATRIX WHICH */
|
Chris@25
|
136 /* WILL BE REGARDED AS A SET OF VECTORS TO WHICH THE */
|
Chris@25
|
137 /* HOUSEHOLDER TRANSFORMATION IS TO BE APPLIED. */
|
Chris@25
|
138 /* ON EXIT C() CONTAINS THE SET OF TRANSFORMED VECTORS. */
|
Chris@25
|
139 /* ICE STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C(). */
|
Chris@25
|
140 /* ICV STORAGE INCREMENT BETWEEN VECTORS IN C(). */
|
Chris@25
|
141 /* NCV NUMBER OF VECTORS IN C() TO BE TRANSFORMED. IF NCV .LE. 0 */
|
Chris@25
|
142 /* NO OPERATIONS WILL BE DONE ON C(). */
|
Chris@25
|
143 /* ------------------------------------------------------------------ */
|
Chris@25
|
144 /* Subroutine */ int h12_(integer *mode, integer *lpivot, integer *l1,
|
Chris@25
|
145 integer *m, doublereal *u, integer *iue, doublereal *up, doublereal *
|
Chris@25
|
146 c__, integer *ice, integer *icv, integer *ncv)
|
Chris@25
|
147 {
|
Chris@25
|
148 /* System generated locals */
|
Chris@25
|
149 integer u_dim1, u_offset, i__1, i__2;
|
Chris@25
|
150 doublereal d__1, d__2;
|
Chris@25
|
151
|
Chris@25
|
152 /* Builtin functions */
|
Chris@25
|
153 double sqrt(doublereal);
|
Chris@25
|
154
|
Chris@25
|
155 /* Local variables */
|
Chris@25
|
156 static doublereal b;
|
Chris@25
|
157 static integer i__, j, i2, i3, i4;
|
Chris@25
|
158 static doublereal cl, sm;
|
Chris@25
|
159 static integer incr;
|
Chris@25
|
160 static doublereal clinv;
|
Chris@25
|
161
|
Chris@25
|
162 /* ------------------------------------------------------------------ */
|
Chris@25
|
163 /* double precision U(IUE,M) */
|
Chris@25
|
164 /* ------------------------------------------------------------------ */
|
Chris@25
|
165 /* Parameter adjustments */
|
Chris@25
|
166 u_dim1 = *iue;
|
Chris@25
|
167 u_offset = 1 + u_dim1;
|
Chris@25
|
168 u -= u_offset;
|
Chris@25
|
169 --c__;
|
Chris@25
|
170
|
Chris@25
|
171 /* Function Body */
|
Chris@25
|
172 if (0 >= *lpivot || *lpivot >= *l1 || *l1 > *m) {
|
Chris@25
|
173 return 0;
|
Chris@25
|
174 }
|
Chris@25
|
175 cl = (d__1 = u[*lpivot * u_dim1 + 1], abs(d__1));
|
Chris@25
|
176 if (*mode == 2) {
|
Chris@25
|
177 goto L60;
|
Chris@25
|
178 }
|
Chris@25
|
179 /* ****** CONSTRUCT THE TRANSFORMATION. ****** */
|
Chris@25
|
180 i__1 = *m;
|
Chris@25
|
181 for (j = *l1; j <= i__1; ++j) {
|
Chris@25
|
182 /* L10: */
|
Chris@25
|
183 /* Computing MAX */
|
Chris@25
|
184 d__2 = (d__1 = u[j * u_dim1 + 1], abs(d__1));
|
Chris@25
|
185 cl = max(d__2,cl);
|
Chris@25
|
186 }
|
Chris@25
|
187 if (cl <= 0.) {
|
Chris@25
|
188 goto L130;
|
Chris@25
|
189 } else {
|
Chris@25
|
190 goto L20;
|
Chris@25
|
191 }
|
Chris@25
|
192 L20:
|
Chris@25
|
193 clinv = 1. / cl;
|
Chris@25
|
194 /* Computing 2nd power */
|
Chris@25
|
195 d__1 = u[*lpivot * u_dim1 + 1] * clinv;
|
Chris@25
|
196 sm = d__1 * d__1;
|
Chris@25
|
197 i__1 = *m;
|
Chris@25
|
198 for (j = *l1; j <= i__1; ++j) {
|
Chris@25
|
199 /* L30: */
|
Chris@25
|
200 /* Computing 2nd power */
|
Chris@25
|
201 d__1 = u[j * u_dim1 + 1] * clinv;
|
Chris@25
|
202 sm += d__1 * d__1;
|
Chris@25
|
203 }
|
Chris@25
|
204 cl *= sqrt(sm);
|
Chris@25
|
205 if (u[*lpivot * u_dim1 + 1] <= 0.) {
|
Chris@25
|
206 goto L50;
|
Chris@25
|
207 } else {
|
Chris@25
|
208 goto L40;
|
Chris@25
|
209 }
|
Chris@25
|
210 L40:
|
Chris@25
|
211 cl = -cl;
|
Chris@25
|
212 L50:
|
Chris@25
|
213 *up = u[*lpivot * u_dim1 + 1] - cl;
|
Chris@25
|
214 u[*lpivot * u_dim1 + 1] = cl;
|
Chris@25
|
215 goto L70;
|
Chris@25
|
216 /* ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C. ****** */
|
Chris@25
|
217
|
Chris@25
|
218 L60:
|
Chris@25
|
219 if (cl <= 0.) {
|
Chris@25
|
220 goto L130;
|
Chris@25
|
221 } else {
|
Chris@25
|
222 goto L70;
|
Chris@25
|
223 }
|
Chris@25
|
224 L70:
|
Chris@25
|
225 if (*ncv <= 0) {
|
Chris@25
|
226 return 0;
|
Chris@25
|
227 }
|
Chris@25
|
228 b = *up * u[*lpivot * u_dim1 + 1];
|
Chris@25
|
229 /* B MUST BE NONPOSITIVE HERE. IF B = 0., RETURN. */
|
Chris@25
|
230
|
Chris@25
|
231 if (b >= 0.) {
|
Chris@25
|
232 goto L130;
|
Chris@25
|
233 } else {
|
Chris@25
|
234 goto L80;
|
Chris@25
|
235 }
|
Chris@25
|
236 L80:
|
Chris@25
|
237 b = 1. / b;
|
Chris@25
|
238 i2 = 1 - *icv + *ice * (*lpivot - 1);
|
Chris@25
|
239 incr = *ice * (*l1 - *lpivot);
|
Chris@25
|
240 i__1 = *ncv;
|
Chris@25
|
241 for (j = 1; j <= i__1; ++j) {
|
Chris@25
|
242 i2 += *icv;
|
Chris@25
|
243 i3 = i2 + incr;
|
Chris@25
|
244 i4 = i3;
|
Chris@25
|
245 sm = c__[i2] * *up;
|
Chris@25
|
246 i__2 = *m;
|
Chris@25
|
247 for (i__ = *l1; i__ <= i__2; ++i__) {
|
Chris@25
|
248 sm += c__[i3] * u[i__ * u_dim1 + 1];
|
Chris@25
|
249 /* L90: */
|
Chris@25
|
250 i3 += *ice;
|
Chris@25
|
251 }
|
Chris@25
|
252 if (sm != 0.) {
|
Chris@25
|
253 goto L100;
|
Chris@25
|
254 } else {
|
Chris@25
|
255 goto L120;
|
Chris@25
|
256 }
|
Chris@25
|
257 L100:
|
Chris@25
|
258 sm *= b;
|
Chris@25
|
259 c__[i2] += sm * *up;
|
Chris@25
|
260 i__2 = *m;
|
Chris@25
|
261 for (i__ = *l1; i__ <= i__2; ++i__) {
|
Chris@25
|
262 c__[i4] += sm * u[i__ * u_dim1 + 1];
|
Chris@25
|
263 /* L110: */
|
Chris@25
|
264 i4 += *ice;
|
Chris@25
|
265 }
|
Chris@25
|
266 L120:
|
Chris@25
|
267 ;
|
Chris@25
|
268 }
|
Chris@25
|
269 L130:
|
Chris@25
|
270 return 0;
|
Chris@25
|
271 } /* h12_ */
|
Chris@25
|
272
|
Chris@25
|
273 /* SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE) */
|
Chris@25
|
274
|
Chris@25
|
275 /* Algorithm NNLS: NONNEGATIVE LEAST SQUARES */
|
Chris@25
|
276
|
Chris@25
|
277 /* The original version of this code was developed by */
|
Chris@25
|
278 /* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */
|
Chris@25
|
279 /* 1973 JUN 15, and published in the book */
|
Chris@25
|
280 /* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */
|
Chris@25
|
281 /* Revised FEB 1995 to accompany reprinting of the book by SIAM. */
|
Chris@25
|
282
|
Chris@25
|
283 /* GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN */
|
Chris@25
|
284 /* N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM */
|
Chris@25
|
285
|
Chris@25
|
286 /* A * X = B SUBJECT TO X .GE. 0 */
|
Chris@25
|
287 /* ------------------------------------------------------------------ */
|
Chris@25
|
288 /* Subroutine Arguments */
|
Chris@25
|
289
|
Chris@25
|
290 /* A(),MDA,M,N MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE */
|
Chris@25
|
291 /* ARRAY, A(). ON ENTRY A() CONTAINS THE M BY N */
|
Chris@25
|
292 /* MATRIX, A. ON EXIT A() CONTAINS */
|
Chris@25
|
293 /* THE PRODUCT MATRIX, Q*A , WHERE Q IS AN */
|
Chris@25
|
294 /* M BY M ORTHOGONAL MATRIX GENERATED IMPLICITLY BY */
|
Chris@25
|
295 /* THIS SUBROUTINE. */
|
Chris@25
|
296 /* B() ON ENTRY B() CONTAINS THE M-VECTOR, B. ON EXIT B() CON- */
|
Chris@25
|
297 /* TAINS Q*B. */
|
Chris@25
|
298 /* X() ON ENTRY X() NEED NOT BE INITIALIZED. ON EXIT X() WILL */
|
Chris@25
|
299 /* CONTAIN THE SOLUTION VECTOR. */
|
Chris@25
|
300 /* RNORM ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE */
|
Chris@25
|
301 /* RESIDUAL VECTOR. */
|
Chris@25
|
302 /* W() AN N-ARRAY OF WORKING SPACE. ON EXIT W() WILL CONTAIN */
|
Chris@25
|
303 /* THE DUAL SOLUTION VECTOR. W WILL SATISFY W(I) = 0. */
|
Chris@25
|
304 /* FOR ALL I IN SET P AND W(I) .LE. 0. FOR ALL I IN SET Z */
|
Chris@25
|
305 /* ZZ() AN M-ARRAY OF WORKING SPACE. */
|
Chris@25
|
306 /* INDEX() AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N. */
|
Chris@25
|
307 /* ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS */
|
Chris@25
|
308 /* P AND Z AS FOLLOWS.. */
|
Chris@25
|
309
|
Chris@25
|
310 /* INDEX(1) THRU INDEX(NSETP) = SET P. */
|
Chris@25
|
311 /* INDEX(IZ1) THRU INDEX(IZ2) = SET Z. */
|
Chris@25
|
312 /* IZ1 = NSETP + 1 = NPP1 */
|
Chris@25
|
313 /* IZ2 = N */
|
Chris@25
|
314 /* MODE THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING */
|
Chris@25
|
315 /* MEANINGS. */
|
Chris@25
|
316 /* 1 THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY. */
|
Chris@25
|
317 /* 2 THE DIMENSIONS OF THE PROBLEM ARE BAD. */
|
Chris@25
|
318 /* EITHER M .LE. 0 OR N .LE. 0. */
|
Chris@25
|
319 /* 3 ITERATION COUNT EXCEEDED. MORE THAN 3*N ITERATIONS. */
|
Chris@25
|
320
|
Chris@25
|
321 /* ------------------------------------------------------------------ */
|
Chris@25
|
322 /* Subroutine */ int nnls_(doublereal *a, integer *mda, integer *m, integer *
|
Chris@25
|
323 n, doublereal *b, doublereal *x, doublereal *rnorm, doublereal *w,
|
Chris@25
|
324 doublereal *zz, integer *index, integer *mode)
|
Chris@25
|
325 {
|
Chris@25
|
326 /* System generated locals */
|
Chris@25
|
327 integer a_dim1, a_offset, i__1, i__2;
|
Chris@25
|
328 doublereal d__1, d__2;
|
Chris@25
|
329
|
Chris@25
|
330 /* Builtin functions */
|
Chris@25
|
331 double sqrt(doublereal);
|
Chris@25
|
332
|
Chris@25
|
333 /* Local variables */
|
Chris@25
|
334 static integer i__, j, l;
|
Chris@25
|
335 static doublereal t;
|
Chris@25
|
336 extern /* Subroutine */ int g1_(doublereal *, doublereal *, doublereal *,
|
Chris@25
|
337 doublereal *, doublereal *);
|
Chris@25
|
338 static doublereal cc;
|
Chris@25
|
339 extern /* Subroutine */ int h12_(integer *, integer *, integer *, integer
|
Chris@25
|
340 *, doublereal *, integer *, doublereal *, doublereal *, integer *,
|
Chris@25
|
341 integer *, integer *);
|
Chris@25
|
342 static integer ii, jj, ip;
|
Chris@25
|
343 static doublereal sm;
|
Chris@25
|
344 static integer iz, jz;
|
Chris@25
|
345 static doublereal up, ss;
|
Chris@25
|
346 static integer iz1, iz2, npp1;
|
Chris@25
|
347 extern doublereal diff_(doublereal *, doublereal *);
|
Chris@25
|
348 static integer iter;
|
Chris@25
|
349 static doublereal temp, wmax, alpha, asave;
|
Chris@25
|
350 static integer itmax, izmax, nsetp;
|
Chris@25
|
351 static doublereal dummy, unorm, ztest;
|
Chris@25
|
352 static integer rtnkey;
|
Chris@25
|
353
|
Chris@25
|
354 /* ------------------------------------------------------------------ */
|
Chris@25
|
355 /* integer INDEX(N) */
|
Chris@25
|
356 /* double precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */
|
Chris@25
|
357 /* ------------------------------------------------------------------ */
|
Chris@25
|
358 /* Parameter adjustments */
|
Chris@25
|
359 a_dim1 = *mda;
|
Chris@25
|
360 a_offset = 1 + a_dim1;
|
Chris@25
|
361 a -= a_offset;
|
Chris@25
|
362 --b;
|
Chris@25
|
363 --x;
|
Chris@25
|
364 --w;
|
Chris@25
|
365 --zz;
|
Chris@25
|
366 --index;
|
Chris@25
|
367
|
Chris@25
|
368 /* Function Body */
|
Chris@25
|
369 *mode = 1;
|
Chris@25
|
370 if (*m <= 0 || *n <= 0) {
|
Chris@25
|
371 *mode = 2;
|
Chris@25
|
372 return 0;
|
Chris@25
|
373 }
|
Chris@25
|
374 iter = 0;
|
Chris@25
|
375 itmax = *n * 3;
|
Chris@25
|
376
|
Chris@25
|
377 /* INITIALIZE THE ARRAYS INDEX() AND X(). */
|
Chris@25
|
378
|
Chris@25
|
379 i__1 = *n;
|
Chris@25
|
380 for (i__ = 1; i__ <= i__1; ++i__) {
|
Chris@25
|
381 x[i__] = 0.;
|
Chris@25
|
382 /* L20: */
|
Chris@25
|
383 index[i__] = i__;
|
Chris@25
|
384 }
|
Chris@25
|
385
|
Chris@25
|
386 iz2 = *n;
|
Chris@25
|
387 iz1 = 1;
|
Chris@25
|
388 nsetp = 0;
|
Chris@25
|
389 npp1 = 1;
|
Chris@25
|
390 /* ****** MAIN LOOP BEGINS HERE ****** */
|
Chris@25
|
391 L30:
|
Chris@25
|
392 /* QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION. */
|
Chris@25
|
393 /* OR IF M COLS OF A HAVE BEEN TRIANGULARIZED. */
|
Chris@25
|
394
|
Chris@25
|
395 if (iz1 > iz2 || nsetp >= *m) {
|
Chris@25
|
396 goto L350;
|
Chris@25
|
397 }
|
Chris@25
|
398
|
Chris@25
|
399 /* COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W(). */
|
Chris@25
|
400
|
Chris@25
|
401 i__1 = iz2;
|
Chris@25
|
402 for (iz = iz1; iz <= i__1; ++iz) {
|
Chris@25
|
403 j = index[iz];
|
Chris@25
|
404 sm = 0.;
|
Chris@25
|
405 i__2 = *m;
|
Chris@25
|
406 for (l = npp1; l <= i__2; ++l) {
|
Chris@25
|
407 /* L40: */
|
Chris@25
|
408 sm += a[l + j * a_dim1] * b[l];
|
Chris@25
|
409 }
|
Chris@25
|
410 w[j] = sm;
|
Chris@25
|
411 /* L50: */
|
Chris@25
|
412 }
|
Chris@25
|
413 /* FIND LARGEST POSITIVE W(J). */
|
Chris@25
|
414 L60:
|
Chris@25
|
415 wmax = 0.;
|
Chris@25
|
416 i__1 = iz2;
|
Chris@25
|
417 for (iz = iz1; iz <= i__1; ++iz) {
|
Chris@25
|
418 j = index[iz];
|
Chris@25
|
419 if (w[j] > wmax) {
|
Chris@25
|
420 wmax = w[j];
|
Chris@25
|
421 izmax = iz;
|
Chris@25
|
422 }
|
Chris@25
|
423 /* L70: */
|
Chris@25
|
424 }
|
Chris@25
|
425
|
Chris@25
|
426 /* IF WMAX .LE. 0. GO TO TERMINATION. */
|
Chris@25
|
427 /* THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS. */
|
Chris@25
|
428
|
Chris@25
|
429 if (wmax <= 0.) {
|
Chris@25
|
430 goto L350;
|
Chris@25
|
431 }
|
Chris@25
|
432 iz = izmax;
|
Chris@25
|
433 j = index[iz];
|
Chris@25
|
434
|
Chris@25
|
435 /* THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P. */
|
Chris@25
|
436 /* BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID */
|
Chris@25
|
437 /* NEAR LINEAR DEPENDENCE. */
|
Chris@25
|
438
|
Chris@25
|
439 asave = a[npp1 + j * a_dim1];
|
Chris@25
|
440 i__1 = npp1 + 1;
|
Chris@25
|
441 h12_(&c__1, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &dummy, &
|
Chris@25
|
442 c__1, &c__1, &c__0);
|
Chris@25
|
443 unorm = 0.;
|
Chris@25
|
444 if (nsetp != 0) {
|
Chris@25
|
445 i__1 = nsetp;
|
Chris@25
|
446 for (l = 1; l <= i__1; ++l) {
|
Chris@25
|
447 /* L90: */
|
Chris@25
|
448 /* Computing 2nd power */
|
Chris@25
|
449 d__1 = a[l + j * a_dim1];
|
Chris@25
|
450 unorm += d__1 * d__1;
|
Chris@25
|
451 }
|
Chris@25
|
452 }
|
Chris@25
|
453 unorm = sqrt(unorm);
|
Chris@25
|
454 d__2 = unorm + (d__1 = a[npp1 + j * a_dim1], abs(d__1)) * .01;
|
Chris@25
|
455 if (diff_(&d__2, &unorm) > 0.) {
|
Chris@25
|
456
|
Chris@25
|
457 /* COL J IS SUFFICIENTLY INDEPENDENT. COPY B INTO ZZ, UPDATE ZZ */
|
Chris@25
|
458 /* AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */
|
Chris@25
|
459
|
Chris@25
|
460 i__1 = *m;
|
Chris@25
|
461 for (l = 1; l <= i__1; ++l) {
|
Chris@25
|
462 /* L120: */
|
Chris@25
|
463 zz[l] = b[l];
|
Chris@25
|
464 }
|
Chris@25
|
465 i__1 = npp1 + 1;
|
Chris@25
|
466 h12_(&c__2, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &zz[1], &
|
Chris@25
|
467 c__1, &c__1, &c__1);
|
Chris@25
|
468 ztest = zz[npp1] / a[npp1 + j * a_dim1];
|
Chris@25
|
469
|
Chris@25
|
470 /* SEE IF ZTEST IS POSITIVE */
|
Chris@25
|
471
|
Chris@25
|
472 if (ztest > 0.) {
|
Chris@25
|
473 goto L140;
|
Chris@25
|
474 }
|
Chris@25
|
475 }
|
Chris@25
|
476
|
Chris@25
|
477 /* REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P. */
|
Chris@25
|
478 /* RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL */
|
Chris@25
|
479 /* COEFFS AGAIN. */
|
Chris@25
|
480
|
Chris@25
|
481 a[npp1 + j * a_dim1] = asave;
|
Chris@25
|
482 w[j] = 0.;
|
Chris@25
|
483 goto L60;
|
Chris@25
|
484
|
Chris@25
|
485 /* THE INDEX J=INDEX(IZ) HAS BEEN SELECTED TO BE MOVED FROM */
|
Chris@25
|
486 /* SET Z TO SET P. UPDATE B, UPDATE INDICES, APPLY HOUSEHOLDER */
|
Chris@25
|
487 /* TRANSFORMATIONS TO COLS IN NEW SET Z, ZERO SUBDIAGONAL ELTS IN */
|
Chris@25
|
488 /* COL J, SET W(J)=0. */
|
Chris@25
|
489
|
Chris@25
|
490 L140:
|
Chris@25
|
491 i__1 = *m;
|
Chris@25
|
492 for (l = 1; l <= i__1; ++l) {
|
Chris@25
|
493 /* L150: */
|
Chris@25
|
494 b[l] = zz[l];
|
Chris@25
|
495 }
|
Chris@25
|
496
|
Chris@25
|
497 index[iz] = index[iz1];
|
Chris@25
|
498 index[iz1] = j;
|
Chris@25
|
499 ++iz1;
|
Chris@25
|
500 nsetp = npp1;
|
Chris@25
|
501 ++npp1;
|
Chris@25
|
502
|
Chris@25
|
503 if (iz1 <= iz2) {
|
Chris@25
|
504 i__1 = iz2;
|
Chris@25
|
505 for (jz = iz1; jz <= i__1; ++jz) {
|
Chris@25
|
506 jj = index[jz];
|
Chris@25
|
507 h12_(&c__2, &nsetp, &npp1, m, &a[j * a_dim1 + 1], &c__1, &up, &a[
|
Chris@25
|
508 jj * a_dim1 + 1], &c__1, mda, &c__1);
|
Chris@25
|
509 /* L160: */
|
Chris@25
|
510 }
|
Chris@25
|
511 }
|
Chris@25
|
512
|
Chris@25
|
513 if (nsetp != *m) {
|
Chris@25
|
514 i__1 = *m;
|
Chris@25
|
515 for (l = npp1; l <= i__1; ++l) {
|
Chris@25
|
516 /* L180: */
|
Chris@25
|
517 a[l + j * a_dim1] = 0.;
|
Chris@25
|
518 }
|
Chris@25
|
519 }
|
Chris@25
|
520
|
Chris@25
|
521 w[j] = 0.;
|
Chris@25
|
522 /* SOLVE THE TRIANGULAR SYSTEM. */
|
Chris@25
|
523 /* STORE THE SOLUTION TEMPORARILY IN ZZ(). */
|
Chris@25
|
524 rtnkey = 1;
|
Chris@25
|
525 goto L400;
|
Chris@25
|
526 L200:
|
Chris@25
|
527
|
Chris@25
|
528 /* ****** SECONDARY LOOP BEGINS HERE ****** */
|
Chris@25
|
529
|
Chris@25
|
530 /* ITERATION COUNTER. */
|
Chris@25
|
531
|
Chris@25
|
532 L210:
|
Chris@25
|
533 ++iter;
|
Chris@25
|
534 if (iter > itmax) {
|
Chris@25
|
535 *mode = 3;
|
Chris@25
|
536 /* write (*,'(/a)') ' NNLS quitting on iteration count.' */
|
Chris@25
|
537 goto L350;
|
Chris@25
|
538 }
|
Chris@25
|
539
|
Chris@25
|
540 /* SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */
|
Chris@25
|
541 /* IF NOT COMPUTE ALPHA. */
|
Chris@25
|
542
|
Chris@25
|
543 alpha = 2.;
|
Chris@25
|
544 i__1 = nsetp;
|
Chris@25
|
545 for (ip = 1; ip <= i__1; ++ip) {
|
Chris@25
|
546 l = index[ip];
|
Chris@25
|
547 if (zz[ip] <= 0.) {
|
Chris@25
|
548 t = -x[l] / (zz[ip] - x[l]);
|
Chris@25
|
549 if (alpha > t) {
|
Chris@25
|
550 alpha = t;
|
Chris@25
|
551 jj = ip;
|
Chris@25
|
552 }
|
Chris@25
|
553 }
|
Chris@25
|
554 /* L240: */
|
Chris@25
|
555 }
|
Chris@25
|
556
|
Chris@25
|
557 /* IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL */
|
Chris@25
|
558 /* STILL = 2. IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP. */
|
Chris@25
|
559
|
Chris@25
|
560 if (alpha == 2.) {
|
Chris@25
|
561 goto L330;
|
Chris@25
|
562 }
|
Chris@25
|
563
|
Chris@25
|
564 /* OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO */
|
Chris@25
|
565 /* INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ. */
|
Chris@25
|
566
|
Chris@25
|
567 i__1 = nsetp;
|
Chris@25
|
568 for (ip = 1; ip <= i__1; ++ip) {
|
Chris@25
|
569 l = index[ip];
|
Chris@25
|
570 x[l] += alpha * (zz[ip] - x[l]);
|
Chris@25
|
571 /* L250: */
|
Chris@25
|
572 }
|
Chris@25
|
573
|
Chris@25
|
574 /* MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I */
|
Chris@25
|
575 /* FROM SET P TO SET Z. */
|
Chris@25
|
576
|
Chris@25
|
577 i__ = index[jj];
|
Chris@25
|
578 L260:
|
Chris@25
|
579 x[i__] = 0.;
|
Chris@25
|
580
|
Chris@25
|
581 if (jj != nsetp) {
|
Chris@25
|
582 ++jj;
|
Chris@25
|
583 i__1 = nsetp;
|
Chris@25
|
584 for (j = jj; j <= i__1; ++j) {
|
Chris@25
|
585 ii = index[j];
|
Chris@25
|
586 index[j - 1] = ii;
|
Chris@25
|
587 g1_(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1], &cc, &ss, &a[j
|
Chris@25
|
588 - 1 + ii * a_dim1]);
|
Chris@25
|
589 a[j + ii * a_dim1] = 0.;
|
Chris@25
|
590 i__2 = *n;
|
Chris@25
|
591 for (l = 1; l <= i__2; ++l) {
|
Chris@25
|
592 if (l != ii) {
|
Chris@25
|
593
|
Chris@25
|
594 /* Apply procedure G2 (CC,SS,A(J-1,L),A(J,L)) */
|
Chris@25
|
595
|
Chris@25
|
596 temp = a[j - 1 + l * a_dim1];
|
Chris@25
|
597 a[j - 1 + l * a_dim1] = cc * temp + ss * a[j + l * a_dim1]
|
Chris@25
|
598 ;
|
Chris@25
|
599 a[j + l * a_dim1] = -ss * temp + cc * a[j + l * a_dim1];
|
Chris@25
|
600 }
|
Chris@25
|
601 /* L270: */
|
Chris@25
|
602 }
|
Chris@25
|
603
|
Chris@25
|
604 /* Apply procedure G2 (CC,SS,B(J-1),B(J)) */
|
Chris@25
|
605
|
Chris@25
|
606 temp = b[j - 1];
|
Chris@25
|
607 b[j - 1] = cc * temp + ss * b[j];
|
Chris@25
|
608 b[j] = -ss * temp + cc * b[j];
|
Chris@25
|
609 /* L280: */
|
Chris@25
|
610 }
|
Chris@25
|
611 }
|
Chris@25
|
612
|
Chris@25
|
613 npp1 = nsetp;
|
Chris@25
|
614 --nsetp;
|
Chris@25
|
615 --iz1;
|
Chris@25
|
616 index[iz1] = i__;
|
Chris@25
|
617
|
Chris@25
|
618 /* SEE IF THE REMAINING COEFFS IN SET P ARE FEASIBLE. THEY SHOULD */
|
Chris@25
|
619 /* BE BECAUSE OF THE WAY ALPHA WAS DETERMINED. */
|
Chris@25
|
620 /* IF ANY ARE INFEASIBLE IT IS DUE TO ROUND-OFF ERROR. ANY */
|
Chris@25
|
621 /* THAT ARE NONPOSITIVE WILL BE SET TO ZERO */
|
Chris@25
|
622 /* AND MOVED FROM SET P TO SET Z. */
|
Chris@25
|
623
|
Chris@25
|
624 i__1 = nsetp;
|
Chris@25
|
625 for (jj = 1; jj <= i__1; ++jj) {
|
Chris@25
|
626 i__ = index[jj];
|
Chris@25
|
627 if (x[i__] <= 0.) {
|
Chris@25
|
628 goto L260;
|
Chris@25
|
629 }
|
Chris@25
|
630 /* L300: */
|
Chris@25
|
631 }
|
Chris@25
|
632
|
Chris@25
|
633 /* COPY B( ) INTO ZZ( ). THEN SOLVE AGAIN AND LOOP BACK. */
|
Chris@25
|
634
|
Chris@25
|
635 i__1 = *m;
|
Chris@25
|
636 for (i__ = 1; i__ <= i__1; ++i__) {
|
Chris@25
|
637 /* L310: */
|
Chris@25
|
638 zz[i__] = b[i__];
|
Chris@25
|
639 }
|
Chris@25
|
640 rtnkey = 2;
|
Chris@25
|
641 goto L400;
|
Chris@25
|
642 L320:
|
Chris@25
|
643 goto L210;
|
Chris@25
|
644 /* ****** END OF SECONDARY LOOP ****** */
|
Chris@25
|
645
|
Chris@25
|
646 L330:
|
Chris@25
|
647 i__1 = nsetp;
|
Chris@25
|
648 for (ip = 1; ip <= i__1; ++ip) {
|
Chris@25
|
649 i__ = index[ip];
|
Chris@25
|
650 /* L340: */
|
Chris@25
|
651 x[i__] = zz[ip];
|
Chris@25
|
652 }
|
Chris@25
|
653 /* ALL NEW COEFFS ARE POSITIVE. LOOP BACK TO BEGINNING. */
|
Chris@25
|
654 goto L30;
|
Chris@25
|
655
|
Chris@25
|
656 /* ****** END OF MAIN LOOP ****** */
|
Chris@25
|
657
|
Chris@25
|
658 /* COME TO HERE FOR TERMINATION. */
|
Chris@25
|
659 /* COMPUTE THE NORM OF THE FINAL RESIDUAL VECTOR. */
|
Chris@25
|
660
|
Chris@25
|
661 L350:
|
Chris@25
|
662 sm = 0.;
|
Chris@25
|
663 if (npp1 <= *m) {
|
Chris@25
|
664 i__1 = *m;
|
Chris@25
|
665 for (i__ = npp1; i__ <= i__1; ++i__) {
|
Chris@25
|
666 /* L360: */
|
Chris@25
|
667 /* Computing 2nd power */
|
Chris@25
|
668 d__1 = b[i__];
|
Chris@25
|
669 sm += d__1 * d__1;
|
Chris@25
|
670 }
|
Chris@25
|
671 } else {
|
Chris@25
|
672 i__1 = *n;
|
Chris@25
|
673 for (j = 1; j <= i__1; ++j) {
|
Chris@25
|
674 /* L380: */
|
Chris@25
|
675 w[j] = 0.;
|
Chris@25
|
676 }
|
Chris@25
|
677 }
|
Chris@25
|
678 *rnorm = sqrt(sm);
|
Chris@25
|
679 return 0;
|
Chris@25
|
680
|
Chris@25
|
681 /* THE FOLLOWING BLOCK OF CODE IS USED AS AN INTERNAL SUBROUTINE */
|
Chris@25
|
682 /* TO SOLVE THE TRIANGULAR SYSTEM, PUTTING THE SOLUTION IN ZZ(). */
|
Chris@25
|
683
|
Chris@25
|
684 L400:
|
Chris@25
|
685 i__1 = nsetp;
|
Chris@25
|
686 for (l = 1; l <= i__1; ++l) {
|
Chris@25
|
687 ip = nsetp + 1 - l;
|
Chris@25
|
688 if (l != 1) {
|
Chris@25
|
689 i__2 = ip;
|
Chris@25
|
690 for (ii = 1; ii <= i__2; ++ii) {
|
Chris@25
|
691 zz[ii] -= a[ii + jj * a_dim1] * zz[ip + 1];
|
Chris@25
|
692 /* L410: */
|
Chris@25
|
693 }
|
Chris@25
|
694 }
|
Chris@25
|
695 jj = index[ip];
|
Chris@25
|
696 zz[ip] /= a[ip + jj * a_dim1];
|
Chris@25
|
697 /* L430: */
|
Chris@25
|
698 }
|
Chris@25
|
699 switch (rtnkey) {
|
Chris@25
|
700 case 1: goto L200;
|
Chris@25
|
701 case 2: goto L320;
|
Chris@25
|
702 }
|
Chris@25
|
703 return 0;
|
Chris@25
|
704 } /* nnls_ */
|
Chris@25
|
705
|