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

#define complex complex<float>

#define PI 3.1415926535897932384626433832795

int FindRoots(complex a[], int m, complex roots[]);
int Laguer(complex a[],int m,complex *x, int *its);


main(int argc, char *argv[])
{
	int size;
	float *image[128];
	FILE *fp;
	complex u, v;
	float row, phai;
	static complex *coeff;
	static complex *solution;
	int i, j;
	static char buff[256];
	
	
	if( argc < 4 )
	{
		printf( "Usage: zerosheet datafile size row\n" );
		exit(0);
	}
	
	fp = fopen( argv[1], "rt" );
	if( fp == NULL )
	{
		printf( "Can't fopen file\n" );
		exit(0);
	}
	size = atoi( argv[2] );
	row = atof( argv[3] );
	
	for( i = 0; i < size; i++ )
	{
		image[i] = (float *)malloc( sizeof(float)*size );
	}

	coeff = (complex *)malloc( sizeof(complex)*size );		/* mہ@*/
	solution = (complex *)malloc( sizeof(complex)*size );

	for( i = 0; i < size; i++ )			/* ̓f[^ǂݍ */
	{
		for( j = 0; j < size; j++ )
		{
			fgets( buff, 256, fp );
			image[i][j] = atof( buff );
		}
	}
	
	fclose( fp );


	for( phai = 0.0; phai < 2.0 * PI; phai += 0.01 )		/* ʑ[Q΂܂ŕω */
	{
		u = row * exp( complex( 0.0, 1.0)*phai );	/* ̌W@*/
		for( i = 0; i < size; i++ )
		{
			coeff[i] = 0.0;
			for( j = 0; j < size; j++ )
			{
				coeff[i] += (image[i][j] + coeff[i]*u);
			}
		}

		if( FindRoots(coeff, size-1, solution) == -1 )	/* ߂ */
			continue;;
		for( i = 1; i < size; i++ )
		{												/* ʕ\ */
			printf( "%f, %f\n", real(solution[i]),
				imag(solution[i]) );
		}
	}

}

#define EPS 2.0e-6
#define MAXM 100

int FindRoots(complex a[], int m, complex roots[])
{
	int i,its,j,jj;
	complex x,b,c;
	complex *ad;
	int result;
	
	ad = (complex *)malloc( sizeof(complex)*(m+1) );
	
	for (j=0;j<=m;j++)
	{
		ad[j]=a[j];
	}
	for (j=m;j>=1;j--)
	{
		x = complex(0.0, 0.0);
		result=Laguer(ad,j,&x,&its);
		if( result == -1 )
		{
			fprintf( stderr, "error\n" );
			return(-1);
		}
		if (fabs(imag(x)) <= 2.0*EPS*fabs(real(x)) )
			x=complex( real(x), 0.0);

		roots[j]=x;
		b=ad[j];
		for (jj=j-1; jj>=0; jj--) {
			c=ad[jj];
			ad[jj]=b;
			b=x*b + c;
		}
	}
	
	for (j=1;j<=m;j++)
		Laguer(a,m,&roots[j],&its);
	
	
	free( ad );
	
	return(1);

}


#define EPSS 1.0e-7
#define MR 8
#define MT 5
#define MAXIT (MT*MR)

int Laguer(complex a[],int m,complex *x, int *its)
{
	int iter,j;
	float abx,abp,abm,err;
	float abmax;
	complex dx,x1,g,h,sq,gp,gm,g2;
	complex P, Pd, Pdd;
	static float frac[MR+1] = {0.0,0.5,0.25,0.75,0.13,0.38,0.62,0.88,1.0};

	for (iter=1;iter<=MAXIT;iter++)
	{
		*its=iter;
		err=abs(a[m]);
		abx=abs(*x);

		err = 0.0;
		P=Pd=Pdd=complex(0.0, 0.0);
		for( j=m; j>=0; j--)
		{
			P=(*x)*P + a[j];
			err=abs(P)+abx*err;
		}
		for( j=m; j>=1; j-- )
		{
			Pd = Pd*(*x) + j*a[j];
		}
		for( j=m; j>=2; j-- )
		{
			Pdd = Pdd*(*x) + j*(j-1)*a[j];
		}

		g=Pd/P;
		g2=g*g;
		h=g2 - Pdd / P;

		err *= EPSS;
		if (abs(P) <= err)
			return(1);
		sq=sqrt((m-1)*(m*h - g2));
		gp=g+sq;
		gm=g-sq;
		abp=abs(gp);
		abm=abs(gm);
		if (abp < abm)
			gp=gm;
		if( abp > abm )
			abmax = abp;
		else
			abmax = abm;
		
		if( abmax > 0.0 )
			dx = m/gp;
		else
			dx = exp(log(1+abx))*exp(complex(0.0, 1.0)*iter);
		
		x1=(*x)-dx;
		if (real(*x) == real(x1) && imag(*x) == imag(x1))
			return(1);
		if (iter % MT) 
			*x=x1;
		else 
			*x=(*x)-frac[iter/MT]*dx;
	}
	return(-1);
}
