#include <iostream>
#include "graph_holder.h"
#include <math.h>
#include <list>
#include <cstdlib>
#include <ctime>

using namespace std;

extern void swap_int (int *num1, int *num2);
extern void permute(int *array, int array_size);
extern void Hamming7_decode(int *input, int *output);
extern void matrix_multiply(int *vector_input, int *matrix, int *vector_output, int matrix_rows, int matrix_cols);
extern void press_enter();
extern void BCH15_alg_decode(int *input, int *output);
extern void BCH15_ML_decode(int *input, int *output);
extern void Transpose(int *matrix_in, int rows,int columns, int *matrix_out);
extern void matrix_matrix_multiply(int *matrix_input_left, int *matrix_input_right,
	int *matrix_output, int left_matrix_rows, int left_matrix_cols, 
	int right_matrix_cols);
extern int Hamming_distance(int *word1, int *word2, int size) ;
extern quaternion multiply(quaternion x, quaternion y);
extern quaternion add(quaternion x, quaternion y);
extern quaternion subtract(quaternion x,quaternion y);
extern quaternion divisor(quaternion arg1, quaternion arg2);
extern quaternion remainder(quaternion ar1, quaternion arg2, quaternion div);
extern quaternion gcd(quaternion arg1,quaternion arg2);
extern void find_xy(int p, int *x, int *y);
extern quaternion find_qsquare( int p);
extern alpha_exp add_exp(alpha_exp a1, alpha_exp a2);
extern alpha_exp multiply_exp (alpha_exp a1, alpha_exp a2);
extern char equals (alpha_exp a1, alpha_exp a2);
extern alpha_exp divide_exp( alpha_exp a1, alpha_exp a2);
extern alpha_exp power_exp( alpha_exp a1, int power);
extern alpha_exp compute_sum (alpha_exp k);
extern int pp(int base, int exp);
extern int trace(alpha_exp a);
extern int four_squar(int num, decomposition **d_ptr);
extern void reduce_decomp(decomposition *d_ptr,int ps, int q);
extern int embed(decomposition *d_ptr, int size, int p, int q, mtwo **m_ptr, int up_lim);
extern void distinguished(decomposition *d_ptr, decomposition *nd, int size, int p);
extern int equals_mtwo(mtwo a, mtwo b, int q);
extern int gen_mat(mtwo **mats, int q);
extern int eqa(mtwo a, mtwo *b, int sz, int q); 
extern int gcdn(int a, int b, int *s, int *t);
extern int inverse_field (int e, int p) ;
extern int reduceq( int e, int q);
extern int normal_mtwo_equals(mtwo a, mtwo b);
extern mtwo mult(mtwo x, int a, int p);
extern mtwo mmultiply(mtwo a, mtwo b, int q);
extern int find_m(mtwo m, mtwo *group, int sizegr, int q);
extern void create_ramanujan(mtwo *group1, int sizegr1, mtwo *group2, int sizegr2, int *mtrx, int p, int q);
int read_line(char *buf, int ln, FILE *fptr, int ls);


void RM16_decode(int *input, int *output) {
	FILE *fptr=0;
	  int i;
//	  std::cout << "\n recieved: ";
//	  for(i=0;i<16;i++)
//		  std::cout << " " << input[i];

	



int parmat[11][16]=     {{0,   1,   1,   0,   1,   1,   0,   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}, 
  {0,   1,   0,   1,   1,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0}, 
  {1,   0,   0,   1,   1,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0}, 
  {1,   1,   1,   1,   1,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0,   0}, 
  {1,   1,   1,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0,   0}, 
  {1,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   0}, 
  {1,   0,   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0}, 
  {0,   1,   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,   0}, 
  {0,   0,   1,   1,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0}, 
  {1,   1,   0,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1}};

  int syndrome[11][1];
  matrix_matrix_multiply(parmat[0], input,
	syndrome[0],11 , 16
	, 1);

  //std::cout << "\n syndrome:";

  for(i=0;i<11;i++)
	  syndrome[i][0]=syndrome[i][0]%2;
 // for(i=0;i<11;i++)
//	  std::cout << " " << syndrome[i][0];
  int number = syndrome[10][0]+syndrome[9][0]*2+syndrome[8][0]*4+syndrome[7][0]*8+syndrome[6][0]*16+
	  syndrome[5][0]*32+syndrome[4][0]*64+syndrome[3][0]*128+syndrome[2][0]*256+syndrome[1][0]*512+
	  syndrome[0][0]*1024;
 // std::cout << "\n number = " << number;
  fptr=fopen("c:/proj1/trn_mtr.txt", "r");
        if (!fptr)        {
                std::cout << "can't open trn_mtr.txt";
                exit(1);
        }

       char trt[16];


                read_line(trt, 1+number, fptr,16);


        // using buf[i]:

            

        fclose(fptr);

  for(i=0;i<16;i++)
	  output[i]=(input[i]+trt[i])%2;

}

int read_line(char *buf, int ln, FILE *fptr, int ls)
        {
                char *ptr;
                int n;

                n=fseek(fptr, (ls+2)*(ln-1),SEEK_SET);
                if (n)        {
                        std::cout << "\nfseek error";
                        exit(1);
                }
                ptr =fgets( buf, ls+2, fptr);
                 if (!ptr){
                        std::cout << "\ncan't read trn_mtx.txt ";
                        exit(1);
                }
                
                return (1);
}
