Mercurial > hg > nnls-chroma
changeset 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 | 568ff0daa659 |
children | 906d3705536d |
files | Makefile.cc-linux nnls.c nnls.f nnls.h |
diffstat | 4 files changed, 711 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile.cc-linux Thu Oct 21 12:21:41 2010 +0100 +++ b/Makefile.cc-linux Thu Oct 21 14:38:02 2010 +0100 @@ -48,6 +48,7 @@ ## Uncomment these for Linux using the standard tools: +CFLAGS = -I$(VAMP_SDK_DIR) -I$(LAPACK_DIR) -I$(FFT_DIR) -I$(NNLS_DIR) -Wall -fPIC CXXFLAGS = -I$(VAMP_SDK_DIR) -I$(LAPACK_DIR) -I$(FFT_DIR) -I$(NNLS_DIR) -Wall -fPIC PLUGIN_EXT = .so PLUGIN = $(PLUGIN_LIBRARY_NAME)$(PLUGIN_EXT) @@ -79,9 +80,6 @@ $(PLUGIN): $(PLUGIN_CODE_OBJECTS) $(CXX) -o $@ $^ $(LDFLAGS) -nnls.o: nnls.f - gfortran -std=legacy -fPIC -Wall -c $< - clean: rm -f *.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nnls.c Thu Oct 21 14:38:02 2010 +0100 @@ -0,0 +1,705 @@ + +#include "nnls.h" + +typedef int integer; +typedef unsigned int uinteger; +typedef char *address; +typedef short int shortint; +typedef float real; +typedef double doublereal; + +#define abs(x) ((x) >= 0 ? (x) : -(x)) +#define dabs(x) (doublereal)abs(x) +#define min(a,b) ((a) <= (b) ? (a) : (b)) +#define max(a,b) ((a) >= (b) ? (a) : (b)) +#define dmin(a,b) (doublereal)min(a,b) +#define dmax(a,b) (doublereal)max(a,b) +#define bit_test(a,b) ((a) >> (b) & 1) +#define bit_clear(a,b) ((a) & ~((uinteger)1 << (b))) +#define bit_set(a,b) ((a) | ((uinteger)1 << (b))) + +double d_sign(doublereal *a, doublereal *b) +{ + double x; + x = (*a >= 0 ? *a : - *a); + return (*b >= 0 ? x : -x); +} + +/* Table of constant values */ + +static integer c__1 = 1; +static integer c__0 = 0; +static integer c__2 = 2; + +doublereal diff_(doublereal *x, doublereal *y) +{ + /* System generated locals */ + doublereal ret_val; + + +/* Function used in tests that depend on machine precision. */ + +/* The original version of this code was developed by */ +/* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */ +/* 1973 JUN 7, and published in the book */ +/* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */ +/* Revised FEB 1995 to accompany reprinting of the book by SIAM. */ + + ret_val = *x - *y; + return ret_val; +} /* diff_ */ + +/* Subroutine */ int g1_(doublereal *a, doublereal *b, doublereal *cterm, + doublereal *sterm, doublereal *sig) +{ + /* System generated locals */ + doublereal d__1; + + /* Builtin functions */ + double sqrt(doublereal), d_sign(doublereal *, doublereal *); + + /* Local variables */ + static doublereal xr, yr; + + +/* COMPUTE ORTHOGONAL ROTATION MATRIX.. */ + +/* The original version of this code was developed by */ +/* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */ +/* 1973 JUN 12, and published in the book */ +/* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */ +/* Revised FEB 1995 to accompany reprinting of the book by SIAM. */ + +/* COMPUTE.. MATRIX (C, S) SO THAT (C, S)(A) = (SQRT(A**2+B**2)) */ +/* (-S,C) (-S,C)(B) ( 0 ) */ +/* COMPUTE SIG = SQRT(A**2+B**2) */ +/* SIG IS COMPUTED LAST TO ALLOW FOR THE POSSIBILITY THAT */ +/* SIG MAY BE IN THE SAME LOCATION AS A OR B . */ +/* ------------------------------------------------------------------ */ +/* ------------------------------------------------------------------ */ + if (abs(*a) > abs(*b)) { + xr = *b / *a; +/* Computing 2nd power */ + d__1 = xr; + yr = sqrt(d__1 * d__1 + 1.); + d__1 = 1. / yr; + *cterm = d_sign(&d__1, a); + *sterm = *cterm * xr; + *sig = abs(*a) * yr; + return 0; + } + if (*b != 0.) { + xr = *a / *b; +/* Computing 2nd power */ + d__1 = xr; + yr = sqrt(d__1 * d__1 + 1.); + d__1 = 1. / yr; + *sterm = d_sign(&d__1, b); + *cterm = *sterm * xr; + *sig = abs(*b) * yr; + return 0; + } + *sig = 0.; + *cterm = 0.; + *sterm = 1.; + return 0; +} /* g1_ */ + +/* SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV) */ + +/* CONSTRUCTION AND/OR APPLICATION OF A SINGLE */ +/* HOUSEHOLDER TRANSFORMATION.. Q = I + U*(U**T)/B */ + +/* The original version of this code was developed by */ +/* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */ +/* 1973 JUN 12, and published in the book */ +/* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */ +/* Revised FEB 1995 to accompany reprinting of the book by SIAM. */ +/* ------------------------------------------------------------------ */ +/* Subroutine Arguments */ + +/* MODE = 1 OR 2 Selects Algorithm H1 to construct and apply a */ +/* Householder transformation, or Algorithm H2 to apply a */ +/* previously constructed transformation. */ +/* LPIVOT IS THE INDEX OF THE PIVOT ELEMENT. */ +/* L1,M IF L1 .LE. M THE TRANSFORMATION WILL BE CONSTRUCTED TO */ +/* ZERO ELEMENTS INDEXED FROM L1 THROUGH M. IF L1 GT. M */ +/* THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION. */ +/* U(),IUE,UP On entry with MODE = 1, U() contains the pivot */ +/* vector. IUE is the storage increment between elements. */ +/* On exit when MODE = 1, U() and UP contain quantities */ +/* defining the vector U of the Householder transformation. */ +/* on entry with MODE = 2, U() and UP should contain */ +/* quantities previously computed with MODE = 1. These will */ +/* not be modified during the entry with MODE = 2. */ +/* C() ON ENTRY with MODE = 1 or 2, C() CONTAINS A MATRIX WHICH */ +/* WILL BE REGARDED AS A SET OF VECTORS TO WHICH THE */ +/* HOUSEHOLDER TRANSFORMATION IS TO BE APPLIED. */ +/* ON EXIT C() CONTAINS THE SET OF TRANSFORMED VECTORS. */ +/* ICE STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C(). */ +/* ICV STORAGE INCREMENT BETWEEN VECTORS IN C(). */ +/* NCV NUMBER OF VECTORS IN C() TO BE TRANSFORMED. IF NCV .LE. 0 */ +/* NO OPERATIONS WILL BE DONE ON C(). */ +/* ------------------------------------------------------------------ */ +/* Subroutine */ int h12_(integer *mode, integer *lpivot, integer *l1, + integer *m, doublereal *u, integer *iue, doublereal *up, doublereal * + c__, integer *ice, integer *icv, integer *ncv) +{ + /* System generated locals */ + integer u_dim1, u_offset, i__1, i__2; + doublereal d__1, d__2; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + static doublereal b; + static integer i__, j, i2, i3, i4; + static doublereal cl, sm; + static integer incr; + static doublereal clinv; + +/* ------------------------------------------------------------------ */ +/* double precision U(IUE,M) */ +/* ------------------------------------------------------------------ */ + /* Parameter adjustments */ + u_dim1 = *iue; + u_offset = 1 + u_dim1; + u -= u_offset; + --c__; + + /* Function Body */ + if (0 >= *lpivot || *lpivot >= *l1 || *l1 > *m) { + return 0; + } + cl = (d__1 = u[*lpivot * u_dim1 + 1], abs(d__1)); + if (*mode == 2) { + goto L60; + } +/* ****** CONSTRUCT THE TRANSFORMATION. ****** */ + i__1 = *m; + for (j = *l1; j <= i__1; ++j) { +/* L10: */ +/* Computing MAX */ + d__2 = (d__1 = u[j * u_dim1 + 1], abs(d__1)); + cl = max(d__2,cl); + } + if (cl <= 0.) { + goto L130; + } else { + goto L20; + } +L20: + clinv = 1. / cl; +/* Computing 2nd power */ + d__1 = u[*lpivot * u_dim1 + 1] * clinv; + sm = d__1 * d__1; + i__1 = *m; + for (j = *l1; j <= i__1; ++j) { +/* L30: */ +/* Computing 2nd power */ + d__1 = u[j * u_dim1 + 1] * clinv; + sm += d__1 * d__1; + } + cl *= sqrt(sm); + if (u[*lpivot * u_dim1 + 1] <= 0.) { + goto L50; + } else { + goto L40; + } +L40: + cl = -cl; +L50: + *up = u[*lpivot * u_dim1 + 1] - cl; + u[*lpivot * u_dim1 + 1] = cl; + goto L70; +/* ****** APPLY THE TRANSFORMATION I+U*(U**T)/B TO C. ****** */ + +L60: + if (cl <= 0.) { + goto L130; + } else { + goto L70; + } +L70: + if (*ncv <= 0) { + return 0; + } + b = *up * u[*lpivot * u_dim1 + 1]; +/* B MUST BE NONPOSITIVE HERE. IF B = 0., RETURN. */ + + if (b >= 0.) { + goto L130; + } else { + goto L80; + } +L80: + b = 1. / b; + i2 = 1 - *icv + *ice * (*lpivot - 1); + incr = *ice * (*l1 - *lpivot); + i__1 = *ncv; + for (j = 1; j <= i__1; ++j) { + i2 += *icv; + i3 = i2 + incr; + i4 = i3; + sm = c__[i2] * *up; + i__2 = *m; + for (i__ = *l1; i__ <= i__2; ++i__) { + sm += c__[i3] * u[i__ * u_dim1 + 1]; +/* L90: */ + i3 += *ice; + } + if (sm != 0.) { + goto L100; + } else { + goto L120; + } +L100: + sm *= b; + c__[i2] += sm * *up; + i__2 = *m; + for (i__ = *l1; i__ <= i__2; ++i__) { + c__[i4] += sm * u[i__ * u_dim1 + 1]; +/* L110: */ + i4 += *ice; + } +L120: + ; + } +L130: + return 0; +} /* h12_ */ + +/* SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE) */ + +/* Algorithm NNLS: NONNEGATIVE LEAST SQUARES */ + +/* The original version of this code was developed by */ +/* Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory */ +/* 1973 JUN 15, and published in the book */ +/* "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974. */ +/* Revised FEB 1995 to accompany reprinting of the book by SIAM. */ + +/* GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B, COMPUTE AN */ +/* N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM */ + +/* A * X = B SUBJECT TO X .GE. 0 */ +/* ------------------------------------------------------------------ */ +/* Subroutine Arguments */ + +/* A(),MDA,M,N MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE */ +/* ARRAY, A(). ON ENTRY A() CONTAINS THE M BY N */ +/* MATRIX, A. ON EXIT A() CONTAINS */ +/* THE PRODUCT MATRIX, Q*A , WHERE Q IS AN */ +/* M BY M ORTHOGONAL MATRIX GENERATED IMPLICITLY BY */ +/* THIS SUBROUTINE. */ +/* B() ON ENTRY B() CONTAINS THE M-VECTOR, B. ON EXIT B() CON- */ +/* TAINS Q*B. */ +/* X() ON ENTRY X() NEED NOT BE INITIALIZED. ON EXIT X() WILL */ +/* CONTAIN THE SOLUTION VECTOR. */ +/* RNORM ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE */ +/* RESIDUAL VECTOR. */ +/* W() AN N-ARRAY OF WORKING SPACE. ON EXIT W() WILL CONTAIN */ +/* THE DUAL SOLUTION VECTOR. W WILL SATISFY W(I) = 0. */ +/* FOR ALL I IN SET P AND W(I) .LE. 0. FOR ALL I IN SET Z */ +/* ZZ() AN M-ARRAY OF WORKING SPACE. */ +/* INDEX() AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N. */ +/* ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS */ +/* P AND Z AS FOLLOWS.. */ + +/* INDEX(1) THRU INDEX(NSETP) = SET P. */ +/* INDEX(IZ1) THRU INDEX(IZ2) = SET Z. */ +/* IZ1 = NSETP + 1 = NPP1 */ +/* IZ2 = N */ +/* MODE THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING */ +/* MEANINGS. */ +/* 1 THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY. */ +/* 2 THE DIMENSIONS OF THE PROBLEM ARE BAD. */ +/* EITHER M .LE. 0 OR N .LE. 0. */ +/* 3 ITERATION COUNT EXCEEDED. MORE THAN 3*N ITERATIONS. */ + +/* ------------------------------------------------------------------ */ +/* Subroutine */ int nnls_(doublereal *a, integer *mda, integer *m, integer * + n, doublereal *b, doublereal *x, doublereal *rnorm, doublereal *w, + doublereal *zz, integer *index, integer *mode) +{ + /* System generated locals */ + integer a_dim1, a_offset, i__1, i__2; + doublereal d__1, d__2; + + /* Builtin functions */ + double sqrt(doublereal); + + /* Local variables */ + static integer i__, j, l; + static doublereal t; + extern /* Subroutine */ int g1_(doublereal *, doublereal *, doublereal *, + doublereal *, doublereal *); + static doublereal cc; + extern /* Subroutine */ int h12_(integer *, integer *, integer *, integer + *, doublereal *, integer *, doublereal *, doublereal *, integer *, + integer *, integer *); + static integer ii, jj, ip; + static doublereal sm; + static integer iz, jz; + static doublereal up, ss; + static integer iz1, iz2, npp1; + extern doublereal diff_(doublereal *, doublereal *); + static integer iter; + static doublereal temp, wmax, alpha, asave; + static integer itmax, izmax, nsetp; + static doublereal dummy, unorm, ztest; + static integer rtnkey; + +/* ------------------------------------------------------------------ */ +/* integer INDEX(N) */ +/* double precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */ +/* ------------------------------------------------------------------ */ + /* Parameter adjustments */ + a_dim1 = *mda; + a_offset = 1 + a_dim1; + a -= a_offset; + --b; + --x; + --w; + --zz; + --index; + + /* Function Body */ + *mode = 1; + if (*m <= 0 || *n <= 0) { + *mode = 2; + return 0; + } + iter = 0; + itmax = *n * 3; + +/* INITIALIZE THE ARRAYS INDEX() AND X(). */ + + i__1 = *n; + for (i__ = 1; i__ <= i__1; ++i__) { + x[i__] = 0.; +/* L20: */ + index[i__] = i__; + } + + iz2 = *n; + iz1 = 1; + nsetp = 0; + npp1 = 1; +/* ****** MAIN LOOP BEGINS HERE ****** */ +L30: +/* QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION. */ +/* OR IF M COLS OF A HAVE BEEN TRIANGULARIZED. */ + + if (iz1 > iz2 || nsetp >= *m) { + goto L350; + } + +/* COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W(). */ + + i__1 = iz2; + for (iz = iz1; iz <= i__1; ++iz) { + j = index[iz]; + sm = 0.; + i__2 = *m; + for (l = npp1; l <= i__2; ++l) { +/* L40: */ + sm += a[l + j * a_dim1] * b[l]; + } + w[j] = sm; +/* L50: */ + } +/* FIND LARGEST POSITIVE W(J). */ +L60: + wmax = 0.; + i__1 = iz2; + for (iz = iz1; iz <= i__1; ++iz) { + j = index[iz]; + if (w[j] > wmax) { + wmax = w[j]; + izmax = iz; + } +/* L70: */ + } + +/* IF WMAX .LE. 0. GO TO TERMINATION. */ +/* THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS. */ + + if (wmax <= 0.) { + goto L350; + } + iz = izmax; + j = index[iz]; + +/* THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P. */ +/* BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID */ +/* NEAR LINEAR DEPENDENCE. */ + + asave = a[npp1 + j * a_dim1]; + i__1 = npp1 + 1; + h12_(&c__1, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &dummy, & + c__1, &c__1, &c__0); + unorm = 0.; + if (nsetp != 0) { + i__1 = nsetp; + for (l = 1; l <= i__1; ++l) { +/* L90: */ +/* Computing 2nd power */ + d__1 = a[l + j * a_dim1]; + unorm += d__1 * d__1; + } + } + unorm = sqrt(unorm); + d__2 = unorm + (d__1 = a[npp1 + j * a_dim1], abs(d__1)) * .01; + if (diff_(&d__2, &unorm) > 0.) { + +/* COL J IS SUFFICIENTLY INDEPENDENT. COPY B INTO ZZ, UPDATE ZZ */ +/* AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */ + + i__1 = *m; + for (l = 1; l <= i__1; ++l) { +/* L120: */ + zz[l] = b[l]; + } + i__1 = npp1 + 1; + h12_(&c__2, &npp1, &i__1, m, &a[j * a_dim1 + 1], &c__1, &up, &zz[1], & + c__1, &c__1, &c__1); + ztest = zz[npp1] / a[npp1 + j * a_dim1]; + +/* SEE IF ZTEST IS POSITIVE */ + + if (ztest > 0.) { + goto L140; + } + } + +/* REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P. */ +/* RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL */ +/* COEFFS AGAIN. */ + + a[npp1 + j * a_dim1] = asave; + w[j] = 0.; + goto L60; + +/* THE INDEX J=INDEX(IZ) HAS BEEN SELECTED TO BE MOVED FROM */ +/* SET Z TO SET P. UPDATE B, UPDATE INDICES, APPLY HOUSEHOLDER */ +/* TRANSFORMATIONS TO COLS IN NEW SET Z, ZERO SUBDIAGONAL ELTS IN */ +/* COL J, SET W(J)=0. */ + +L140: + i__1 = *m; + for (l = 1; l <= i__1; ++l) { +/* L150: */ + b[l] = zz[l]; + } + + index[iz] = index[iz1]; + index[iz1] = j; + ++iz1; + nsetp = npp1; + ++npp1; + + if (iz1 <= iz2) { + i__1 = iz2; + for (jz = iz1; jz <= i__1; ++jz) { + jj = index[jz]; + h12_(&c__2, &nsetp, &npp1, m, &a[j * a_dim1 + 1], &c__1, &up, &a[ + jj * a_dim1 + 1], &c__1, mda, &c__1); +/* L160: */ + } + } + + if (nsetp != *m) { + i__1 = *m; + for (l = npp1; l <= i__1; ++l) { +/* L180: */ + a[l + j * a_dim1] = 0.; + } + } + + w[j] = 0.; +/* SOLVE THE TRIANGULAR SYSTEM. */ +/* STORE THE SOLUTION TEMPORARILY IN ZZ(). */ + rtnkey = 1; + goto L400; +L200: + +/* ****** SECONDARY LOOP BEGINS HERE ****** */ + +/* ITERATION COUNTER. */ + +L210: + ++iter; + if (iter > itmax) { + *mode = 3; +/* write (*,'(/a)') ' NNLS quitting on iteration count.' */ + goto L350; + } + +/* SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */ +/* IF NOT COMPUTE ALPHA. */ + + alpha = 2.; + i__1 = nsetp; + for (ip = 1; ip <= i__1; ++ip) { + l = index[ip]; + if (zz[ip] <= 0.) { + t = -x[l] / (zz[ip] - x[l]); + if (alpha > t) { + alpha = t; + jj = ip; + } + } +/* L240: */ + } + +/* IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL */ +/* STILL = 2. IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP. */ + + if (alpha == 2.) { + goto L330; + } + +/* OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO */ +/* INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ. */ + + i__1 = nsetp; + for (ip = 1; ip <= i__1; ++ip) { + l = index[ip]; + x[l] += alpha * (zz[ip] - x[l]); +/* L250: */ + } + +/* MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I */ +/* FROM SET P TO SET Z. */ + + i__ = index[jj]; +L260: + x[i__] = 0.; + + if (jj != nsetp) { + ++jj; + i__1 = nsetp; + for (j = jj; j <= i__1; ++j) { + ii = index[j]; + index[j - 1] = ii; + g1_(&a[j - 1 + ii * a_dim1], &a[j + ii * a_dim1], &cc, &ss, &a[j + - 1 + ii * a_dim1]); + a[j + ii * a_dim1] = 0.; + i__2 = *n; + for (l = 1; l <= i__2; ++l) { + if (l != ii) { + +/* Apply procedure G2 (CC,SS,A(J-1,L),A(J,L)) */ + + temp = a[j - 1 + l * a_dim1]; + a[j - 1 + l * a_dim1] = cc * temp + ss * a[j + l * a_dim1] + ; + a[j + l * a_dim1] = -ss * temp + cc * a[j + l * a_dim1]; + } +/* L270: */ + } + +/* Apply procedure G2 (CC,SS,B(J-1),B(J)) */ + + temp = b[j - 1]; + b[j - 1] = cc * temp + ss * b[j]; + b[j] = -ss * temp + cc * b[j]; +/* L280: */ + } + } + + npp1 = nsetp; + --nsetp; + --iz1; + index[iz1] = i__; + +/* SEE IF THE REMAINING COEFFS IN SET P ARE FEASIBLE. THEY SHOULD */ +/* BE BECAUSE OF THE WAY ALPHA WAS DETERMINED. */ +/* IF ANY ARE INFEASIBLE IT IS DUE TO ROUND-OFF ERROR. ANY */ +/* THAT ARE NONPOSITIVE WILL BE SET TO ZERO */ +/* AND MOVED FROM SET P TO SET Z. */ + + i__1 = nsetp; + for (jj = 1; jj <= i__1; ++jj) { + i__ = index[jj]; + if (x[i__] <= 0.) { + goto L260; + } +/* L300: */ + } + +/* COPY B( ) INTO ZZ( ). THEN SOLVE AGAIN AND LOOP BACK. */ + + i__1 = *m; + for (i__ = 1; i__ <= i__1; ++i__) { +/* L310: */ + zz[i__] = b[i__]; + } + rtnkey = 2; + goto L400; +L320: + goto L210; +/* ****** END OF SECONDARY LOOP ****** */ + +L330: + i__1 = nsetp; + for (ip = 1; ip <= i__1; ++ip) { + i__ = index[ip]; +/* L340: */ + x[i__] = zz[ip]; + } +/* ALL NEW COEFFS ARE POSITIVE. LOOP BACK TO BEGINNING. */ + goto L30; + +/* ****** END OF MAIN LOOP ****** */ + +/* COME TO HERE FOR TERMINATION. */ +/* COMPUTE THE NORM OF THE FINAL RESIDUAL VECTOR. */ + +L350: + sm = 0.; + if (npp1 <= *m) { + i__1 = *m; + for (i__ = npp1; i__ <= i__1; ++i__) { +/* L360: */ +/* Computing 2nd power */ + d__1 = b[i__]; + sm += d__1 * d__1; + } + } else { + i__1 = *n; + for (j = 1; j <= i__1; ++j) { +/* L380: */ + w[j] = 0.; + } + } + *rnorm = sqrt(sm); + return 0; + +/* THE FOLLOWING BLOCK OF CODE IS USED AS AN INTERNAL SUBROUTINE */ +/* TO SOLVE THE TRIANGULAR SYSTEM, PUTTING THE SOLUTION IN ZZ(). */ + +L400: + i__1 = nsetp; + for (l = 1; l <= i__1; ++l) { + ip = nsetp + 1 - l; + if (l != 1) { + i__2 = ip; + for (ii = 1; ii <= i__2; ++ii) { + zz[ii] -= a[ii + jj * a_dim1] * zz[ip + 1]; +/* L410: */ + } + } + jj = index[ip]; + zz[ip] /= a[ip + jj * a_dim1]; +/* L430: */ + } + switch (rtnkey) { + case 1: goto L200; + case 2: goto L320; + } + return 0; +} /* nnls_ */ +
--- a/nnls.f Thu Oct 21 12:21:41 2010 +0100 +++ b/nnls.f Thu Oct 21 14:38:02 2010 +0100 @@ -345,7 +345,7 @@ ITER=ITER+1 IF (ITER .gt. ITMAX) then MODE=3 - write (*,'(/a)') ' NNLS quitting on iteration count.' +c write (*,'(/a)') ' NNLS quitting on iteration count.' GO TO 350 endif C
--- a/nnls.h Thu Oct 21 12:21:41 2010 +0100 +++ b/nnls.h Thu Oct 21 14:38:02 2010 +0100 @@ -1,7 +1,9 @@ #ifndef NNLS_H #define NNLS_H +#ifdef __cplusplus extern "C" { +#endif int nnls_(double *a, int *mda, int *m, int *n, double *b, double *x, double *rnorm, @@ -9,7 +11,9 @@ #define NNLS nnls_ +#ifdef __cplusplus } +#endif #endif