/// <summary> /// Initializes a new instance of the <see cref="Polynomial"/> class. /// </summary> /// <param name="gfield">The gfield.</param> /// <param name="coefficients">The coefficients.</param> /// <remarks></remarks> internal Polynomial(GaloisField256 gfield, int[] coefficients) { int coefficientsLength = coefficients.Length; if (coefficientsLength == 0 || coefficients == null) throw new ArithmeticException("Can not create empty Polynomial"); m_GField = gfield; m_primitive = gfield.Primitive; if (coefficientsLength > 1 && coefficients[0] == 0) { int firstNonZeroIndex = 1; while (firstNonZeroIndex < coefficientsLength && coefficients[firstNonZeroIndex] == 0) { firstNonZeroIndex++; } if (firstNonZeroIndex == coefficientsLength) m_Coefficients = new[] {0}; else { int newLength = coefficientsLength - firstNonZeroIndex; m_Coefficients = new int[newLength]; Array.Copy(coefficients, firstNonZeroIndex, m_Coefficients, 0, newLength); } } else { m_Coefficients = new int[coefficientsLength]; Array.Copy(coefficients, m_Coefficients, coefficientsLength); } }
/// <summary> /// After create GeneratorPolynomial. Keep it as long as possible. /// Unless QRCode encode is done or no more QRCode need to generate. /// </summary> internal GeneratorPolynomial(GaloisField256 gfield) { Gfield = gfield; CacheGenerator = new List <Polynomial>(10) { new Polynomial(Gfield, new int[] { 1 }) }; }
/// <summary> /// Instantiates a new instance of the Rs256Encoder. /// </summary> /// <param name="size"></param> /// <param name="decodedSize"></param> /// <param name="fieldGeneratorPoly"></param> public Rs256Encoder(int size, int decodedSize, int fieldGeneratorPoly) { this.size = size; this.decodedSize = decodedSize; this.checkwords = (size - 1) - decodedSize; this.gf = new GaloisField256(size, fieldGeneratorPoly); this.codeGenPoly = BuildCodeGenPoly(); this.modTempResult = new byte[this.checkwords]; }
public void Test_against_CSV_Dataset(int i, int exp) { GaloisField256 gfield = GaloisField256.QRCodeGaloisField; int result = gfield.Exponent(i); if (exp != result) { Assert.Fail("Fail. request {0} Expect {1} result {2}", i, exp, result); } }
public void Test_against_reference_implementation(int i, int exp) { GaloisField256 gfield = GaloisField256.QRCodeGaloisField; int result = gfield.Exponent(i); if (exp != result) { Assert.Fail("Fail. request {0} Expect {1} result {2}", i, exp, result); } }
private void TestOneCase(int[] aCoeff, int[] bCoeff, string option, int[] expect) { GaloisField256 gfield = GaloisField256.QRCodeGaloisField; Polynomial apoly = new Polynomial(gfield, aCoeff); Polynomial bpoly = new Polynomial(gfield, bCoeff); int[] result = resultCoeff(apoly, bpoly, option); if (!PolynomialExtensions.isEqual(result, expect)) { Assert.Fail("result {0} expect {1} option {2}", result[0], expect[0], option); } }
public void PerformanceTest() { Random randomizer = new Random(); sbyte[] zxTestCase = PolynomialExtensions.GenerateSbyteArray(40, randomizer); int ecBytes = 50; byte[] testCase = PolynomialExtensions.ToByteArray(zxTestCase); Stopwatch sw = new Stopwatch(); int timesofTest = 10000; string[] timeElapsed = new string[2]; sw.Start(); GaloisField256 gf256 = GaloisField256.QRCodeGaloisField; GeneratorPolynomial generator = new GeneratorPolynomial(gf256); for (int i = 0; i < timesofTest; i++) { ReedSolomonEncoder.Encode(testCase, ecBytes, generator); } sw.Stop(); timeElapsed[0] = sw.ElapsedMilliseconds.ToString(); sw.Reset(); sw.Start(); for (int i = 0; i < timesofTest; i++) { EncoderInternal.generateECBytes(zxTestCase, ecBytes); } sw.Stop(); timeElapsed[1] = sw.ElapsedMilliseconds.ToString(); Assert.Pass("ReedSolomon performance {0} Tests~ QrCode.Net: {1} ZXing: {2}", timesofTest, timeElapsed[0], timeElapsed[1]); }
private void TestOneCase(int[] aCoeff, int[] bCoeff, int[] expQuotient, int[] expRemainder) { GaloisField256 gfield = GaloisField256.QRCodeGaloisField; Polynomial apoly = new Polynomial(gfield, aCoeff); Polynomial bpoly = new Polynomial(gfield, bCoeff); PolyDivideStruct pds = apoly.Divide(bpoly); int[] quotient = pds.Quotient.Coefficients; int[] remainder = pds.Remainder.Coefficients; if (!PolynomialExtensions.isEqual(quotient, expQuotient)) { Assert.Fail("Quotient not equal. Result {0}, Expect {1}", aCoeff.Length, bCoeff.Length); } if (!PolynomialExtensions.isEqual(remainder, expRemainder)) { Assert.Fail("Remainder not equal. Result {0}, Expect {1}", remainder.Length, aCoeff.Length); } }
internal Polynomial(GaloisField256 gfield, int[] coefficients) { int coefficientsLength = coefficients.Length; if (coefficientsLength == 0 || coefficients is null) { throw new ArithmeticException($"Cannot create empty {nameof(Polynomial)}."); } GField = gfield; Primitive = gfield.Primitive; if (coefficientsLength > 1 && coefficients[0] == 0) { int firstNonZeroIndex = 1; while (firstNonZeroIndex < coefficientsLength && coefficients[firstNonZeroIndex] == 0) { firstNonZeroIndex++; } if (firstNonZeroIndex == coefficientsLength) { Coefficients = new int[] { 0 }; } else { int newLength = coefficientsLength - firstNonZeroIndex; Coefficients = new int[newLength]; Array.Copy(coefficients, firstNonZeroIndex, Coefficients, 0, newLength); } } else { Coefficients = new int[coefficientsLength]; Array.Copy(coefficients, Coefficients, coefficientsLength); } }
public Rs256Decoder(int size, int numDataSymbols, int fieldGenPoly) { this.size = size; this.numDataSymbols = numDataSymbols; this.fieldGenPoly = fieldGenPoly; this.numCheckBytes = (size - 1) - numDataSymbols; this.CodeWordSize = size - 1; this.gf = new GaloisField256(size, fieldGenPoly); // Syndrom calculation buffers this.syndroms = new byte[numCheckBytes]; // Lamda calculation buffers this.lambda = new byte[numCheckBytes - 1]; this.corrPoly = new byte[numCheckBytes - 1]; this.lambdaStar = new byte[numCheckBytes - 1]; // LambdaPrime calculation buffers this.lambdaPrime = new byte[numCheckBytes - 2]; // Omega calculation buffers this.omega = new byte[numCheckBytes - 2]; // Error position calculation this.errorIndexes = new byte[size - 1]; // Cache of the lookup used in the ChienSearch process. this.chienCache = new byte[size - 1]; for (int i = 0; i < this.chienCache.Length; i++) { this.chienCache[i] = gf.Inverses[gf.Field[i + 1]]; } }
/// <summary> /// Generate error correction blocks. Then out put with codewords BitList /// ISO/IEC 18004/2006 P45, 46. Chapter 6.6 Constructing final message codewords sequence. /// </summary> /// <param name="dataCodewords">Datacodewords from DataEncodation.DataEncode</param> /// <param name="numTotalBytes">Total number of bytes</param> /// <param name="numDataBytes">Number of data bytes</param> /// <param name="numECBlocks">Number of Error Correction blocks</param> /// <returns>codewords BitList contain datacodewords and ECCodewords</returns> internal static BitList FillECCodewords(BitList dataCodewords, VersionDetail vd) { List <byte> dataCodewordsByte = dataCodewords.List; int ecBlockGroup2 = vd.ECBlockGroup2; int ecBlockGroup1 = vd.ECBlockGroup1; int numDataBytesGroup1 = vd.NumDataBytesGroup1; int numDataBytesGroup2 = vd.NumDataBytesGroup2; int ecBytesPerBlock = vd.NumECBytesPerBlock; int dataBytesOffset = 0; byte[][] dByteJArray = new byte[vd.NumECBlocks][]; byte[][] ecByteJArray = new byte[vd.NumECBlocks][]; GaloisField256 gf256 = GaloisField256.QRCodeGaloisField; GeneratorPolynomial generator = new GeneratorPolynomial(gf256); for (int blockID = 0; blockID < vd.NumECBlocks; blockID++) { if (blockID < ecBlockGroup1) { dByteJArray[blockID] = new byte[numDataBytesGroup1]; for (int index = 0; index < numDataBytesGroup1; index++) { dByteJArray[blockID][index] = dataCodewordsByte[dataBytesOffset + index]; } dataBytesOffset += numDataBytesGroup1; } else { dByteJArray[blockID] = new byte[numDataBytesGroup2]; for (int index = 0; index < numDataBytesGroup2; index++) { dByteJArray[blockID][index] = dataCodewordsByte[dataBytesOffset + index]; } dataBytesOffset += numDataBytesGroup2; } ecByteJArray[blockID] = ReedSolomonEncoder.Encode(dByteJArray[blockID], ecBytesPerBlock, generator); } if (vd.NumDataBytes != dataBytesOffset) { throw new ArgumentException("Data bytes does not match offset"); } BitList codewords = new BitList(); int maxDataLength = ecBlockGroup1 == vd.NumECBlocks ? numDataBytesGroup1 : numDataBytesGroup2; for (int dataID = 0; dataID < maxDataLength; dataID++) { for (int blockID = 0; blockID < vd.NumECBlocks; blockID++) { if (!(dataID == numDataBytesGroup1 && blockID < ecBlockGroup1)) { codewords.Add((int)dByteJArray[blockID][dataID], 8); } } } for (int ECID = 0; ECID < ecBytesPerBlock; ECID++) { for (int blockID = 0; blockID < vd.NumECBlocks; blockID++) { codewords.Add((int)ecByteJArray[blockID][ECID], 8); } } if (vd.NumTotalBytes != codewords.Count >> 3) { throw new ArgumentException(string.Format("total bytes: {0}, actual bits: {1}", vd.NumTotalBytes, codewords.Count)); } return(codewords); }