Files
cuetools.net/CUETools.Parity/Galois.cs
2010-02-18 21:12:44 +00:00

333 lines
12 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Parity
{
public class Galois
{
private ushort[] expTbl; // 二重にもつことによりmul, div等を簡略化
private ushort[] logTbl;
private int w;
private int max;
private int symStart = 0;
/**
* スカラー、ベクターの相互変換テーブルの作成
*/
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;
}
}
/**
* スカラー -> ベクター変換
*
* @param a int
* @return int
*/
public int toExp(int a)
{
return expTbl[a];
}
/**
* ベクター -> スカラー変換
*
* @param a int
* @return int
*/
public int toLog(int a)
{
return logTbl[a];
}
/**
* 誤り位置インデックスの計算
*
* @param length int
* データ長
* @param a int
* 誤り位置ベクター
* @return int
* 誤り位置インデックス
*/
public int toPos(int length, int a)
{
return length - 1 - logTbl[a];
}
/**
* 掛け算
*
* @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]];
}
/**
* 掛け算
*
* @param a int
* @param b int
* @return int
* = a * α^b
*/
public int mulExp(int a, int b)
{
return (a == 0) ? 0 : expTbl[logTbl[a] + b];
}
/**
* 割り算
*
* @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];
}
/**
* 割り算
*
* @param a int
* @param b int
* @return int
* = a / α^b
*/
public int divExp(int a, int b)
{
return (a == 0) ? 0 : expTbl[logTbl[a] - b + max];
}
/**
* 逆数
*
* @param a int
* @return int
* = 1/a
*/
public int inv(int a)
{
return expTbl[max - logTbl[a]];
}
/**
* 数式の掛け算
*
* @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]
}
}
}
}
}
/**
* 生成多項式配列の作成
* G(x)=Π[k=0,n-1](x + α^k)
* encodeGxの添え字と次数の並びが逆なのに注意
* encodeGx[0] = x^(npar - 1)の項
* encodeGx[1] = x^(npar - 2)の項
* ...
* encodeGx[npar - 1] = x^0の項
*/
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 = α^kou
// (x + α^kou)を掛る
for (int j = 0; j < npar - 1; j++)
{
// 現在の項 * α^kou + 一つ下の次数の項
encodeGx[j] = mul(encodeGx[j], ex) ^ encodeGx[j + 1];
}
encodeGx[npar - 1] = mul(encodeGx[npar - 1], ex);// 最下位項の計算
}
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;
}
/**
* シンドロームの計算
* @param data int[]
* 入力データ配列
* @param length int
* データ長
* @param syn int[]
* (x - α^0) (x - α^1) (x - α^2) ...のシンドローム
* @return boolean
* true: シンドロームは総て0
*/
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 * α^i
wk = data[idx] ^ ((wk == 0) ? 0 : expTbl[logTbl[wk] + i]); // wk = data + wk * α^i
}
syn[i] = wk;
hasErr |= wk;
}
return hasErr == 0;
}
/**
* シンドロームの計算
* @param data int[]
* 入力データ配列
* @param length int
* データ長
* @param syn int[]
* (x - α^0) (x - α^1) (x - α^2) ...のシンドローム
* @return boolean
* true: シンドロームは総て0
*/
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 * α^i
wk = data[idx] ^ ((wk == 0) ? 0 : expTbl[logTbl[wk] + i]); // wk = data + wk * α^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)
{
}
}
}