changeset 22:444c344681f3 matthiasm-plugin

* Rather than worry about provenance of C versions, why not just use the FORTRAN? (We can back this out if it doesn't go well with the build scripts)
author Chris Cannam
date Thu, 21 Oct 2010 11:58:28 +0100
parents 1e2d0db15920
children 93c836cfb8c5
files Makefile.cc-linux NNLSChroma.cpp nnls.cc nnls.cpp nnls.f nnls.h
diffstat 6 files changed, 497 insertions(+), 1335 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.cc-linux	Mon Oct 18 09:35:26 2010 +0000
+++ b/Makefile.cc-linux	Thu Oct 21 11:58:28 2010 +0100
@@ -31,7 +31,6 @@
 NNLS_DIR = ../tsnnls/tsnnls
 
 
-
 ##  Uncomment these for an OS/X native build using command-line tools:
 #CXXFLAGS = -I$(VAMP_SDK_DIR) -I$(LAPACK_DIR) -I$(FFT_DIR) -I$(NNLS_DIR) -Wall -fPIC -g
 #PLUGIN_EXT = .dylib
@@ -80,6 +79,9 @@
 $(PLUGIN): $(PLUGIN_CODE_OBJECTS)
 	   $(CXX) -o $@ $^ $(LDFLAGS)
 
+nnls.o:	 nnls.f
+	 gfortran -std=legacy -fPIC -Wall -c $< 
+
 clean:
 	rm -f *.o
 
--- a/NNLSChroma.cpp	Mon Oct 18 09:35:26 2010 +0000
+++ b/NNLSChroma.cpp	Thu Oct 21 11:58:28 2010 +0100
@@ -1199,7 +1199,7 @@
 	        f6.hasTimestamp = true;
 	        f6.timestamp = f2.timestamp;
 	        
-			float b[256];
+			double b[256];
 	
 	        bool some_b_greater_zero = false;
 			float sumb = 0;
@@ -1233,7 +1233,7 @@
 					}
 		        
 				} else {
-					float x[84+1000];
+				    double x[84+1000];
 					for (int i = 1; i < 1084; ++i) x[i] = 1.0;
                     vector<int> signifIndex;
                     int index=0;
@@ -1247,20 +1247,22 @@
                         f3.values.push_back(0); // fill the values, change later
                         index++;
 					}
-				    float rnorm;
-				    float w[84+1000];
-				    float zz[84+1000];
+				    double rnorm;
+				    double w[84+1000];
+				    double zz[84+1000];
 				    int indx[84+1000];
 				    int mode;
                     int dictsize = 256*signifIndex.size();
                     // cerr << "dictsize is " << dictsize << "and values size" << f3.values.size()<< endl;
-					float *curr_dict = new float[dictsize];
+		    double *curr_dict = new double[dictsize];
 					for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
                         for (unsigned iBin = 0; iBin < 256; iBin++) {
     						curr_dict[iNote * 256 + iBin] = 1.0 * m_dict[signifIndex[iNote] * 256 + iBin];
                         }
 					}
