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