mirror of
https://github.com/claunia/cuetools.net.git
synced 2025-12-16 18:14:25 +00:00
333 lines
12 KiB
C#
333 lines
12 KiB
C#
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)
|
||
{
|
||
}
|
||
}
|
||
}
|