Galois Field

by evgkch

JavaScript

const reverseStr = str => str.split('').reverse().join('');

const vecToVal = str => parseInt(reverseStr(str), 2);
const valToVec = (x, length = 0) => reverseStr(x.toString(2).padStart(length, '0'));

// ni - number of inputs
// x  - output vector as a number
const ZPx = (ni, x) => {
	if (ni === 0)
  	return x;
  else
  {
	  const p = 2 ** (ni - 1);
  	const fst = x & ((1 << p) - 1),
    			scd = x >> p;
          
    return ZPx(ni - 1, fst) ^ (ZPx(ni - 1, fst ^ scd) << p);
  }
};

const ZPv = (ni, outVec) => {
	return valToVec(ZPx(ni, vecToVal(outVec)), 2 ** ni);
}

const makeMask = (inputs, mask) => {
	return inputs.filter((_, i) => Number(mask[i]));
}

const makeZPoly = (inputs, outVec) => {
	const ni = inputs.length;
  const vec = ZPv(ni, outVec);
  const vecLength = vec.length;
  
  let polyArr = [];
  
  if (Number(vec[0]))
  	polyArr.push('1');
  
  for (let i = 1; i < vecLength; i++) {
  	if (Number(vec[i]))
    {
    	const mask = valToVec(i, ni);
    	const maskedArr = makeMask(inputs, mask);
      polyArr.push(maskedArr.join(' '))
    }
  }
  
  return polyArr.join(' + ');
}

const forEachSymbolsPair = (symbols, cb) => {
	for (let i = 0; i < symbols.length; i++)
  {
  	for (let j = 0; j < symbols.length; j++)
    {
			cb(symbols[i] + symbols[j]);
    }
  }
} 

const makeGF2 = (order, dict, table) => {
	const length = dict['0'].length;
  const vecs = Array.from({ length }, (_, k) => '');
  
  forEachSymbolsPair(order, s => {
  	const output = dict[table[s]];
		for (let i = 0; i < length; i++)
    {
    	vecs[i] += output[i];
    }
  }); 
  
	return vecs.reverse();
}

{
const dictGF4 = {
	'0': '00',
  '1': '01',
  'a': '10',
  'b': '11'
};

const orderGF4 = ['0', '1', 'a', 'b'];

const mulFG4 = {
	'00': '0',
  '01': '0',
  '0a': '0',
  '0b': '0',
  '10': '0',
  '11': '1',
  '1a': 'a',
  '1b': 'b',
  'a0': '0',
  'a1': 'a',
  'aa': 'b',
  'ab': '1',
  'b0': '0',
  'b1': 'b',
  'ba': '1',
  'bb': 'a',
};

const addFG4 = {
	'00': '0',
  '01': '1',
  '0a':...