#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define NCOMPONENT 3
#define NSAMPLE 100


main(int argc, char *argv[])
{
 	static float spectrum[NCOMPONENT+1][NSAMPLE+1];
	static float data[NSAMPLE+1];
	static float result[NCOMPONENT+1];
	int i;

	ReadData( spectrum, data , argv[1]);

	NNLsm( spectrum, data, result );

	for( i = 1; i <= NCOMPONENT; i++ )
	{
		printf( "Component %d -> %f\n", i, result[i] );
	}

}

ReadData( spectrum, data, fname )
float spectrum[NCOMPONENT+1][NSAMPLE+1];
float data[NSAMPLE+1];
char fname[];
{
	int i, j;
	FILE *fp;
	static char buff[256];

	fp = fopen( fname, "rt" );
	if( fp == NULL )
	{
		printf( "Can't open file\n" );
		exit(0);
	}

	for( i = 1; i <= NCOMPONENT; i++ )
	{
		for( j = 1; j <= NSAMPLE; j++ )
		{
			fgets( buff, 256, fp );
			spectrum[i][j] = atof( buff );
		}
	}

	for( i = 1; i <= NSAMPLE; i++ )
	{
		fgets( buff, 256, fp );
		data[i] = atof( buff );
	}

	printf( "ReadData end\n" );
}


NNLsm( spectrum, data, x )
float spectrum[NCOMPONENT+1][NSAMPLE+1];
float data[NSAMPLE+1];
float x[NCOMPONENT+1];
{
	float z[NSAMPLE+1];
	int i, j, k;
	static float r[NCOMPONENT+1][NCOMPONENT+1], rr;
	static float b[NCOMPONENT+1], bb;
	int nz;
	int np;
	static float iz[NCOMPONENT+1];
	float rx;
	static float w[NCOMPONENT+1];
	float wmax;
	int mi;
	int i1;
	static int ip[NCOMPONENT+1];
	static float b1[NCOMPONENT+1];
	static float r1[NCOMPONENT+1][NCOMPONENT+1];
	static float x1[NCOMPONENT+1];
	float sc;
	float sm;
	static int jz[NCOMPONENT+1];
	float al;
	int i2;
	float al1;
	int j1;


	for( i = 1; i <= NSAMPLE; i++ )
	{
		z[i] = 1.0;
	}

	for( j = 1; j <= NCOMPONENT; j++ )
	{
		for( k = j; k <= NCOMPONENT; k++ )
		{
			rr = 0.0; 
			for( i = 1; i <= NSAMPLE; i++ )
			{
				rr = rr + spectrum[j][i]*spectrum[k][i] / z[i];
			}
			r[j][k] = rr;
			r[k][j] = rr;
		}
	}


	for( j = 1; j <= NCOMPONENT; j++ )
	{
		bb = 0.0;
		for( i = 1; i <= NSAMPLE; i++ )
		{
			bb = bb + spectrum[j][i]*data[i] / z[i];
		}
		b[j] = bb;
	}

	nz = NCOMPONENT;
	np = 0;

	for( i = 1; i <= NCOMPONENT; i++ )
	{
		x[i] = 0.0;
		iz[i] = i;
	}

	while(1)
	{
		for( i = 1; i <= NCOMPONENT; i++ )
		{
			rx = 0.0;
			for( j = 1; j <= NCOMPONENT; j++ )
			{
				rx = rx + r[i][j]*x[j];
			}
			w[i] = b[i] - rx;
		}

		if( nz == 0 )
			return;
	
		wmax = 1.0e-8;
		mi = 0;

		for( i = 1; i <= nz; i++ )
		{
			i1 = iz[i];
			if( w[i1] > wmax )
			{
				wmax = w[i1];
				mi = i;
			}
		}

		if( mi == 0 )
			return;
	
		np = np + 1;
		ip[np] = iz[mi];
	
		iz[mi] = iz[nz];
		nz = nz - 1;
	
		for( i = 1; i <= np; i++ )
		{
			i1 = ip[i];
			for( j = 1; j <= np; j++ )
			{
				j1 = ip[j];
				r1[i][j] = r[i1][j1];
			}
	
			b1[i] = b[i1];
		}
	
		if( np == 1 )
		{
			x1[1] = b1[1]/r1[1][1];
		}
		else
		{
			for( i = 1; i <= np-1; i++ )
			{
				for( j = i+1; j <= np; j++ )
				{
					sc = r1[j][i]/r1[i][i];
					for( k = i+1; k <= np; k++ )
					{
						r1[j][k] = r1[j][k] - sc*r1[i][k];
					}
					b1[j] = b1[j] - sc*b1[i];
				}
			}
			x1[np] = b1[np] / r1[np][np];
			for( i = np-1; i >= 1; i-- )
			{
				sm = 0.0;
				for( j = i+1; j <= np; j++ )
				{
					sm = sm + r1[i][j]*x1[j];
				}
				x1[i] = (b1[i] - sm)/r1[i][i];
			}
		}
	
		j = 0;

		for( i = 1; i <= np; i++ )
		{
			if( x1[i] <= 0.0 )
			{
				j = j + 1;
				jz[j] = i;
			}
		}

		if( j == 0 )
		{
			for( i = 1; i <= np; i++ )
			{
				x[ip[i]] = x1[i];
			}
		}
		else
		{

			al = 1e10;
			mi = 0;
			for( i = 1; i <= j; i++ )
			{
				i1 = jz[i];
				i2 = ip[i1];
				al1 = x[i2]/(x[i2] - x1[i1]);
				if( al1 < al )
				{
					al = al1;
					mi = i1;
				}
			}
	
			for( i = 1; i <= np; i++ )
			{
				i1 = ip[i];
				x[i1] = (1.0 - al)*x[i1] + al*x1[i];
			}
	
			x[ip[mi]] = 0.0;
	
			nz = nz + 1;
			iz[nz] = ip[mi];
			ip[mi] = ip[np];
			np = np - 1;
	
		}
	}
}


