/*
	GALOISFIELD

	This Package is written by Jan Struyf
	URL: http://ace.ulyssis.student.kuleuven.ac.be/~jeans
	EMail: jan.struyf@student.kuleuven.ac.be
	Post:	Jan Struyf, Hoogstraat 47, 3360 Bierbeek, BELGIUM

	You can do anything with it, if you leave this comment field unmodified.
*/

import java.util.Vector;

public class CyclicCode {
	int n, pwr, beta;
	GaloisField base, extfield;
	GaloisPolynomial gx, hx;
	
	public CyclicCode(GaloisField newbase, int newn) throws GaloisException {
		base = newbase;
		n = newn;
	
		int[] res = base.getKPrimitiveNRoot(n);
		pwr = res[0]; beta = res[1];

		base.setDisplayMode(GaloisField.POLYCOEFS);
		
		if (pwr == 1) extfield = base;
		else extfield = new ExtendedGaloisField(base,'W',pwr);
	}	

	public Vector getCyclotomics() {
		return extfield.getBase().getAllCyclotomics(n);
	}

	public void calcGandH(int[] sel) throws GaloisException {
		gx = calcGorH(sel,true);
		hx = calcGorH(sel,false);
	}

	public GaloisPolynomial getGenerator() {
		return gx;
	}

	public GaloisPolynomial getParity() {
		return hx;
	}

	public GaloisPolynomial calcGorH(int[] sel, boolean selCrit) throws GaloisException {
		Vector mycyclos = getCyclotomics();
		GaloisPolynomial res = 
			GaloisPolynomial.createConstant(GaloisField.ONE,'x',extfield.getBase());
		for (int ctr = 0; ctr < mycyclos.size(); ctr++) {
			boolean ntfound = true;
			for (int tel = 0; tel < sel.length && ntfound; tel++) {
				if (ctr == sel[tel]) ntfound = false;
			}
			if (ntfound != selCrit) {
				int[] mycyclo = (int[])mycyclos.elementAt(ctr);
				int mypwr = mycyclo[0];
				int alfapwr = mypwr * beta;
				GaloisPolynomial primpol = 
					extfield.getMinimalPolynomial(alfapwr,'x');
				res = res.product(primpol);			
			}
		}
		return res;
	}

	public GaloisField getField() {
		return base;
	}

	public GaloisField getExtField() {
		return extfield;
	}

	public int getBeta() {
		return beta;
	}

	public int getK() {
		return getN() - getGenerator().degree();
	}

	public int getN() {
		return n;
	}

	public GaloisPolynomial encode(GaloisPolynomial poly) throws GaloisException {
		if (poly.degree() >= getK())
			throw new GaloisException("encode: Information word too long",GaloisException.CODE);
		GaloisPolynomial generator = getGenerator();
		generator = generator.toExtended(poly.getField());
		return poly.product(generator);
	}

	public GaloisPolynomial syndrome(GaloisPolynomial poly) throws GaloisException {
		if (poly.degree() >= n)
			throw new GaloisException("syndrome: Code word too long",GaloisException.CODE);
		GaloisPolynomial generator = getGenerator();
		generator = generator.toExtended(poly.getField());
		GaloisPolynomial divres[] = poly.divide(generator);
		return divres[1];
	}

	public static int getKPower(GaloisField newbase, int newn) {
		int[] res = newbase.getKPrimitiveNRoot(newn);
		return res[0]; 
	}
}
