/*---------------------------------------------------------------------------*
* IT++ *
*---------------------------------------------------------------------------*
* Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, *
* Tobias Ringström, and Jonas Samuelsson. *
* *
* Permission to use, copy, modify, and distribute this software and its *
* documentation under the terms of the GNU General Public License is hereby *
* granted. No representations are made about the suitability of this *
* software for any purpose. It is provided "as is" without expressed or *
* implied warranty. See the GNU General Public License for more details. *
*---------------------------------------------------------------------------*/
/*!
\file
\brief Implementation of Galois Field algebra classes and functions
\author Tony Ottosson
1.8
2004/09/30 11:53:31
*/
#include "comm/galois.h"
#include <iostream>
using std::ostream;
using std::istream;
namespace itpp {
Array<Array<int> > GF::alphapow;
Array<Array<int> > GF::logalpha;
ivec GF::q="1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384";
// set q=2^mvalue
void GF::set_size(int qvalue)
{
int mtemp;
mtemp = round_i(log2(double(qvalue)));
it_assert((1<<mtemp)==qvalue, "GF::setsize : q is not a power of 2");
it_assert(mtemp<=14, "GF::setsize : q must be less than or equal to 2^14");
/* Construct GF(q), q=2^m. From Wicker, "Error Control Systems
for digital communication and storage" pp. 463-465 */
int reduce, temp, n;
const int reducetable[]={3,3,3,5,3,9,29,17,9,5,83,27,43}; // starts at m=2,..,14
it_error_if(mtemp < 1 || mtemp > 14, "createfield : m out of range");
m=mtemp;
if (alphapow.size() < (m+1) ) {
alphapow.set_size(m+1);
logalpha.set_size(m+1);
}
if (alphapow(m).size() == 0) {
alphapow(m).set_size(qvalue);
logalpha(m).set_size(qvalue);
alphapow(m) = 0;
logalpha(m) = 0;
if (m == 1) { // GF(2), special case
alphapow(1)(0)=1;
logalpha(1)(0)=-1; logalpha(1)(1)=0;
} else {
reduce=reducetable[m-2];
alphapow(m)(0)=1; // alpha^0 = 1
for (n=1; n<(1<<m)-1; n++) {
temp=alphapow(m)(n-1);
temp=(temp << 1); // multiply by alpha
if (temp & (1<<m)) // contains alpha**m term
alphapow(m)(n)=(temp & ~(1<<m))^reduce;
else
alphapow(m)(n)=temp; // if no alpha**m term, store as is
// create table to go in opposite direction
logalpha(m)(0)=-1; // special case, actually log(0)=-inf
}
for (n=0;n<(1<<m)-1;n++)
logalpha(m)(alphapow(m)(n))=n;
}
}
}
//! Output stream operator for GF
ostream &operator<<(ostream &os, const GF &ingf)
{
if (ingf.value == -1)
os << "0";
else
os << "alpha^" << ingf.value;
return os;
}
//! Output stream operator for GFX
ostream &operator<<(ostream &os, const GFX &ingfx)
{
int terms=0;
for (int i=0; i<ingfx.degree+1; i++) {
if (ingfx.coeffs(i) != GF(ingfx.q,-1) ) {
if (terms != 0) os << " + ";
terms++;
if (ingfx.coeffs(i) == GF(ingfx.q,0) ) {// is the coefficient an one (=alpha^0=1)
os << "x^" << i;
} else {
os << ingfx.coeffs(i) << "*x^" << i;
}
}
}
if (terms == 0) os << "0";
return os;
}
//----------------- Help Functions -----------------
//! Division of two GFX (local help function)
GFX divgfx(const GFX &c, const GFX &g) {
int q = c.get_size();
GFX temp = c;
int tempdegree = temp.get_true_degree();
int gdegree = g.get_true_degree();
int degreedif = tempdegree - gdegree;
if (degreedif < 0) return GFX(q,0); // denominator larger than nominator. Return zero polynomial.
GFX m(q,degreedif), divisor(q);
for (int i=0; i<c.get_degree(); i++) {
m[degreedif] = temp[tempdegree]/g[gdegree];
divisor.set_degree(degreedif);
divisor.clear();
divisor[degreedif] = m[degreedif];
temp -= divisor*g;
tempdegree = temp.get_true_degree();
degreedif = tempdegree - gdegree;
if ( (degreedif<0) || (temp.get_true_degree()==0 && temp[0] == GF(q,-1) ) ) {
break;
}
}
return m;
}
//! Modulo function of two GFX (local help function)
GFX modgfx(const GFX &a, const GFX &b)
{
int q = a.get_size();
GFX temp = a;
int tempdegree = temp.get_true_degree();
int bdegree = b.get_true_degree();
int degreedif = a.get_true_degree() - b.get_true_degree();
if (degreedif < 0) return temp; // Denominator larger than nominator. Return nominator.
GFX m(q,degreedif), divisor(q);
for (int i=0; i<a.get_degree(); i++) {
m[degreedif] = temp[tempdegree]/b[bdegree];
divisor.set_degree(degreedif);
divisor.clear();
divisor[degreedif] = m[degreedif];
temp -= divisor*b; // Bug-fixed. Used to be: temp -= divisor*a;
tempdegree = temp.get_true_degree();
degreedif = temp.get_true_degree() - bdegree;
if ( (degreedif<0) || (temp.get_true_degree()==0 && temp[0] == GF(q,-1) ) ) {
break;
}
}
return temp;
}
} //namespace itpp
syntax highlighted by Code2HTML, v. 0.9.1