comparison nnls.c @ 25:6d9e1ee7b35a matthiasm-plugin

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