annotate nnls.cc @ 5:ec9fcfe1ce9e matthiasm-plugin

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