-					nnls(curr_dict, nNote, nNote, signifIndex.size(), b, x, &rnorm, w, zz, indx, &mode);
+					int sz = signifIndex.size();
+					int nn = nNote;
+					NNLS(curr_dict, &nn, &nn, &sz, b, x, &rnorm, w, zz, indx, &mode);
                     delete [] curr_dict;
 					for (unsigned iNote = 0; iNote < signifIndex.size(); ++iNote) {
 						f3.values[signifIndex[iNote]] = x[iNote];
--- a/nnls.cc	Mon Oct 18 09:35:26 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,591 +0,0 @@
-//      $Id: nnls.cc,v 1.1.1.1 2003/04/02 22:06:19 suvrit Exp $
-// File: nnls.cc
-// Implements the Lawson-Hanson NNLS algorithm
-
-#include "nnls.h"
-
-float d_sign(float& a, float& b)
-{
-  float x;
-  x = (a >= 0 ? a : - a);
-  return (b >= 0 ? x : -x);
-}
-
-/* Table of constant values */
-
-int c__1 = 1;
-int c__0 = 0;
-int c__2 = 2;
-
-
-int nnls(float* a,  int mda,  int m,  int n, float* b,
-         float* x, float* rnorm, float* w, float* zz, int* index,
-         int* mode)
-{
-  /* System generated locals */
-  int a_dim1, a_offset, idx1, idx2;
-  float d1, d2;
-
-
-  /* Local variables */
-  static int iter;
-  static float temp, wmax;
-  static int i__, j, l;
-  static float t, alpha, asave;
-  static int itmax, izmax, nsetp;
-  static float unorm, ztest, cc;
-  float dummy[2];
-  static int ii, jj, ip;
-  static float sm;
-  static int iz, jz;
-  static float up, ss;
-  static int rtnkey, iz1, iz2, npp1;
-
-  /*     ------------------------------------------------------------------
-   */
-  /*     int INDEX(N) */
-  /*     float precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */
-  /*     ------------------------------------------------------------------
-   */
-  /* Parameter adjustments */
-  a_dim1 = mda;
-  a_offset = a_dim1 + 1;
-  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(). */
-
-  idx1 = n;
-  for (i__ = 1; i__ <= idx1; ++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().
-   */
-
-  idx1 = iz2;
-  for (iz = iz1; iz <= idx1; ++iz) {
-    j = index[iz];
-    sm = 0.;
-    idx2 = m;
-    for (l = npp1; l <= idx2; ++l) {
-      /* L40: */
-      sm += a[l + j * a_dim1] * b[l];
-    }
-    w[j] = sm;
-    /* L50: */
-  }
-  /*                                   FIND LARGEST POSITIVE W(J). */
- L60:
-  wmax = 0.;
-  idx1 = iz2;
-  for (iz = iz1; iz <= idx1; ++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];
-  idx1 = npp1 + 1;
-  h12(c__1, &npp1, &idx1, m, &a[j * a_dim1 + 1], &c__1, &up, dummy, &
-      c__1, &c__1, &c__0);
-  unorm = 0.;
-  if (nsetp != 0) {
-    idx1 = nsetp;
-    for (l = 1; l <= idx1; ++l) {
-      /* L90: */
-      /* Computing 2nd power */
-      d1 = a[l + j * a_dim1];
-      unorm += d1 * d1;
-    }
-  }
-  unorm = sqrt(unorm);
-  d2 = unorm + (d1 = a[npp1 + j * a_dim1], nnls_abs(d1)) * .01;
-  if ((d2- unorm) > 0.) {
-
-    /*        COL J IS SUFFICIENTLY INDEPENDENT.  COPY B INTO ZZ, UPDATE Z
-              Z */
-    /*        AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */
-
-    idx1 = m;
-    for (l = 1; l <= idx1; ++l) {
-      /* L120: */
-      zz[l] = b[l];
-    }
-    idx1 = npp1 + 1;
-    h12(c__2, &npp1, &idx1, 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:
-  idx1 = m;
-  for (l = 1; l <= idx1; ++l) {
-    /* L150: */
-    b[l] = zz[l];
-  }
-
-  index[iz] = index[iz1];
-  index[iz1] = j;
-  ++iz1;
-  nsetp = npp1;
-  ++npp1;
-
-  if (iz1 <= iz2) {
-    idx1 = iz2;
-    for (jz = iz1; jz <= idx1; ++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) {
-    idx1 = m;
-    for (l = npp1; l <= idx1; ++l) {
-      /* L180: */
-      // SS: CHECK THIS DAMAGE....
-      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;
-    /* The following lines were replaced after the f2c translation */
-    /* s_wsfe(&io___22); */
-    /* do_fio(&c__1, " NNLS quitting on iteration count.", 34L); */
-    /* e_wsfe(); */
-    fprintf(stdout, "\n NNLS quitting on iteration count.\n");
-    fflush(stdout);
-    goto L350;
-  }
-
-  /*                    SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */
-  /*                                  IF NOT COMPUTE ALPHA. */
-
-  alpha = 2.;
-  idx1 = nsetp;
-  for (ip = 1; ip <= idx1; ++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. */
-
-  idx1 = nsetp;
-  for (ip = 1; ip <= idx1; ++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;
-    idx1 = nsetp;
-    for (j = jj; j <= idx1; ++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]);
-      // SS: CHECK THIS DAMAGE...
-      a[j + ii * a_dim1] = 0.;
-      idx2 = n;
-      for (l = 1; l <= idx2; ++l) {
-        if (l != ii) {
-
-          /*                 Apply procedure G2 (CC,SS,A(J-1,L),A(J,
-                             L)) */
-
-          temp = a[j - 1 + l * a_dim1];
-          // SS: CHECK THIS DAMAGE
-          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. */
-
-  idx1 = nsetp;
-  for (jj = 1; jj <= idx1; ++jj) {
-    i__ = index[jj];
-    if (x[i__] <= 0.) {
-      goto L260;
-    }
-    /* L300: */
-  }
-
-  /*         COPY B( ) INTO ZZ( ).  THEN SOLVE AGAIN AND LOOP BACK. */
-
-  idx1 = m;
-  for (i__ = 1; i__ <= idx1; ++i__) {
-    /* L310: */
-    zz[i__] = b[i__];
-  }
-  rtnkey = 2;
-  goto L400;
- L320:
-  goto L210;
-  /*                      ******  END OF SECONDARY LOOP  ****** */
-
- L330:
-  idx1 = nsetp;
-  for (ip = 1; ip <= idx1; ++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) {
-    idx1 = m;
-    for (i__ = npp1; i__ <= idx1; ++i__) {
-      /* L360: */
-      /* Computing 2nd power */
-      d1 = b[i__];
-      sm += d1 * d1;
-    }
-  } else {
-    idx1 = n;
-    for (j = 1; j <= idx1; ++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:
-  idx1 = nsetp;
-  for (l = 1; l <= idx1; ++l) {
-    ip = nsetp + 1 - l;
-    if (l != 1) {
-      idx2 = ip;
-      for (ii = 1; ii <= idx2; ++ii) {
-        zz[ii] -= a[ii + jj * a_dim1] * zz[ip + 1];
-        /* L410: */
-      }
-    }
-    jj = index[ip];
-    zz[ip] /= a[ip + jj * a_dim1];
-    /* L430: */
-  }
-  switch ((int)rtnkey) {
-  case 1:  goto L200;
-  case 2:  goto L320;
-  }
-
-  /* The next line was added after the f2c translation to keep
-     compilers from complaining about a void return from a non-void
-     function. */
-  return 0;
-
-} /* nnls_ */
-
-
-int g1(float* a, float* b, float* cterm, float* sterm, float* sig)
-{
-  /* System generated locals */
-  float d;
-
-  static float xr, yr;
-
-
-  if (nnls_abs(*a) > nnls_abs(*b)) {
-    xr = *b / *a;
-    /* Computing 2nd power */
-    d = xr;
-    yr = sqrt(d * d + 1.);
-    d = 1. / yr;
-    *cterm = d_sign(d, *a);
-    *sterm = *cterm * xr;
-    *sig = nnls_abs(*a) * yr;
-    return 0;
-  }
-  if (*b != 0.) {
-    xr = *a / *b;
-    /* Computing 2nd power */
-    d = xr;
-    yr = sqrt(d * d + 1.);
-    d = 1. / yr;
-    *sterm = d_sign(d, *b);
-    *cterm = *sterm * xr;
-    *sig = nnls_abs(*b) * yr;
-    return 0;
-  }
-  *sig = 0.;
-  *cterm = 0.;
-  *sterm = 1.;
-  return 0;
-} /* g1_ */
-
-
-/* See nnls.h for explanation */
-int h12(int mode, int* lpivot, int* l1,
-        int m, float* u, int* iue, float* up, float* c__,
-        int* ice, int* icv, int* ncv)
-{
-  /* System generated locals */
-  int u_dim1, u_offset, idx1, idx2;
-  float d, d2;
-
-  /* Builtin functions */
-  /* The following line was commented out after the f2c translation */
-  /* float sqrt(); */
-
-  /* Local variables */
-  static int incr;
-  static float b;
-  static int i__, j;
-  static float clinv;
-  static int i2, i3, i4;
-  static float cl, sm;
-
-  /*     ------------------------------------------------------------------
-   */
-  /*     float precision U(IUE,M) */
-  /*     ------------------------------------------------------------------
-   */
-  /* Parameter adjustments */
-  u_dim1 = *iue;
-  u_offset = u_dim1 + 1;
-  u -= u_offset;
-  --c__;
-
-  /* Function Body */
-  if (0 >= *lpivot || *lpivot >= *l1 || *l1 > m) {
-    return 0;
-  }
-  cl = (d = u[*lpivot * u_dim1 + 1], nnls_abs(d));
-  if (mode == 2) {
-    goto L60;
-  }
-  /*                            ****** CONSTRUCT THE TRANSFORMATION. ******
-   */
-  idx1 = m;
-  for (j = *l1; j <= idx1; ++j) {
-    /* L10: */
-    /* Computing MAX */
-    d2 = (d = u[j * u_dim1 + 1], nnls_abs(d));
-    cl = nnls_max(d2,cl);
-  }
-  if (cl <= 0.) {
-    goto L130;
-  } else {
-    goto L20;
-  }
- L20:
-  clinv = 1. / cl;
-  /* Computing 2nd power */
-  d = u[*lpivot * u_dim1 + 1] * clinv;
-  sm = d * d;
-  idx1 = m;
-  for (j = *l1; j <= idx1; ++j) {
-    /* L30: */
-    /* Computing 2nd power */
-    d = u[j * u_dim1 + 1] * clinv;
-    sm += d * d;
-  }
-  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);
-  idx1 = *ncv;
-  for (j = 1; j <= idx1; ++j) {
-    i2 += *icv;
-    i3 = i2 + incr;
-    i4 = i3;
-    sm = c__[i2] * *up;
-    idx2 = m;
-    for (i__ = *l1; i__ <= idx2; ++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;
-    idx2 = m;
-    for (i__ = *l1; i__ <= idx2; ++i__) {
-      c__[i4] += sm * u[i__ * u_dim1 + 1];
-      /* L110: */
-      i4 += *ice;
-    }
-  L120:
-    ;
-  }
- L130:
-  return 0;
-} /* h12 */
--- a/nnls.cpp	Mon Oct 18 09:35:26 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,619 +0,0 @@
-// 	$Id: nnls.cc,v 1.1.2.1 2003/03/06 16:28:07 suvrit Exp $	
-// File: nnls.cc
-// Implements the Lawson-Hanson NNLS algorithm
-// Copied over from nnls.c so i don't ahve copyright on this
-//...somebody else has.....don't know if this should be under GPL or LGPL or
-// whatever, but i'll put a lil note here anyways:
-
-// Copyright (C) 2004 Lawson-Hanson
-// Modifications to adapt to c++ by Suvrit Sra.
-
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation; either version 2
-// of the License, or (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-
-#include "nnls.h"
-#include <iostream>
-
-using namespace std;
-
-float d_sign(float& a, float& b)
-{
-  float x;
-  x = (a >= 0 ? a : - a);
-  return (b >= 0 ? x : -x);
-}
- 
-/* Table of constant values */
- 
-int c__1 = 1;
-int c__0 = 0;
-int c__2 = 2;
-
-
-int nnls(float* a,  int mda,  int m,  int n, float* b, 
-	 float* x, float* rnorm, float* w, float* zz, int* index, 
-	 int* mode)
-{
-  /* System generated locals */
-  int a_dim1, a_offset, idx1, idx2;
-  float d1, d2;
- 
- 
-  /* Local variables */
-  static int iter;
-  static float temp, wmax;
-  static int i__, j, l;
-  static float t, alpha, asave;
-  static int itmax, izmax, nsetp;
-  static float unorm, ztest, cc;
-  float dummy[2];
-  static int ii, jj, ip;
-  static float sm;
-  static int iz, jz;
-  static float up, ss;
-  static int rtnkey, iz1, iz2, npp1;
- 
-  /*     ------------------------------------------------------------------ 
-   */
-  /*     int INDEX(N) */
-  /*     float precision A(MDA,N), B(M), W(N), X(N), ZZ(M) */
-  /*     ------------------------------------------------------------------ 
-   */
-  /* Parameter adjustments */
-  a_dim1 = mda;
-  a_offset = a_dim1 + 1;
-  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 * 30;
- 
-  /*                    INITIALIZE THE ARRAYS INDEX() AND X(). */
- 
-  idx1 = n;
-  for (i__ = 1; i__ <= idx1; ++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(). 
-   */
- 
-  idx1 = iz2;
-  for (iz = iz1; iz <= idx1; ++iz) {
-    j = index[iz];
-    sm = 0.;
-    idx2 = m;
-    for (l = npp1; l <= idx2; ++l) {
-      /* L40: */
-      sm += a[l + j * a_dim1] * b[l];
-    }
-    w[j] = sm;
-    /* L50: */
-  }
-  /*                                   FIND LARGEST POSITIVE W(J). */
- L60:
-  wmax = 0.;
-  idx1 = iz2;
-  for (iz = iz1; iz <= idx1; ++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];
-  idx1 = npp1 + 1;
-  h12(c__1, &npp1, &idx1, m, &a[j * a_dim1 + 1], &c__1, &up, dummy, &
-      c__1, &c__1, &c__0);
-  unorm = 0.;
-  if (nsetp != 0) {
-    idx1 = nsetp;
-    for (l = 1; l <= idx1; ++l) {
-      /* L90: */
-      /* Computing 2nd power */
-      d1 = a[l + j * a_dim1];
-      unorm += d1 * d1;
-    }
-  }
-  unorm = sqrt(unorm);
-  d2 = unorm + (d1 = a[npp1 + j * a_dim1], nnls_abs(d1)) * .01;
-  if ((d2- unorm) > 0.) {
- 
-    /*        COL J IS SUFFICIENTLY INDEPENDENT.  COPY B INTO ZZ, UPDATE Z
-	      Z */
-    /*        AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ). */
- 
-    idx1 = m;
-    for (l = 1; l <= idx1; ++l) {
-      /* L120: */
-      zz[l] = b[l];
-    }
-    idx1 = npp1 + 1;
-    h12(c__2, &npp1, &idx1, 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:
-  idx1 = m;
-  for (l = 1; l <= idx1; ++l) {
-    /* L150: */
-    b[l] = zz[l];
-  }
- 
-  index[iz] = index[iz1];
-  index[iz1] = j;
-  ++iz1;
-  nsetp = npp1;
-  ++npp1;
- 
-  if (iz1 <= iz2) {
-    idx1 = iz2;
-    for (jz = iz1; jz <= idx1; ++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) {
-    idx1 = m;
-    for (l = npp1; l <= idx1; ++l) {
-      /* L180: */
-      // SS: CHECK THIS DAMAGE....
-      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;
-// cerr << iter << endl;
-  if (iter > itmax) {
-    *mode = 3;
-    /* The following lines were replaced after the f2c translation */
-    /* s_wsfe(&io___22); */
-    /* do_fio(&c__1, " NNLS quitting on iteration count.", 34L); */
-    /* e_wsfe(); */
-    fprintf(stdout, "\n NNLS quitting on iteration count.\n");
-    fflush(stdout);
-    goto L350;
-  }
- 
-  /*                    SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE. */
-  /*                                  IF NOT COMPUTE ALPHA. */
- 
-  alpha = 2.;
-  idx1 = nsetp;
-  for (ip = 1; ip <= idx1; ++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. */
- 
-  idx1 = nsetp;
-  for (ip = 1; ip <= idx1; ++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;
-    idx1 = nsetp;
-    for (j = jj; j <= idx1; ++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]);
-      // SS: CHECK THIS DAMAGE...
-      a[j + ii * a_dim1] = 0.;
-      idx2 = n;
-      for (l = 1; l <= idx2; ++l) {
-	if (l != ii) {
- 
-	  /*                 Apply procedure G2 (CC,SS,A(J-1,L),A(J,
-			     L)) */
- 
-	  temp = a[j - 1 + l * a_dim1];
-	  // SS: CHECK THIS DAMAGE
-	  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__;
-// cerr << "index[" << iz1 << "]  is " << i__ << endl;
- 
-  /*        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. */
- 
-  idx1 = nsetp;
-  for (jj = 1; jj <= idx1; ++jj) {
-    i__ = index[jj];
-    if (x[i__] <= 0.) {
-      goto L260;
-    }
-    /* L300: */
-  }
- 
-  /*         COPY B( ) INTO ZZ( ).  THEN SOLVE AGAIN AND LOOP BACK. */
- 
-  idx1 = m;
-  for (i__ = 1; i__ <= idx1; ++i__) {
-    /* L310: */
-    zz[i__] = b[i__];
-  }
-  rtnkey = 2;
-  goto L400;
- L320:
-  goto L210;
-  /*                      ******  END OF SECONDARY LOOP  ****** */
- 
- L330:
-  idx1 = nsetp;
-  for (ip = 1; ip <= idx1; ++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) {
-    idx1 = m;
-    for (i__ = npp1; i__ <= idx1; ++i__) {
-      /* L360: */
-      /* Computing 2nd power */
-      d1 = b[i__];
-      sm += d1 * d1;
-    }
-  } else {
-    idx1 = n;
-    for (j = 1; j <= idx1; ++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:
-  idx1 = nsetp;
-  for (l = 1; l <= idx1; ++l) {
-    ip = nsetp + 1 - l;
-    if (l != 1) {
-      idx2 = ip;
-      for (ii = 1; ii <= idx2; ++ii) {
-	zz[ii] -= a[ii + jj * a_dim1] * zz[ip + 1];
-	/* L410: */
-      }
-    }
-    jj = index[ip];
-	// cerr << ip << " " << jj << " " << a_dim1 << endl;
-    zz[ip] /= a[ip + jj * a_dim1];
-    /* L430: */
-  }
-  switch ((int)rtnkey) {
-  case 1:  goto L200;
-  case 2:  goto L320;
-  }
- 
-  /* The next line was added after the f2c translation to keep
-     compilers from complaining about a void return from a non-void
-     function. */
-  return 0;
- 
-} /* nnls_ */
-
-
-int g1(float* a, float* b, float* cterm, float* sterm, float* sig)
-{
-  /* System generated locals */
-  float d;
- 
-  static float xr, yr;
- 
- 
-  if (nnls_abs(*a) > nnls_abs(*b)) {
-    xr = *b / *a;
-    /* Computing 2nd power */
-    d = xr;
-    yr = sqrt(d * d + 1.);
-    d = 1. / yr;
-    *cterm = d_sign(d, *a);
-    *sterm = *cterm * xr;
-    *sig = nnls_abs(*a) * yr;
-    return 0;
-  }
-  if (*b != 0.) {
-    xr = *a / *b;
-    /* Computing 2nd power */
-    d = xr;
-    yr = sqrt(d * d + 1.);
-    d = 1. / yr;
-    *sterm = d_sign(d, *b);
-    *cterm = *sterm * xr;
-    *sig = nnls_abs(*b) * yr;
-    return 0;
-  }
-  *sig = 0.;
-  *cterm = 0.;
-  *sterm = 1.;
-  return 0;
-} /* g1_ */
- 
-
-/* See nnls.h for explanation */
-int h12(int mode, int* lpivot, int* l1, 
-	int m, float* u, int* iue, float* up, float* c__, 
-	int* ice, int* icv, int* ncv)
-{
-  /* System generated locals */
-  int u_dim1, u_offset, idx1, idx2;
-  float d, d2;
- 
-  /* Builtin functions */
-  /* The following line was commented out after the f2c translation */
-  /* float sqrt(); */
- 
-  /* Local variables */
-  static int incr;
-  static float b;
-  static int i__, j;
-  static float clinv;
-  static int i2, i3, i4;
-  static float cl, sm;
- 
-  /*     ------------------------------------------------------------------ 
-   */
-  /*     float precision U(IUE,M) */
-  /*     ------------------------------------------------------------------ 
-   */
-  /* Parameter adjustments */
-  u_dim1 = *iue;
-  u_offset = u_dim1 + 1;
-  u -= u_offset;
-  --c__;
- 
-  /* Function Body */
-  if (0 >= *lpivot || *lpivot >= *l1 || *l1 > m) {
-    return 0;
-  }
-  cl = (d = u[*lpivot * u_dim1 + 1], nnls_abs(d));
-  if (mode == 2) {
-    goto L60;
-  }
-  /*                            ****** CONSTRUCT THE TRANSFORMATION. ****** 
-   */
-  idx1 = m;
-  for (j = *l1; j <= idx1; ++j) {
-    /* L10: */
-    /* Computing MAX */
-    d2 = (d = u[j * u_dim1 + 1], nnls_abs(d));
-    cl = nnls_max(d2,cl);
-  }
-  if (cl <= 0.) {
-    goto L130;
-  } else {
-    goto L20;
-  }
- L20:
-  clinv = 1. / cl;
-  /* Computing 2nd power */
-  d = u[*lpivot * u_dim1 + 1] * clinv;
-  sm = d * d;
-  idx1 = m;
-  for (j = *l1; j <= idx1; ++j) {
-    /* L30: */
-    /* Computing 2nd power */
-    d = u[j * u_dim1 + 1] * clinv;
-    sm += d * d;
-  }
-  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);
-  idx1 = *ncv;
-  for (j = 1; j <= idx1; ++j) {
-    i2 += *icv;
-    i3 = i2 + incr;
-    i4 = i3;
-    sm = c__[i2] * *up;
-    idx2 = m;
-    for (i__ = *l1; i__ <= idx2; ++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;
-    idx2 = m;
-    for (i__ = *l1; i__ <= idx2; ++i__) {
-      c__[i4] += sm * u[i__ * u_dim1 + 1];
-      /* L110: */
-      i4 += *ice;
-    }
-  L120:
-    ;
-  }
- L130:
-  return 0;
-} /* h12 */
- 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nnls.f	Thu Oct 21 11:58:28 2010 +0100
@@ -0,0 +1,479 @@
+
+       double precision FUNCTION DIFF(X,Y)
+c
+c  Function used in tests that depend on machine precision.
+c
+c  The original version of this code was developed by
+c  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
+c  1973 JUN 7, and published in the book
+c  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
+c  Revised FEB 1995 to accompany reprinting of the book by SIAM.
+C
+      double precision X, Y
+      DIFF=X-Y  
+      RETURN
+      END   
+
+
+      SUBROUTINE G1 (A,B,CTERM,STERM,SIG)   
+c
+C     COMPUTE ORTHOGONAL ROTATION MATRIX..  
+c
+c  The original version of this code was developed by
+c  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
+c  1973 JUN 12, and published in the book
+c  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
+c  Revised FEB 1995 to accompany reprinting of the book by SIAM.
+C   
+C     COMPUTE.. MATRIX   (C, S) SO THAT (C, S)(A) = (SQRT(A**2+B**2))   
+C                        (-S,C)         (-S,C)(B)   (   0          )    
+C     COMPUTE SIG = SQRT(A**2+B**2) 
+C        SIG IS COMPUTED LAST TO ALLOW FOR THE POSSIBILITY THAT 
+C        SIG MAY BE IN THE SAME LOCATION AS A OR B .
+C     ------------------------------------------------------------------
+      double precision A, B, CTERM, ONE, SIG, STERM, XR, YR, ZERO
+      parameter(ONE = 1.0d0, ZERO = 0.0d0)
+C     ------------------------------------------------------------------
+      if (abs(A) .gt. abs(B)) then
+         XR=B/A
+         YR=sqrt(ONE+XR**2)
+         CTERM=sign(ONE/YR,A)
+         STERM=CTERM*XR
+         SIG=abs(A)*YR     
+         RETURN
+      endif
+
+      if (B .ne. ZERO) then
+         XR=A/B
+         YR=sqrt(ONE+XR**2)
+         STERM=sign(ONE/YR,B)
+         CTERM=STERM*XR
+         SIG=abs(B)*YR     
+         RETURN
+      endif
+
+      SIG=ZERO  
+      CTERM=ZERO  
+      STERM=ONE   
+      RETURN
+      END   
+
+
+C     SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV)  
+C   
+C  CONSTRUCTION AND/OR APPLICATION OF A SINGLE   
+C  HOUSEHOLDER TRANSFORMATION..     Q = I + U*(U**T)/B   
+C   
+c  The original version of this code was developed by
+c  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
+c  1973 JUN 12, and published in the book
+c  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
+c  Revised FEB 1995 to accompany reprinting of the book by SIAM.
+C     ------------------------------------------------------------------
+c                     Subroutine Arguments
+c
+C     MODE   = 1 OR 2   Selects Algorithm H1 to construct and apply a
+c            Householder transformation, or Algorithm H2 to apply a
+c            previously constructed transformation.
+C     LPIVOT IS THE INDEX OF THE PIVOT ELEMENT. 
+C     L1,M   IF L1 .LE. M   THE TRANSFORMATION WILL BE CONSTRUCTED TO   
+C            ZERO ELEMENTS INDEXED FROM L1 THROUGH M.   IF L1 GT. M     
+C            THE SUBROUTINE DOES AN IDENTITY TRANSFORMATION.
+C     U(),IUE,UP    On entry with MODE = 1, U() contains the pivot
+c            vector.  IUE is the storage increment between elements.  
+c            On exit when MODE = 1, U() and UP contain quantities
+c            defining the vector U of the Householder transformation.
+c            on entry with MODE = 2, U() and UP should contain
+c            quantities previously computed with MODE = 1.  These will
+c            not be modified during the entry with MODE = 2.   
+C     C()    ON ENTRY with MODE = 1 or 2, C() CONTAINS A MATRIX WHICH
+c            WILL BE REGARDED AS A SET OF VECTORS TO WHICH THE
+c            HOUSEHOLDER TRANSFORMATION IS TO BE APPLIED.
+c            ON EXIT C() CONTAINS THE SET OF TRANSFORMED VECTORS.
+C     ICE    STORAGE INCREMENT BETWEEN ELEMENTS OF VECTORS IN C().  
+C     ICV    STORAGE INCREMENT BETWEEN VECTORS IN C().  
+C     NCV    NUMBER OF VECTORS IN C() TO BE TRANSFORMED. IF NCV .LE. 0  
+C            NO OPERATIONS WILL BE DONE ON C(). 
+C     ------------------------------------------------------------------
+      SUBROUTINE H12 (MODE,LPIVOT,L1,M,U,IUE,UP,C,ICE,ICV,NCV)  
+C     ------------------------------------------------------------------
+      integer I, I2, I3, I4, ICE, ICV, INCR, IUE, J
+      integer L1, LPIVOT, M, MODE, NCV
+      double precision B, C(*), CL, CLINV, ONE, SM
+c     double precision U(IUE,M)
+      double precision U(IUE,*)
+      double precision UP
+      parameter(ONE = 1.0d0)
+C     ------------------------------------------------------------------
+      IF (0.GE.LPIVOT.OR.LPIVOT.GE.L1.OR.L1.GT.M) RETURN    
+      CL=abs(U(1,LPIVOT))   
+      IF (MODE.EQ.2) GO TO 60   
+C                            ****** CONSTRUCT THE TRANSFORMATION. ******
+          DO 10 J=L1,M  
+   10     CL=MAX(abs(U(1,J)),CL)  
+      IF (CL) 130,130,20
+   20 CLINV=ONE/CL  
+      SM=(U(1,LPIVOT)*CLINV)**2   
+          DO 30 J=L1,M  
+   30     SM=SM+(U(1,J)*CLINV)**2 
+      CL=CL*SQRT(SM)   
+      IF (U(1,LPIVOT)) 50,50,40     
+   40 CL=-CL
+   50 UP=U(1,LPIVOT)-CL 
+      U(1,LPIVOT)=CL    
+      GO TO 70  
+C            ****** APPLY THE TRANSFORMATION  I+U*(U**T)/B  TO C. ******
+C   
+   60 IF (CL) 130,130,70
+   70 IF (NCV.LE.0) RETURN  
+      B= UP*U(1,LPIVOT)
+C                       B  MUST BE NONPOSITIVE HERE.  IF B = 0., RETURN.
+C   
+      IF (B) 80,130,130 
+   80 B=ONE/B   
+      I2=1-ICV+ICE*(LPIVOT-1)   
+      INCR=ICE*(L1-LPIVOT)  
+          DO 120 J=1,NCV
+          I2=I2+ICV     
+          I3=I2+INCR    
+          I4=I3 
+          SM=C(I2)*UP
+              DO 90 I=L1,M  
+              SM=SM+C(I3)*U(1,I)
+   90         I3=I3+ICE 
+          IF (SM) 100,120,100   
+  100     SM=SM*B   
+          C(I2)=C(I2)+SM*UP
+              DO 110 I=L1,M 
+              C(I4)=C(I4)+SM*U(1,I)
+  110         I4=I4+ICE 
+  120     CONTINUE  
+  130 RETURN
+      END   
+
+
+
+C     SUBROUTINE NNLS  (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE)
+C   
+C  Algorithm NNLS: NONNEGATIVE LEAST SQUARES
+C   
+c  The original version of this code was developed by
+c  Charles L. Lawson and Richard J. Hanson at Jet Propulsion Laboratory
+c  1973 JUN 15, and published in the book
+c  "SOLVING LEAST SQUARES PROBLEMS", Prentice-HalL, 1974.
+c  Revised FEB 1995 to accompany reprinting of the book by SIAM.
+c
+C     GIVEN AN M BY N MATRIX, A, AND AN M-VECTOR, B,  COMPUTE AN
+C     N-VECTOR, X, THAT SOLVES THE LEAST SQUARES PROBLEM   
+C   
+C                      A * X = B  SUBJECT TO X .GE. 0   
+C     ------------------------------------------------------------------
+c                     Subroutine Arguments
+c
+C     A(),MDA,M,N     MDA IS THE FIRST DIMENSIONING PARAMETER FOR THE   
+C                     ARRAY, A().   ON ENTRY A() CONTAINS THE M BY N    
+C                     MATRIX, A.           ON EXIT A() CONTAINS 
+C                     THE PRODUCT MATRIX, Q*A , WHERE Q IS AN   
+C                     M BY M ORTHOGONAL MATRIX GENERATED IMPLICITLY BY  
+C                     THIS SUBROUTINE.  
+C     B()     ON ENTRY B() CONTAINS THE M-VECTOR, B.   ON EXIT B() CON- 
+C             TAINS Q*B.
+C     X()     ON ENTRY X() NEED NOT BE INITIALIZED.  ON EXIT X() WILL   
+C             CONTAIN THE SOLUTION VECTOR.  
+C     RNORM   ON EXIT RNORM CONTAINS THE EUCLIDEAN NORM OF THE  
+C             RESIDUAL VECTOR.  
+C     W()     AN N-ARRAY OF WORKING SPACE.  ON EXIT W() WILL CONTAIN    
+C             THE DUAL SOLUTION VECTOR.   W WILL SATISFY W(I) = 0.  
+C             FOR ALL I IN SET P  AND W(I) .LE. 0. FOR ALL I IN SET Z   
+C     ZZ()     AN M-ARRAY OF WORKING SPACE.     
+C     INDEX()     AN INTEGER WORKING ARRAY OF LENGTH AT LEAST N.
+C                 ON EXIT THE CONTENTS OF THIS ARRAY DEFINE THE SETS    
+C                 P AND Z AS FOLLOWS..  
+C   
+C                 INDEX(1)   THRU INDEX(NSETP) = SET P.     
+C                 INDEX(IZ1) THRU INDEX(IZ2)   = SET Z.     
+C                 IZ1 = NSETP + 1 = NPP1
+C                 IZ2 = N   
+C     MODE    THIS IS A SUCCESS-FAILURE FLAG WITH THE FOLLOWING 
+C             MEANINGS. 
+C             1     THE SOLUTION HAS BEEN COMPUTED SUCCESSFULLY.
+C             2     THE DIMENSIONS OF THE PROBLEM ARE BAD.  
+C                   EITHER M .LE. 0 OR N .LE. 0.
+C             3    ITERATION COUNT EXCEEDED.  MORE THAN 3*N ITERATIONS. 
+C   
+C     ------------------------------------------------------------------
+      SUBROUTINE NNLS (A,MDA,M,N,B,X,RNORM,W,ZZ,INDEX,MODE) 
+C     ------------------------------------------------------------------
+      integer I, II, IP, ITER, ITMAX, IZ, IZ1, IZ2, IZMAX, J, JJ, JZ, L
+      integer M, MDA, MODE,N, NPP1, NSETP, RTNKEY
+c     integer INDEX(N)  
+c     double precision A(MDA,N), B(M), W(N), X(N), ZZ(M)   
+      integer INDEX(*)  
+      double precision A(MDA,*), B(*), W(*), X(*), ZZ(*)   
+      double precision ALPHA, ASAVE, CC, DIFF, DUMMY, FACTOR, RNORM
+      double precision SM, SS, T, TEMP, TWO, UNORM, UP, WMAX
+      double precision ZERO, ZTEST
+      parameter(FACTOR = 0.01d0)
+      parameter(TWO = 2.0d0, ZERO = 0.0d0)
+C     ------------------------------------------------------------------
+      MODE=1
+      IF (M .le. 0 .or. N .le. 0) then
+         MODE=2
+         RETURN
+      endif
+      ITER=0
+      ITMAX=3*N 
+C   
+C                    INITIALIZE THE ARRAYS INDEX() AND X(). 
+C   
+          DO 20 I=1,N   
+          X(I)=ZERO     
+   20     INDEX(I)=I    
+C   
+      IZ2=N 
+      IZ1=1 
+      NSETP=0   
+      NPP1=1
+C                             ******  MAIN LOOP BEGINS HERE  ******     
+   30 CONTINUE  
+C                  QUIT IF ALL COEFFICIENTS ARE ALREADY IN THE SOLUTION.
+C                        OR IF M COLS OF A HAVE BEEN TRIANGULARIZED.    
+C   
+      IF (IZ1 .GT.IZ2.OR.NSETP.GE.M) GO TO 350   
+C   
+C         COMPUTE COMPONENTS OF THE DUAL (NEGATIVE GRADIENT) VECTOR W().
+C   
+      DO 50 IZ=IZ1,IZ2  
+         J=INDEX(IZ)   
+         SM=ZERO   
+         DO 40 L=NPP1,M
+   40        SM=SM+A(L,J)*B(L)     
+         W(J)=SM   
+   50 continue
+C                                   FIND LARGEST POSITIVE W(J). 
+   60 continue
+      WMAX=ZERO 
+      DO 70 IZ=IZ1,IZ2  
+         J=INDEX(IZ)   
+         IF (W(J) .gt. WMAX) then
+            WMAX=W(J)     
+            IZMAX=IZ  
+         endif
+   70 CONTINUE  
+C   
+C             IF WMAX .LE. 0. GO TO TERMINATION.
+C             THIS INDICATES SATISFACTION OF THE KUHN-TUCKER CONDITIONS.
+C   
+      IF (WMAX .le. ZERO) go to 350
+      IZ=IZMAX  
+      J=INDEX(IZ)   
+C   
+C     THE SIGN OF W(J) IS OK FOR J TO BE MOVED TO SET P.    
+C     BEGIN THE TRANSFORMATION AND CHECK NEW DIAGONAL ELEMENT TO AVOID  
+C     NEAR LINEAR DEPENDENCE.   
+C   
+      ASAVE=A(NPP1,J)   
+      CALL H12 (1,NPP1,NPP1+1,M,A(1,J),1,UP,DUMMY,1,1,0)    
+      UNORM=ZERO
+      IF (NSETP .ne. 0) then
+          DO 90 L=1,NSETP   
+   90       UNORM=UNORM+A(L,J)**2     
+      endif
+      UNORM=sqrt(UNORM) 
+      IF (DIFF(UNORM+ABS(A(NPP1,J))*FACTOR,UNORM) .gt. ZERO) then
+C   
+C        COL J IS SUFFICIENTLY INDEPENDENT.  COPY B INTO ZZ, UPDATE ZZ
+C        AND SOLVE FOR ZTEST ( = PROPOSED NEW VALUE FOR X(J) ).    
+C   
+         DO 120 L=1,M  
+  120        ZZ(L)=B(L)    
+         CALL H12 (2,NPP1,NPP1+1,M,A(1,J),1,UP,ZZ,1,1,1)   
+         ZTEST=ZZ(NPP1)/A(NPP1,J)  
+C   
+C                                     SEE IF ZTEST IS POSITIVE  
+C   
+         IF (ZTEST .gt. ZERO) go to 140
+      endif
+C   
+C     REJECT J AS A CANDIDATE TO BE MOVED FROM SET Z TO SET P.  
+C     RESTORE A(NPP1,J), SET W(J)=0., AND LOOP BACK TO TEST DUAL
+C     COEFFS AGAIN.     
+C   
+      A(NPP1,J)=ASAVE   
+      W(J)=ZERO 
+      GO TO 60  
+C   
+C     THE INDEX  J=INDEX(IZ)  HAS BEEN SELECTED TO BE MOVED FROM
+C     SET Z TO SET P.    UPDATE B,  UPDATE INDICES,  APPLY HOUSEHOLDER  
+C     TRANSFORMATIONS TO COLS IN NEW SET Z,  ZERO SUBDIAGONAL ELTS IN   
+C     COL J,  SET W(J)=0.   
+C   
+  140 continue
+      DO 150 L=1,M  
+  150    B(L)=ZZ(L)    
+C   
+      INDEX(IZ)=INDEX(IZ1)  
+      INDEX(IZ1)=J  
+      IZ1=IZ1+1 
+      NSETP=NPP1
+      NPP1=NPP1+1   
+C   
+      IF (IZ1 .le. IZ2) then
+         DO 160 JZ=IZ1,IZ2 
+            JJ=INDEX(JZ)  
+            CALL H12 (2,NSETP,NPP1,M,A(1,J),1,UP,A(1,JJ),1,MDA,1)
+  160    continue
+      endif
+C   
+      IF (NSETP .ne. M) then
+         DO 180 L=NPP1,M   
+  180       A(L,J)=ZERO   
+      endif
+C   
+      W(J)=ZERO 
+C                                SOLVE THE TRIANGULAR SYSTEM.   
+C                                STORE THE SOLUTION TEMPORARILY IN ZZ().
+      RTNKEY = 1
+      GO TO 400 
+  200 CONTINUE  
+C   
+C                       ******  SECONDARY LOOP BEGINS HERE ******   
+C   
+C                          ITERATION COUNTER.   
+C 
+  210 continue  
+      ITER=ITER+1   
+      IF (ITER .gt. ITMAX) then
+         MODE=3
+         write (*,'(/a)') ' NNLS quitting on iteration count.'
+         GO TO 350 
+      endif
+C   
+C                    SEE IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE.    
+C                                  IF NOT COMPUTE ALPHA.    
+C   
+      ALPHA=TWO 
+      DO 240 IP=1,NSETP 
+         L=INDEX(IP)   
+         IF (ZZ(IP) .le. ZERO) then
+            T=-X(L)/(ZZ(IP)-X(L))     
+            IF (ALPHA .gt. T) then
+               ALPHA=T   
+               JJ=IP 
+            endif
+         endif
+  240 CONTINUE  
+C   
+C          IF ALL NEW CONSTRAINED COEFFS ARE FEASIBLE THEN ALPHA WILL   
+C          STILL = 2.    IF SO EXIT FROM SECONDARY LOOP TO MAIN LOOP.   
+C   
+      IF (ALPHA.EQ.TWO) GO TO 330   
+C   
+C          OTHERWISE USE ALPHA WHICH WILL BE BETWEEN 0. AND 1. TO   
+C          INTERPOLATE BETWEEN THE OLD X AND THE NEW ZZ.    
+C   
+      DO 250 IP=1,NSETP 
+         L=INDEX(IP)   
+         X(L)=X(L)+ALPHA*(ZZ(IP)-X(L)) 
+  250 continue
+C   
+C        MODIFY A AND B AND THE INDEX ARRAYS TO MOVE COEFFICIENT I  
+C        FROM SET P TO SET Z.   
+C   
+      I=INDEX(JJ)   
+  260 continue
+      X(I)=ZERO 
+C   
+      IF (JJ .ne. NSETP) then
+         JJ=JJ+1   
+         DO 280 J=JJ,NSETP 
+            II=INDEX(J)   
+            INDEX(J-1)=II 
+            CALL G1 (A(J-1,II),A(J,II),CC,SS,A(J-1,II))   
+            A(J,II)=ZERO  
+            DO 270 L=1,N  
+               IF (L.NE.II) then
+c
+c                 Apply procedure G2 (CC,SS,A(J-1,L),A(J,L))  
+c
+                  TEMP = A(J-1,L)
+                  A(J-1,L) = CC*TEMP + SS*A(J,L)
+                  A(J,L)   =-SS*TEMP + CC*A(J,L)
+               endif
+  270       CONTINUE  
+c
+c                 Apply procedure G2 (CC,SS,B(J-1),B(J))   
+c
+            TEMP = B(J-1)
+            B(J-1) = CC*TEMP + SS*B(J)    
+            B(J)   =-SS*TEMP + CC*B(J)    
+  280    continue
+      endif
+c
+      NPP1=NSETP
+      NSETP=NSETP-1     
+      IZ1=IZ1-1 
+      INDEX(IZ1)=I  
+C   
+C        SEE IF THE REMAINING COEFFS IN SET P ARE FEASIBLE.  THEY SHOULD
+C        BE BECAUSE OF THE WAY ALPHA WAS DETERMINED.
+C        IF ANY ARE INFEASIBLE IT IS DUE TO ROUND-OFF ERROR.  ANY   
+C        THAT ARE NONPOSITIVE WILL BE SET TO ZERO   
+C        AND MOVED FROM SET P TO SET Z. 
+C   
+      DO 300 JJ=1,NSETP 
+         I=INDEX(JJ)   
+         IF (X(I) .le. ZERO) go to 260
+  300 CONTINUE  
+C   
+C         COPY B( ) INTO ZZ( ).  THEN SOLVE AGAIN AND LOOP BACK.
+C   
+      DO 310 I=1,M  
+  310     ZZ(I)=B(I)    
+      RTNKEY = 2
+      GO TO 400 
+  320 CONTINUE  
+      GO TO 210 
+C                      ******  END OF SECONDARY LOOP  ******
+C   
+  330 continue
+      DO 340 IP=1,NSETP 
+          I=INDEX(IP)   
+  340     X(I)=ZZ(IP)   
+C        ALL NEW COEFFS ARE POSITIVE.  LOOP BACK TO BEGINNING.  
+      GO TO 30  
+C   
+C                        ******  END OF MAIN LOOP  ******   
+C   
+C                        COME TO HERE FOR TERMINATION.  
+C                     COMPUTE THE NORM OF THE FINAL RESIDUAL VECTOR.    
+C 
+  350 continue  
+      SM=ZERO   
+      IF (NPP1 .le. M) then
+         DO 360 I=NPP1,M   
+  360       SM=SM+B(I)**2 
+      else
+         DO 380 J=1,N  
+  380       W(J)=ZERO     
+      endif
+      RNORM=sqrt(SM)    
+      RETURN
+C   
+C     THE FOLLOWING BLOCK OF CODE IS USED AS AN INTERNAL SUBROUTINE     
+C     TO SOLVE THE TRIANGULAR SYSTEM, PUTTING THE SOLUTION IN ZZ().     
+C   
+  400 continue
+      DO 430 L=1,NSETP  
+         IP=NSETP+1-L  
+         IF (L .ne. 1) then
+            DO 410 II=1,IP
+               ZZ(II)=ZZ(II)-A(II,JJ)*ZZ(IP+1)   
+  410       continue
+         endif
+         JJ=INDEX(IP)  
+         ZZ(IP)=ZZ(IP)/A(IP,JJ)    
+  430 continue
+      go to (200, 320), RTNKEY
+      END   
+
--- a/nnls.h	Mon Oct 18 09:35:26 2010 +0000
+++ b/nnls.h	Thu Oct 21 11:58:28 2010 +0100
@@ -1,126 +1,15 @@
 #ifndef NNLS_H
 #define NNLS_H
 
-#include <stdio.h>
-#include <math.h>
-#define nnls_max(a,b) ((a) >= (b) ? (a) : (b))
-#define nnls_abs(x) ((x) >= 0 ? (x) : -(x))
+extern "C" {
 
-typedef int integer;
-typedef float floatreal;
+int nnls_(double *a, int *mda, int *m, int *n, 
+	  double *b, double *x, double *rnorm, 
+	  double *w, double *zz, int *index, int *mode);
 
-/*     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 INT 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(float* a, int mda, int m, int n, 
-	  float* b, float* x, float* rnorm, 
-	  float* w, float* zz, int* index, int* mode);
+#define NNLS nnls_
 
+}
 
-
-/*     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(int mode, int* lpivot, int* l1, 
-	 int m, float* u, int* iue, float* up, float* c__, 
-	 int* ice, int* icv, int* ncv);
-
-
-    /*     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 . */
-int g1(float* a, float* b, float* cterm, float* sterm, float* sig);
 #endif