annotate nnls.cpp @ 2:957e1fde20df matthiasm-plugin

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