annotate nnls.c @ 144:0d70058c2bce

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