Files
cuetools.net/CUETools.Parity/Galois.cs

333 lines
12 KiB
C#
Raw Normal View History

2010-02-18 21:12:44 +00:00
<EFBFBD><EFBFBD>using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Parity
{
public class Galois
{
private ushort[] expTbl; // <EFBFBD>N͑k0<EFBFBD>0d0S0h0k0<EFBFBD>0<EFBFBD>0mul, divI{<EFBFBD>0!|euS
private ushort[] logTbl;
private int w;
private int max;
private int symStart = 0;
/**
* <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>00<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0n0<EFBFBD>v<EFBFBD>N Y<EFBFBD>c<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0n0\Ob
*/
public Galois(int polynomial, int _w)
{
w = _w;
max = (1 << _w) - 1;
expTbl = new ushort[max * 2];
logTbl = new ushort[max + 1];
int d = 1;
for (int i = 0; i < max; i++)
{
//if (d == 0)
// throw new Exception("oops");
expTbl[i] = expTbl[max + i] = (ushort)d;
logTbl[d] = (ushort)i;
d <<= 1;
if (((d >> _w) & 1) != 0)
d = (d ^ polynomial) & max;
}
}
public int Max
{
get
{
return max;
}
}
public ushort[] ExpTbl
{
get
{
return expTbl;
}
}
public ushort[] LogTbl
{
get
{
return logTbl;
}
}
/**
* <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0 -> <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0 Y<EFBFBD>c
*
* @param a int
* @return int
*/
public int toExp(int a)
{
return expTbl[a];
}
/**
* <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0 -> <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0 Y<EFBFBD>c
*
* @param a int
* @return int
*/
public int toLog(int a)
{
return logTbl[a];
}
/**
* <EFBFBD><EFBFBD><EFBFBD>0MOn<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0n0<EFBFBD><EFBFBD>{
*
* @param length int
* <EFBFBD>0<EFBFBD>0<EFBFBD>0w<EFBFBD>
* @param a int
* <EFBFBD><EFBFBD><EFBFBD>0MOn<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0
* @return int
* <EFBFBD><EFBFBD><EFBFBD>0MOn<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0
*/
public int toPos(int length, int a)
{
return length - 1 - logTbl[a];
}
/**
* <EFBFBD>cQ0<EFBFBD>{
*
* @param a int
* @param b int
* @return int
* = a * b
*/
public int mul(int a, int b)
{
return (a == 0 || b == 0) ? 0 : expTbl[(int)logTbl[a] + logTbl[b]];
}
/**
* <EFBFBD>cQ0<EFBFBD>{
*
* @param a int
* @param b int
* @return int
* = a * <EFBFBD>^b
*/
public int mulExp(int a, int b)
{
return (a == 0) ? 0 : expTbl[logTbl[a] + b];
}
/**
* rR<EFBFBD>0<EFBFBD>{
*
* @param a int
* @param b int
* @return int
* = a / b
*/
public int div(int a, int b)
{
return (a == 0) ? 0 : expTbl[logTbl[a] - logTbl[b] + max];
}
/**
* rR<EFBFBD>0<EFBFBD>{
*
* @param a int
* @param b int
* @return int
* = a / <EFBFBD>^b
*/
public int divExp(int a, int b)
{
return (a == 0) ? 0 : expTbl[logTbl[a] - b + max];
}
/**
* <EFBFBD>pe
*
* @param a int
* @return int
* = 1/a
*/
public int inv(int a)
{
return expTbl[max - logTbl[a]];
}
/**
* pe_n0<EFBFBD>cQ0<EFBFBD>{
*
* @param seki int[]
* seki = a * b
* @param a int[]
* @param b int[]
*/
public void mulPoly(int[] seki, int[] a, int[] b)
{
Array.Clear(seki, 0, seki.Length);
for (int ia = 0; ia < a.Length; ia++)
{
if (a[ia] != 0)
{
int loga = logTbl[a[ia]];
int ib2 = Math.Min(b.Length, seki.Length - ia);
for (int ib = 0; ib < ib2; ib++)
{
if (b[ib] != 0)
{
seki[ia + ib] ^= expTbl[loga + logTbl[b[ib]]]; // = a[ia] * b[ib]
}
}
}
}
}
public unsafe void mulPoly(int* seki, int* a, int* b, int lenS, int lenA, int lenB)
{
for (int i = 0; i < lenS; i++)
seki[i] = 0;
for (int ia = 0; ia < lenA; ia++)
{
if (a[ia] != 0)
{
int loga = logTbl[a[ia]];
int ib2 = Math.Min(lenB, lenS - ia);
for (int ib = 0; ib < ib2; ib++)
{
if (b[ib] != 0)
{
seki[ia + ib] ^= expTbl[loga + logTbl[b[ib]]]; // = a[ia] * b[ib]
}
}
}
}
}
/**
* ubY<EFBFBD>_M<EFBFBD>Rn0\Ob
* G(x)=<EFBFBD>[k=0,n-1](x + <EFBFBD>^k)
* encodeGxn0<EFBFBD>mH0W[h0!kpen0&Ns0L0<EFBFBD>j0n0k0<EFBFBD>la
* encodeGx[0] = x^(npar - 1)n0<EFBFBD>
* encodeGx[1] = x^(npar - 2)n0<EFBFBD>
* ...
* encodeGx[npar - 1] = x^0n0<EFBFBD>
*/
public int[] makeEncodeGx(int npar)
{
int[] encodeGx = new int[npar];
encodeGx[npar - 1] = 1;
for (int i = 0, kou = symStart; i < npar; i++, kou++)
{
int ex = toExp(kou); // ex = <EFBFBD>^kou
// (x + <EFBFBD>^kou)<EFBFBD>0<EFBFBD>c<EFBFBD>0
for (int j = 0; j < npar - 1; j++)
{
// <EFBFBD>s(Wn0<EFBFBD> * <EFBFBD>^kou + Nd0 Nn0!kpen0<EFBFBD>
encodeGx[j] = mul(encodeGx[j], ex) ^ encodeGx[j + 1];
}
encodeGx[npar - 1] = mul(encodeGx[npar - 1], ex);// g NMO<EFBFBD>n0<EFBFBD><EFBFBD>{
}
return encodeGx;
}
public int[] makeEncodeGxLog(int npar)
{
int[] encodeGx = makeEncodeGx(npar);
for (int i = 0; i < npar; i++)
{
if (encodeGx[i] == 0)
throw new Exception("0 in encodeGx");
encodeGx[i] = toLog(encodeGx[i]);
}
return encodeGx;
}
/**
* <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0n0<EFBFBD><EFBFBD>{
* @param data int[]
* eQ<EFBFBD>R<EFBFBD>0<EFBFBD>0<EFBFBD>0M<EFBFBD>R
* @param length int
* <EFBFBD>0<EFBFBD>0<EFBFBD>0w<EFBFBD>
* @param syn int[]
* (x - <EFBFBD>^0) (x - <EFBFBD>^1) (x - <EFBFBD>^2) ...n0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0
* @return boolean
* true: <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0o0<EFBFBD>}f00
*/
public bool calcSyndrome(byte[] data, int length, int[] syn)
{
int hasErr = 0;
for (int i = 0; i < syn.Length; i++)
{
int wk = 0;
for (int idx = 0; idx < length; idx++)
{
//wk = data[idx] ^ ((wk == 0) ? 0 : expTbl[logTbl[wk] + i + symStart]); // wk = data + wk * <EFBFBD>^i
wk = data[idx] ^ ((wk == 0) ? 0 : expTbl[logTbl[wk] + i]); // wk = data + wk * <EFBFBD>^i
}
syn[i] = wk;
hasErr |= wk;
}
return hasErr == 0;
}
/**
* <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0n0<EFBFBD><EFBFBD>{
* @param data int[]
* eQ<EFBFBD>R<EFBFBD>0<EFBFBD>0<EFBFBD>0M<EFBFBD>R
* @param length int
* <EFBFBD>0<EFBFBD>0<EFBFBD>0w<EFBFBD>
* @param syn int[]
* (x - <EFBFBD>^0) (x - <EFBFBD>^1) (x - <EFBFBD>^2) ...n0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0
* @return boolean
* true: <EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0<EFBFBD>0o0<EFBFBD>}f00
*/
public unsafe bool calcSyndrome(ushort* data, int length, int[] syn)
{
int hasErr = 0;
for (int i = 0; i < syn.Length; i++)
{
int wk = 0;
for (int idx = 0; idx < length; idx++)
{
//wk = data[idx] ^ ((wk == 0) ? 0 : expTbl[logTbl[wk] + i + symStart]); // wk = data + wk * <EFBFBD>^i
wk = data[idx] ^ ((wk == 0) ? 0 : expTbl[logTbl[wk] + i]); // wk = data + wk * <EFBFBD>^i
}
syn[i] = wk;
hasErr |= wk;
}
return hasErr == 0;
}
}
public class Galois81D: Galois
{
public const int POLYNOMIAL = 0x1d;
public static Galois81D instance = new Galois81D();
Galois81D()
: base(POLYNOMIAL, 8)
{
}
}
public class Galois16 : Galois
{
public const int POLYNOMIAL = 0x1100B;
public static Galois16 instance = new Galois16();
Galois16()
: base(POLYNOMIAL, 16)
{
}
}
}