annotate nnls.c @ 184:82d5d11b68d7 tip

Update library URI so it's not document-local
author Chris Cannam
date Wed, 22 Apr 2020 14:21:25 +0100
parents 259ef0f4622b
children
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@176 215 int itmax, izmax = 0, 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