//easy version of code so we can check agaisnt faster version later, if convert option is enabled finds lex least version of mat and stores at mat
int lexleast(int mat[SIZE1][SIZE2], int convert)
{
	int matp[SIZE1][SIZE2]; 
	int matc[SIZE1][SIZE2]; 
	int matleast[SIZE1][SIZE2]; 
	struct entry s1; 
	struct entry s2; 
	int len,n,nx,ny; 
	if(SIZE1==SIZE2)
		len=7; 
	else
		len=3; 

	//printf("starting lex least code \n"); 
	identity(mat,matleast,SIZE1,SIZE2); //store starting value of matleast as mat		
	for(n=0; n<(len+1); n++)
	{
		//n=0 just represents first matrix
		if(n==0)
		{
			identity(mat,matp,SIZE1,SIZE2);
			//printf("i \n"); 			
		} 
		if(n==1)
		{
			verticalflip(mat,matp,SIZE1,SIZE2); 
			//printf("v \n"); 
		}
		if(n==2)
		{
			horizontalflip(mat,matp,SIZE1,SIZE2); 
			//printf("h \n"); 
		}
		if(n==3)
		{
			verticalflip(mat,matc,SIZE1,SIZE2); 
			horizontalflip(matc,matp,SIZE1,SIZE2);
			//printf("vh \n"); 
		}
		if(n==4)
		{
			transpose(mat,matp,SIZE1,SIZE2); 
			//printf("t \n"); 
		}
		if(n==5)
		{
			//identity(mat,matp,size1,size2);
			horizontalflip(mat,matc,SIZE1,SIZE2);
			transpose(matc,matp,SIZE1,SIZE2); 
			//printf("th \n"); 
		}
		if(n==6)
		{
			//identity(mat,matp,size1,size2);
			verticalflip(mat,matc,SIZE1,SIZE2); 
			transpose(matc,matp,SIZE1,SIZE2); 
			//printf("tv \n"); 
		}
		if(n==7)
		{
			//identity(mat,matp,size1,size2);
			verticalflip(mat,matc,SIZE1,SIZE2); 
			horizontalflip(matc,matp,SIZE1,SIZE2);
			transpose(matp,matc,SIZE1,SIZE2);
			identity(matc,matp,SIZE1,SIZE2);
			//printf("tvh \n"); 
		}
		//displaymatrix(matleast,NULL); 
		//displaymatrix(matp,NULL); 
		calculateEntry(matleast,&s1); 
		calculateEntry(matp,&s2); 

		//displayentry(s1,NULL); 
		//displayentry(s2,NULL); 

		if(compareentry(&s1,&s2)==1)
		{	
			if(convert==0)
		 		return 0;
			else
				identity(matp,matleast,SIZE1,SIZE2); 
		} 
	}
	if(convert==1)
	{
		identity(matleast,mat,SIZE1,SIZE2); //return lex least identity of matrix
	} 
	//only returns one if makes it through all parts
	return 1; 
}
int sort(char * fname, int counts, int mat[SIZE1][SIZE2])
{
	FILE * fp; 
	int n,n1,n2, inti,max,start,maxdiff;
	struct fullentry * matrices;
	int minsidelobes [MAXONES]; 
	fp=fopen(fname,"r");
	matrices=(struct fullentry *)calloc(counts,sizeof(struct fullentry)); 
	printf("Beginning to sort results \n");
	max=0;
 
	for(n=0; n<MAXONES; n++)
	{
		minsidelobes[n]=100;	
	}
	for(n=0; n<counts; n++)
	{
		for(n2=0; n2<SIZE2; n2++)
		{				
			for(n1=0; n1<SIZE1; n1++)
			{
				fscanf(fp,"%d ",&inti); 
				mat[n1][n2]=inti;
			}
			fscanf(fp,"\n ",&inti); 
		}
		lexleast(mat,1);  
		calculateFullEntry(mat,&matrices[n]);
		//displayentry(matrices[n].intrep,NULL); 
		if(matrices[n].ones>max)
			max=matrices[n].ones;
		if(minsidelobes[matrices[n].ones]>matrices[n].peaksidelobe)
			minsidelobes[matrices[n].ones]=matrices[n].peaksidelobe;   
	}
	fclose(fp);
	printf("Maximum ones reached in search is %d \n",max);
	printf("optimal sidelobe for each level \n"); 
	start=-1; 
	//
	//printf("minones %d max %d \n",MINONES,max);
	int min=100; 
	//need to be careful here, get start of range and minimum sidelobe independently
	for(n=MINONES; n<=max; n++)
	{
		//printf("%d \n",minsidelobes[n]); 
		if(minsidelobes[n]<min)
		{
			min=minsidelobes[n]; 
		}
		if(start==-1 && minsidelobes[n]!=100)
			start=n; 
		if(start!=-1)
			printf("%d ",minsidelobes[n]); 
	} 
	printf(" \n"); 
	//create matrix for storing sidelobe and length statistics, if find lower sidelobe, need to also break down by sidelobe		 
	int * counttype=(int *)calloc((max-start+1)*(MAXSIDELOBE-min+1),sizeof(int)); 
	qsort((void *)matrices,counts,sizeof(struct fullentry),comparefullentry);
	n2=0;


	//now print out only the unique entries 
	fp=fopen(fname,"w"); 
	fprintf(fp,"Matrices for maximum sidelobe %d with dimensions %d by %d \n",MAXSIDELOBE,SIZE1,SIZE2); 

        //need to print out 1st matrix in list first, code works by printing out 1st unique matrix of sorted group and ignoring the rest
	calculateMatrix(matrices[0].intrep,mat); 
	displaymatrix(mat,fp); 	
	displayentry(matrices[0].intrep,fp);
	fprintf(fp,"\n");

	
	//printf("start %d \n",start);  
	counttype[(max-start+1)*(matrices[0].peaksidelobe-min)+matrices[0].ones-start]++; 
	for(n1=0; n1<=MAXSIDELOBE; n1++)
	{
		fprintf(fp,"%d ",matrices[0].spectrum[n1]); 
	}
	fprintf(fp," \n"); 
	fprintf(fp, "ones %d, peak sidelobe %d \n \n",matrices[0].ones,matrices[0].peaksidelobe);  
	n2++;  
	maxdiff=matrices[0].ones-matrices[0].peaksidelobe;

	printf("range for table is %d ones to %d, and sidelobe %d to %d \n",max,start,MAXSIDELOBE,min); 
	printf("entering loop %d counts \n",counts); 	
 
	for(n=1; n<counts; n++)
	{
		if(compareentry(&matrices[n],&matrices[n-1])!=0) //do not print out as long as previous entry same as current entry
		{

			calculateMatrix(matrices[n].intrep,mat);
			if(matrices[n].peaksidelobe>MAXSIDELOBE)
				continue;  
			displaymatrix(mat,fp); 			
			displayentry(matrices[n].intrep,fp);
			fprintf(fp,"\n"); 
			for(n1=0; n1<=MAXSIDELOBE; n1++)
			{
				fprintf(fp,"%d ",matrices[n].spectrum[n1]); 
			}
			fprintf(fp," \n"); 
			fprintf(fp, "ones %d, peak sidelobe %d \n \n",matrices[n].ones,matrices[n].peaksidelobe);  
			//printf("%d %d \n",(max-start+1)*(matrices[n].peaksidelobe-min)+matrices[n].ones-start,(max-start+1)*(MAXSIDELOBE-min+1)); 
			//printf("%d peaksidelobe, %d ones \n",matrices[n].peaksidelobe,matrices[n].ones); 
			counttype[(max-start+1)*(matrices[n].peaksidelobe-min)+matrices[n].ones-start]++; 
			n2++; 
			if((matrices[0].ones-matrices[0].peaksidelobe)>maxdiff)
				maxdiff=(matrices[0].ones-matrices[0].peaksidelobe);
		}		
	} 
	fprintf(fp,"Total Unique matrices are %d \n",n2); 
	printf("sorted through matrices and eliminated redundant elements, have %d unique matrices out of %d \n",n2,counts); 
	fprintf(fp,"Maximum ones reached in search is %d \n",max);
	fprintf(fp,"optimal sidelobe for each level \n"); 
	for(n=start; n<=max; n++)
		fprintf(fp,"%d : %d ",n,minsidelobes[n]); 
	fprintf(fp," \n"); 
	printf("maxdiff is %d, start is %d, max is %d \n",maxdiff,start,max); 
	printf("printing out table \n"); 
	//print out table of counts to give breakdown and sidelobe and int counts for given max
	for(n1=0; n1<=(max-start); n1++)
	{
		fprintf(fp," \n");
		if(n1==0) 
			fprintf(fp,"   ");
		else
			fprintf(fp,"%d  ",n1+start);  	
		for(n2=0; n2<=(MAXSIDELOBE-min); n2++)
		{
			if(n1==0)
				fprintf(fp,"%d  ",n2+min); 
			else
				fprintf(fp,"%d  ",counttype[(max-start+1)*n2+(n1)]); 			
		}
	}
	printf("finished loop \n"); 
	//needs to also give sum of lowest diagonal corresponding to highest max
	int sum=0; 
	for(n1=0; n1<=(max-start); n1++)
	{
		//printf("%d \n",start+n1-maxdiff-minsidelobes[start]); 
		if((start+n1-maxdiff-min)>=0) //if not lined up properly can give sidelobe we did not include before
			sum=sum+counttype[(max-start+1)*(start+n1-maxdiff-min)+n1]; //need to sweep constant diffmax contour	
	}
	printf("\n \n There are %d results with optimal difference of %d \n",sum,maxdiff); 
	fprintf(fp,"\n \n There are %d results with optimal difference of %d \n",sum,maxdiff);  
	fclose(fp);
	printf("reached end \n");  
	return 0; 
}
static int
WordEntryCMP(WordEntry *a, WordEntry *b, char *buf)
{
	return compareentry(a, b, buf);
}