annotate nnls.cc @ 13:9ae90fa5fa74 matthiasm-plugin

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