// Note: this class is designed to utilize a Zech log table over F_15.
// The only function that uses this is BCH_15_algdecode in proj1; if 
// we do not use that particular decoder (for example, if we choose to
// decode via exhaustive search), this class can be commented out. 

#include <iostream>
#include <math.h>
#include "graph_holder.h"

alpha_exp multiply(alpha_exp a1, alpha_exp a2);
alpha_exp add( alpha_exp a1, alpha_exp a2);
int max(int x, int y);
int min(int x, int y);
extern void press_enter();
char equals (alpha_exp a1, alpha_exp a2);
alpha_exp divide_exp (alpha_exp a1, alpha_exp a2);
alpha_exp compute_sum (alpha_exp k);


int H[4][15] = {{1,0,0,0,1,0,0,1,1,0,1,0,1,1,1},
{0,1,0,0,1,1,0,1,0,1,1,1,1,0,0},
{0,0,1,0,0,1,1,0,1,0,1,1,1,1,0},
{0,0,0,1,0,0,1,1,0,1,0,1,1,1,1}};


int alpha;
int zech[14] = {4,8,14,1,10,13,9,2,7,5,12,11,6,3};


alpha_exp::alpha_exp(int n1, int n2, int n3, int n4) {
	int i;	

	//-1 means the zero vector
	
	
alpha = -1; 
	for (i=0;i<15;i++) {
		if (H[0][i] == n1 && H[1][i] == n2 && H[2][i] == n3 && H[3][i] == n4) {
			alpha = i;
			//std::cout << i << " works! alpha = " << i;
		}
	
	}
	//std::cout << "\n constructor set alpha to  " << alpha;
}

alpha_exp::alpha_exp(int a) {
	alpha = a;
}


alpha_exp multiply_exp (alpha_exp a1, alpha_exp a2) {
   alpha_exp ret(-1);
	if (a1.alpha == -2 || a2.alpha == -2) 
		ret.alpha = -2;
    if (a1.alpha == -1  || a2.alpha == -1)
		ret.alpha = -1;
	else
		 ret.alpha = (a1.alpha + a2.alpha)%15;
	return ret;
}

alpha_exp divide_exp (alpha_exp a1, alpha_exp a2) {
	alpha_exp ret(-1);

	if (a1.alpha == -1) {
		ret.alpha = -1;
	}

	if (a1.alpha != -1 && a2.alpha == -1){
		ret.alpha = -2;
	}
	
	if (a1.alpha != -1 && a2.alpha != -1) {
    int exp = a1.alpha - a2.alpha;
	if (exp >= 0)
		exp = exp%15;
	else
		exp = 15-abs(exp%15);
	 ret.alpha = exp;
	}
	return ret;
}

alpha_exp add_exp ( alpha_exp a1, alpha_exp a2) {
	int mi = min(a1.alpha,a2.alpha);
	int ma = max(a1.alpha,a2.alpha);
	alpha_exp ret(-1);
	
	if (mi != ma) {

	//std::cout << "\n minimum exponent: " << mi;
	//std::cout << "\n maximum exponent: " << ma;
//	press_enter();
	alpha_exp A(mi);
	alpha_exp B(zech[ma - mi-1]);
	//std::cout << "\n max - min - 1 " <<  ma - mi - 1;
	//std::cout << "\n zech[max - min - 1] "  << zech[ma - mi-1];
	 ret = multiply_exp(A,B);
	}
	return ret;
}
alpha_exp power_exp (alpha_exp a1, int power) {
	alpha_exp ret(0,0,0,0);
if (a1.alpha >= 0) {
	ret.alpha = (a1.alpha * power)%15;
}
else { 
ret.alpha = 15-abs((a1.alpha * power)%15);
}

return ret;

}



char equals (alpha_exp a1, alpha_exp a2) {
	char ret;
	if (a1.alpha % 15 == a2.alpha % 15)
		ret = 1;
	else
		ret = 0;

	return ret;
}

int max(int x, int y)
{
    if (x >= y)
    {
        return x;
    }
    return y;
}

int min(int x, int y)
{
    if (x <= y)
    {
        return x;
    }
    return y;
}