annotate 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
rev   line source
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