#include <iostream>
#include "graph_holder.h"
#include <math.h>

int find_row_index(int *matrix, int m, int n, int *row);
int find_row(int *matrix, int m, int n, int *row);
void gen_synd(int *parmat,int *syndrome_tab,int *err_pat);
extern void press_enter();

void rm36decode(int *input, int *output) {


	int parmat[22][62]=     {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 
  {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, 
  {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, 
  {0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 
  {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0}, 
  {0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, 
  {0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, 
  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

static int syndrome_tab[4*1024*1024*22];
static int err_pat[4*1024*1024*62];

gen_synd((int *)parmat,syndrome_tab,err_pat);

}

void gen_synd(int *parmat,int *syndrome_tab,int *err_pat) {
	
int i=0,j,ind1,ind2,ind3,ind4,ind5;
int q=0;
int temp_r[22];
std::cout << "\n before commands";
memset(err_pat,0, 4*1024*1024*62 * sizeof(int));
//for(i=0;i<4*1024*1024*62;i++)
//	err_pat[i]=0;
std::cout << "\n after first memset";
memset(syndrome_tab,0, 22 * sizeof(int));
std::cout << "\n after second memset";
press_enter();


for(i=1;i<63;i++) {
	err_pat[62*i-1+i]=1;
	for(j=0;j<22;j++) 
		syndrome_tab[i*22+j]=parmat[j*62+i-1];
}
i=63;
std::cout << "\n after first loop";
	for(ind1=0;ind1<62-1;ind1++) {
		for(ind2=ind1+1;ind2<62;ind2++) {
			err_pat[i*62+ind1]=1;
			err_pat[i*62+ind2]=1;
			for(j=0;j<22;j++) {
				syndrome_tab[i*22+j] = (parmat[j*22+ind1]+parmat[j*22+ind2])%2;
				}
			i++;
			}
		}

std::cout << "\n after second loop";

	for(ind1=0;ind1<62-2;ind1++) {
		for(ind2=ind1+1;ind2<62-1;ind2++) {
			for(ind3=ind2+1;ind3<62;ind3++) {
				//std::cout << "\n i = " << i; 
				for(j=0;j<22;j++) {
					temp_r[j] = (parmat[j*62+ind1]+parmat[j*62+ind2]+parmat[j*62+ind3])%2;
								  }
				
					for(j=0;j<22;j++) 
					syndrome_tab[i*22+j]=temp_r[j];
					err_pat[i*62+ind1]=1;
					err_pat[i*62+ind2]=1;
					err_pat[i*62+ind3]=1;
					i++;

				
				
				
				




															
											}


										  }


								 }

std::cout << "\n after third loop";

		for(ind1=0;ind1<62-3;ind1++) {
		for(ind2=ind1+1;ind2<62-2;ind2++) {
			for(ind3=ind2+1;ind3<62-1;ind3++) {
				for(ind4=ind3+1;ind4<62;ind4++) {
					if(i%1000==0)
				std::cout << "\n i = " << i; 
				for(j=0;j<22;j++) {
					temp_r[j] = (parmat[j*62+ind1]+parmat[j*62+ind2]+parmat[j*62+ind3]+parmat[j*62+ind4])%2;
								  }
				
					for(j=0;j<22;j++) 
					syndrome_tab[i*22+j]=temp_r[j];
					err_pat[i*62+ind1]=1;
					err_pat[i*62+ind2]=1;
					err_pat[i*62+ind3]=1;
					err_pat[i*62+ind4]=1;
					i++;

				
				
				
				


				}

															
											}


										  }


								 }
		std::cout << "\n after fourth loop";



		for(ind1=0;ind1<62-4;ind1++) {
		for(ind2=ind1+1;ind2<62-3;ind2++) {
			for(ind3=ind2+1;ind3<62-2;ind3++) {
				for(ind4=ind3+1;ind4<62-1;ind4++) {
					for(ind5=ind4+1;ind5<62;ind5++) {
			if(i % 10000==0)		
				std::cout << "\n i = " << i; 
				for(j=0;j<22;j++) {
					temp_r[j] = (parmat[j*62+ind1]+parmat[j*62+ind2]+parmat[j*62+ind3]+parmat[j*62+ind4]+parmat[j*62+ind5])%2;
								  }
			//	if (find_row(syndrome_tab,i,22,temp_r)==0) {
					for(j=0;j<22;j++) 
					syndrome_tab[i*22+j]=temp_r[j];
					err_pat[i*62+ind1]=1;
					err_pat[i*62+ind2]=1;
					err_pat[i*62+ind3]=1;
					err_pat[i*62+ind4]=1;
					err_pat[i*62+ind5]=1;
					i++;

				
			//	}
				
					}


				}

															
											}


										  }


								 }


		

std::cout << "i = " << i;
press_enter();
/*
int k;
std::cout << "\n Error Matrix: ";
for(k=0;k<i;k++) {
	std::cout << "\n k = "<<k<< ": ";
	for(j=0;j<62;j++)
		std::cout << " " << (int) err_pat[k*62+j];
}

press_enter();
std::cout << "\n Syndrome Matrix: ";
for(k=0;k<i;k++) {
	std::cout << "\n k = " << k << ": ";
	for(j=0;j<22;j++)
		std::cout << " " << (int) syndrome_tab[k*10+j];
}

press_enter(); */

}

int find_row_index(int *matrix, int m, int n, int *row) {
// This function finds whether a row is present within a matrix.
// It takes as its input an matrix "matrix", represented as an 
// array of size "m"x"n", where the matrix is assumed to be "m" by "n"
// It returns 1 if "row" is one of the rows of this matrix and zero 
// otherwise. 
	int i,j;
	int ret=-1;
	/*	std::cout << "\n Matrix:";
		for(i=0;i<10;i++) {
			std::cout << "\n";
			for(j=0;j<n;j++) {
				std::cout << " " << (int) matrix[i*n+j];
			}
		}
		press_enter(); */

/*	std::cout << "\n find_row called!";
	std::cout << "\n m = " << m << " and n = " << n;
	std::cout << "\n the row is: \n " ;
		for(j=0;j<n;j++)
			std::cout << " " << row[j];
*/
		


	for(i=0;i<m;i++) {
		for(j=0;j<n;j++) {
			if (matrix[i*n+j]!=row[j])
				break;
			if (j==n-1)
				ret=i;
		}
	}

return ret;
}



int find_row(int *matrix, int m, int n, int *row) {
// This function finds whether a row is present within a matrix.
// It takes as its input an matrix "matrix", represented as an 
// array of size "m"x"n", where the matrix is assumed to be "m" by "n"
// It returns 1 if "row" is one of the rows of this matrix and zero 
// otherwise. 
	int i,j;
	char ret=0;\
	/*	std::cout << "\n Matrix:";
		for(i=0;i<10;i++) {
			std::cout << "\n";
			for(j=0;j<n;j++) {
				std::cout << " " << (int) matrix[i*n+j];
			}
		}
		press_enter(); */

/*	std::cout << "\n find_row called!";
	std::cout << "\n m = " << m << " and n = " << n;
	std::cout << "\n the row is: \n " ;
		for(j=0;j<n;j++)
			std::cout << " " << row[j];
*/
		


	for(i=0;i<m;i++) {
	//	std::cout << "\n row = " << i;
	/*		if(i==433) {
					std::cout << "\n stop";
					std::cout << "\n stop";
					std::cout << "\n stop";
				} */

		for(j=0;j<n;j++) {
	/*		if (i==433) {
		std::cout << "\n n-1 = " << n-1;
		std::cout << "\n column = " << j;
			} */
			if (matrix[i*n+j]!=row[j])
				break;
			if (j==n-1)
				ret=1;
		}
	}

return ret;
}
