init commit
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
namespace MessagingToolkit.QRCode.Codec.Ecc;
|
||||
|
||||
public class BCH15_5
|
||||
{
|
||||
internal int[][] gf16;
|
||||
|
||||
internal bool[] recieveData;
|
||||
|
||||
internal int numCorrectedError;
|
||||
|
||||
internal static string[] bitName = new string[15]
|
||||
{
|
||||
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9",
|
||||
"d0", "d1", "d2", "d3", "d4"
|
||||
};
|
||||
|
||||
public virtual int NumCorrectedError => numCorrectedError;
|
||||
|
||||
public BCH15_5(bool[] source)
|
||||
{
|
||||
gf16 = createGF16();
|
||||
recieveData = source;
|
||||
}
|
||||
|
||||
public virtual bool[] correct()
|
||||
{
|
||||
int[] s = calcSyndrome(recieveData);
|
||||
int[] errorPos = detectErrorBitPosition(s);
|
||||
return correctErrorBit(recieveData, errorPos);
|
||||
}
|
||||
|
||||
internal virtual int[][] createGF16()
|
||||
{
|
||||
gf16 = new int[16][];
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
gf16[i] = new int[4];
|
||||
}
|
||||
int[] array = new int[4] { 1, 1, 0, 0 };
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
gf16[i][i] = 1;
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
gf16[4][i] = array[i];
|
||||
}
|
||||
for (int i = 5; i < 16; i++)
|
||||
{
|
||||
for (int j = 1; j < 4; j++)
|
||||
{
|
||||
gf16[i][j] = gf16[i - 1][j - 1];
|
||||
}
|
||||
if (gf16[i - 1][3] == 1)
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
gf16[i][j] = (gf16[i][j] + array[j]) % 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return gf16;
|
||||
}
|
||||
|
||||
internal virtual int searchElement(int[] x)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 15 && (x[0] != gf16[i][0] || x[1] != gf16[i][1] || x[2] != gf16[i][2] || x[3] != gf16[i][3]); i++)
|
||||
{
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
internal virtual int[] getCode(int input)
|
||||
{
|
||||
int[] array = new int[15];
|
||||
int[] array2 = new int[8];
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
int num = array2[7];
|
||||
int num2;
|
||||
int num3;
|
||||
if (i < 7)
|
||||
{
|
||||
num2 = (input >> 6 - i) % 2;
|
||||
num3 = (num2 + num) % 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = num;
|
||||
num3 = 0;
|
||||
}
|
||||
array2[7] = (array2[6] + num3) % 2;
|
||||
array2[6] = (array2[5] + num3) % 2;
|
||||
array2[5] = array2[4];
|
||||
array2[4] = (array2[3] + num3) % 2;
|
||||
array2[3] = array2[2];
|
||||
array2[2] = array2[1];
|
||||
array2[1] = array2[0];
|
||||
array2[0] = num3;
|
||||
array[14 - i] = num2;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
internal virtual int addGF(int arg1, int arg2)
|
||||
{
|
||||
int[] array = new int[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int num = ((arg1 >= 0 && arg1 < 15) ? gf16[arg1][i] : 0);
|
||||
int num2 = ((arg2 >= 0 && arg2 < 15) ? gf16[arg2][i] : 0);
|
||||
array[i] = (num + num2) % 2;
|
||||
}
|
||||
return searchElement(array);
|
||||
}
|
||||
|
||||
internal virtual int[] calcSyndrome(bool[] y)
|
||||
{
|
||||
int[] array = new int[5];
|
||||
int[] array2 = new int[4];
|
||||
int i;
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
if (y[i])
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
array2[j] = (array2[j] + gf16[i][j]) % 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = searchElement(array2);
|
||||
array[0] = ((i >= 15) ? (-1) : i);
|
||||
array2 = new int[4];
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
if (y[i])
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
array2[j] = (array2[j] + gf16[i * 3 % 15][j]) % 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = searchElement(array2);
|
||||
array[2] = ((i >= 15) ? (-1) : i);
|
||||
array2 = new int[4];
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
if (y[i])
|
||||
{
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
array2[j] = (array2[j] + gf16[i * 5 % 15][j]) % 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
i = searchElement(array2);
|
||||
array[4] = ((i >= 15) ? (-1) : i);
|
||||
return array;
|
||||
}
|
||||
|
||||
internal virtual int[] calcErrorPositionVariable(int[] s)
|
||||
{
|
||||
int[] array = new int[4]
|
||||
{
|
||||
s[0],
|
||||
0,
|
||||
0,
|
||||
0
|
||||
};
|
||||
int arg = (s[0] + s[1]) % 15;
|
||||
int num = addGF(s[2], arg);
|
||||
num = ((num >= 15) ? (-1) : num);
|
||||
arg = (s[2] + s[1]) % 15;
|
||||
int num2 = addGF(s[4], arg);
|
||||
num2 = ((num2 >= 15) ? (-1) : num2);
|
||||
array[1] = ((num2 < 0 && num < 0) ? (-1) : ((num2 - num + 15) % 15));
|
||||
arg = (s[1] + array[0]) % 15;
|
||||
int arg2 = addGF(s[2], arg);
|
||||
arg = (s[0] + array[1]) % 15;
|
||||
array[2] = addGF(arg2, arg);
|
||||
return array;
|
||||
}
|
||||
|
||||
internal virtual int[] detectErrorBitPosition(int[] s)
|
||||
{
|
||||
int[] array = calcErrorPositionVariable(s);
|
||||
int[] array2 = new int[4];
|
||||
if (array[0] == -1)
|
||||
{
|
||||
return array2;
|
||||
}
|
||||
if (array[1] == -1)
|
||||
{
|
||||
array2[0] = 1;
|
||||
array2[1] = array[0];
|
||||
return array2;
|
||||
}
|
||||
for (int i = 0; i < 15; i++)
|
||||
{
|
||||
int arg = i * 3 % 15;
|
||||
int num = i * 2 % 15;
|
||||
int num2 = i;
|
||||
int arg2 = (array[0] + num) % 15;
|
||||
int arg3 = addGF(arg, arg2);
|
||||
arg2 = (array[1] + num2) % 15;
|
||||
int arg4 = addGF(arg2, array[2]);
|
||||
int num3 = addGF(arg3, arg4);
|
||||
if (num3 >= 15)
|
||||
{
|
||||
array2[0]++;
|
||||
array2[array2[0]] = i;
|
||||
}
|
||||
}
|
||||
return array2;
|
||||
}
|
||||
|
||||
internal virtual bool[] correctErrorBit(bool[] y, int[] errorPos)
|
||||
{
|
||||
for (int i = 1; i <= errorPos[0]; i++)
|
||||
{
|
||||
y[errorPos[i]] = !y[errorPos[i]];
|
||||
}
|
||||
numCorrectedError = errorPos[0];
|
||||
return y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
namespace MessagingToolkit.QRCode.Codec.Ecc;
|
||||
|
||||
public class ReedSolomon
|
||||
{
|
||||
internal int[] y;
|
||||
|
||||
internal int[] gexp = new int[512];
|
||||
|
||||
internal int[] glog = new int[256];
|
||||
|
||||
internal int NPAR;
|
||||
|
||||
internal int MAXDEG;
|
||||
|
||||
internal int[] synBytes;
|
||||
|
||||
internal int[] Lambda;
|
||||
|
||||
internal int[] Omega;
|
||||
|
||||
internal int[] ErrorLocs = new int[256];
|
||||
|
||||
internal int NErrors;
|
||||
|
||||
internal int[] ErasureLocs = new int[256];
|
||||
|
||||
internal int NErasures = 0;
|
||||
|
||||
internal bool correctionSucceeded = true;
|
||||
|
||||
public virtual bool CorrectionSucceeded => correctionSucceeded;
|
||||
|
||||
public virtual int NumCorrectedErrors => NErrors;
|
||||
|
||||
public ReedSolomon(int[] source, int NPAR)
|
||||
{
|
||||
initializeGaloisTables();
|
||||
y = source;
|
||||
this.NPAR = NPAR;
|
||||
MAXDEG = NPAR * 2;
|
||||
synBytes = new int[MAXDEG];
|
||||
Lambda = new int[MAXDEG];
|
||||
Omega = new int[MAXDEG];
|
||||
}
|
||||
|
||||
internal virtual void initializeGaloisTables()
|
||||
{
|
||||
int num2;
|
||||
int num3;
|
||||
int num4;
|
||||
int num5;
|
||||
int num6;
|
||||
int num7;
|
||||
int num = (num2 = (num3 = (num4 = (num5 = (num6 = (num7 = 0))))));
|
||||
int num8 = 1;
|
||||
gexp[0] = 1;
|
||||
gexp[255] = gexp[0];
|
||||
glog[0] = 0;
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
int num9 = num7;
|
||||
num7 = num6;
|
||||
num6 = num5;
|
||||
num5 = num4;
|
||||
num4 = num3 ^ num9;
|
||||
num3 = num2 ^ num9;
|
||||
num2 = num ^ num9;
|
||||
num = num8;
|
||||
num8 = num9;
|
||||
gexp[i] = num8 + num * 2 + num2 * 4 + num3 * 8 + num4 * 16 + num5 * 32 + num6 * 64 + num7 * 128;
|
||||
gexp[i + 255] = gexp[i];
|
||||
}
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
for (int j = 0; j < 256; j++)
|
||||
{
|
||||
if (gexp[j] == i)
|
||||
{
|
||||
glog[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual int gmult(int a, int b)
|
||||
{
|
||||
if (a == 0 || b == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int num = glog[a];
|
||||
int num2 = glog[b];
|
||||
return gexp[num + num2];
|
||||
}
|
||||
|
||||
internal virtual int ginv(int elt)
|
||||
{
|
||||
return gexp[255 - glog[elt]];
|
||||
}
|
||||
|
||||
internal virtual void decode_data(int[] data)
|
||||
{
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
int num = 0;
|
||||
for (int j = 0; j < data.Length; j++)
|
||||
{
|
||||
num = data[j] ^ gmult(gexp[i + 1], num);
|
||||
}
|
||||
synBytes[i] = num;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void correct()
|
||||
{
|
||||
decode_data(y);
|
||||
correctionSucceeded = true;
|
||||
bool flag = false;
|
||||
for (int i = 0; i < synBytes.Length; i++)
|
||||
{
|
||||
if (synBytes[i] != 0)
|
||||
{
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
correctionSucceeded = correct_errors_erasures(y, y.Length, 0, new int[1]);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void Modified_Berlekamp_Massey()
|
||||
{
|
||||
int[] array = new int[MAXDEG];
|
||||
int[] array2 = new int[MAXDEG];
|
||||
int[] array3 = new int[MAXDEG];
|
||||
int[] array4 = new int[MAXDEG];
|
||||
init_gamma(array4);
|
||||
copy_poly(array3, array4);
|
||||
mul_z_poly(array3);
|
||||
copy_poly(array, array4);
|
||||
int num = -1;
|
||||
int num2 = NErasures;
|
||||
for (int i = NErasures; i < 8; i++)
|
||||
{
|
||||
int num3 = compute_discrepancy(array, synBytes, num2, i);
|
||||
if (num3 != 0)
|
||||
{
|
||||
for (int j = 0; j < MAXDEG; j++)
|
||||
{
|
||||
array2[j] = array[j] ^ gmult(num3, array3[j]);
|
||||
}
|
||||
if (num2 < i - num)
|
||||
{
|
||||
int num4 = i - num;
|
||||
num = i - num2;
|
||||
for (int j = 0; j < MAXDEG; j++)
|
||||
{
|
||||
array3[j] = gmult(array[j], ginv(num3));
|
||||
}
|
||||
num2 = num4;
|
||||
}
|
||||
for (int j = 0; j < MAXDEG; j++)
|
||||
{
|
||||
array[j] = array2[j];
|
||||
}
|
||||
}
|
||||
mul_z_poly(array3);
|
||||
}
|
||||
for (int j = 0; j < MAXDEG; j++)
|
||||
{
|
||||
Lambda[j] = array[j];
|
||||
}
|
||||
compute_modified_omega();
|
||||
}
|
||||
|
||||
internal virtual void compute_modified_omega()
|
||||
{
|
||||
int[] array = new int[MAXDEG * 2];
|
||||
mult_polys(array, Lambda, synBytes);
|
||||
zero_poly(Omega);
|
||||
for (int i = 0; i < NPAR; i++)
|
||||
{
|
||||
Omega[i] = array[i];
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void mult_polys(int[] dst, int[] p1, int[] p2)
|
||||
{
|
||||
int[] array = new int[MAXDEG * 2];
|
||||
for (int i = 0; i < MAXDEG * 2; i++)
|
||||
{
|
||||
dst[i] = 0;
|
||||
}
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
for (int j = MAXDEG; j < MAXDEG * 2; j++)
|
||||
{
|
||||
array[j] = 0;
|
||||
}
|
||||
for (int j = 0; j < MAXDEG; j++)
|
||||
{
|
||||
array[j] = gmult(p2[j], p1[i]);
|
||||
}
|
||||
for (int j = MAXDEG * 2 - 1; j >= i; j--)
|
||||
{
|
||||
array[j] = array[j - i];
|
||||
}
|
||||
for (int j = 0; j < i; j++)
|
||||
{
|
||||
array[j] = 0;
|
||||
}
|
||||
for (int j = 0; j < MAXDEG * 2; j++)
|
||||
{
|
||||
dst[j] ^= array[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void init_gamma(int[] gamma)
|
||||
{
|
||||
int[] array = new int[MAXDEG];
|
||||
zero_poly(gamma);
|
||||
zero_poly(array);
|
||||
gamma[0] = 1;
|
||||
for (int i = 0; i < NErasures; i++)
|
||||
{
|
||||
copy_poly(array, gamma);
|
||||
scale_poly(gexp[ErasureLocs[i]], array);
|
||||
mul_z_poly(array);
|
||||
add_polys(gamma, array);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void compute_next_omega(int d, int[] A, int[] dst, int[] src)
|
||||
{
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
dst[i] = src[i] ^ gmult(d, A[i]);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual int compute_discrepancy(int[] lambda, int[] S, int L, int n)
|
||||
{
|
||||
int num = 0;
|
||||
for (int i = 0; i <= L; i++)
|
||||
{
|
||||
num ^= gmult(lambda[i], S[n - i]);
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
internal virtual void add_polys(int[] dst, int[] src)
|
||||
{
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
dst[i] ^= src[i];
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void copy_poly(int[] dst, int[] src)
|
||||
{
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void scale_poly(int k, int[] poly)
|
||||
{
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
poly[i] = gmult(k, poly[i]);
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void zero_poly(int[] poly)
|
||||
{
|
||||
for (int i = 0; i < MAXDEG; i++)
|
||||
{
|
||||
poly[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void mul_z_poly(int[] src)
|
||||
{
|
||||
for (int num = MAXDEG - 1; num > 0; num--)
|
||||
{
|
||||
src[num] = src[num - 1];
|
||||
}
|
||||
src[0] = 0;
|
||||
}
|
||||
|
||||
internal virtual void Find_Roots()
|
||||
{
|
||||
NErrors = 0;
|
||||
for (int i = 1; i < 256; i++)
|
||||
{
|
||||
int num = 0;
|
||||
for (int j = 0; j < NPAR + 1; j++)
|
||||
{
|
||||
num ^= gmult(gexp[j * i % 255], Lambda[j]);
|
||||
}
|
||||
if (num == 0)
|
||||
{
|
||||
ErrorLocs[NErrors] = 255 - i;
|
||||
NErrors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual bool correct_errors_erasures(int[] codeword, int csize, int nerasures, int[] erasures)
|
||||
{
|
||||
NErasures = nerasures;
|
||||
for (int i = 0; i < NErasures; i++)
|
||||
{
|
||||
ErasureLocs[i] = erasures[i];
|
||||
}
|
||||
Modified_Berlekamp_Massey();
|
||||
Find_Roots();
|
||||
if (NErrors <= NPAR || NErrors > 0)
|
||||
{
|
||||
for (int j = 0; j < NErrors; j++)
|
||||
{
|
||||
if (ErrorLocs[j] >= csize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < NErrors; j++)
|
||||
{
|
||||
int i = ErrorLocs[j];
|
||||
int num = 0;
|
||||
for (int k = 0; k < MAXDEG; k++)
|
||||
{
|
||||
num ^= gmult(Omega[k], gexp[(255 - i) * k % 255]);
|
||||
}
|
||||
int num2 = 0;
|
||||
for (int k = 1; k < MAXDEG; k += 2)
|
||||
{
|
||||
num2 ^= gmult(Lambda[k], gexp[(255 - i) * (k - 1) % 255]);
|
||||
}
|
||||
int num3 = gmult(num, ginv(num2));
|
||||
codeword[csize - i - 1] ^= num3;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user