Skip to content

Commit

Permalink
Use overloaded methods instead of optional parameters
Browse files Browse the repository at this point in the history
Use overloaded methods instead of optional parameters
Put curly braces around all if statements
Properly cased Encode and Decode method names (breaking)
  • Loading branch information
Sonic-The-Hedgehog-LNK1123 authored Mar 14, 2019
1 parent 88cdc10 commit d2170f2
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 49 deletions.
64 changes: 56 additions & 8 deletions ReedSolomon/GenericGF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,44 @@ namespace STH1123.ReedSolomon
/// <author>Sean Owen</author>
public sealed class GenericGF
{
/// <summary>
/// x^12 + x^6 + x^5 + x^3 + 1
/// </summary>
public static GenericGF AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1, 2); // x^12 + x^6 + x^5 + x^3 + 1

/// <summary>
/// x^10 + x^3 + 1
/// </summary>
public static GenericGF AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1, 2); // x^10 + x^3 + 1

/// <summary>
/// x^6 + x + 1
/// </summary>
public static GenericGF AZTEC_DATA_6 = new GenericGF(0x43, 64, 1, 2); // x^6 + x + 1

/// <summary>
/// x^4 + x + 1
/// </summary>
public static GenericGF AZTEC_PARAM = new GenericGF(0x13, 16, 1, 2); // x^4 + x + 1

/// <summary>
/// x^8 + x^4 + x^3 + x^2 + 1
/// </summary>
public static GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0, 2); // x^8 + x^4 + x^3 + x^2 + 1

/// <summary>
/// x^8 + x^5 + x^3 + x^2 + 1
/// </summary>
public static GenericGF DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256, 1, 2); // x^8 + x^5 + x^3 + x^2 + 1

/// <summary>
/// x^8 + x^5 + x^3 + x^2 + 1
/// </summary>
public static GenericGF AZTEC_DATA_8 = DATA_MATRIX_FIELD_256;

/// <summary>
/// x^6 + x + 1
/// </summary>
public static GenericGF MAXICODE_FIELD_64 = AZTEC_DATA_6;

private int[] expTable;
Expand All @@ -49,14 +80,31 @@ public sealed class GenericGF
/// Create a representation of GF(size) using the given primitive polynomial.
/// </summary>
/// <param name="primitive">irreducible polynomial whose coefficients are represented by
/// * the bits of an int, where the least-significant bit represents the constant
/// * coefficient</param>
/// the bits of an int, where the least-significant bit represents the constant
/// coefficient</param>
/// <param name="size">the size of the field</param>
/// <param name="genBase">the factor b in the generator polynomial can be 0- or 1-based
/// (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
/// In most cases it should be 1, but for QR code it is 0.</param>
public GenericGF(int primitive, int size, int genBase)
: this(primitive, size, genBase, 2)
{
// Constructor added by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// calls overloaded constructor only
}

/// <summary>
/// Create a representation of GF(size) using the given primitive polynomial.
/// </summary>
/// <param name="primitive">irreducible polynomial whose coefficients are represented by
/// the bits of an int, where the least-significant bit represents the constant
/// coefficient</param>
/// <param name="size">the size of the field</param>
/// <param name="genBase">the factor b in the generator polynomial can be 0- or 1-based
/// * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
/// * In most cases it should be 1, but for QR code it is 0.</param>
/// (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
/// In most cases it should be 1, but for QR code it is 0.</param>
/// <param name="alpha">the generator alpha</param>
public GenericGF(int primitive, int size, int genBase, int alpha = 2)
public GenericGF(int primitive, int size, int genBase, int alpha)
{
// Constructor modified by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// to add support for alpha powers other than 2
Expand Down Expand Up @@ -97,7 +145,7 @@ public GenericGF(int primitive, int size, int genBase, int alpha = 2)
}

// Method added by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
internal int multiplyNoLUT(int x, int y, int primitive, int size)
static internal int multiplyNoLUT(int x, int y, int primitive, int size)
{
int r = 0;
while (y > 0)
Expand Down Expand Up @@ -144,7 +192,7 @@ internal int log(int a)
{
if (a == 0)
{
throw new ArgumentException();
throw new ArithmeticException("log(0) is undefined");
}
return logTable[a];
}
Expand All @@ -157,7 +205,7 @@ internal int inverse(int a)
{
if (a == 0)
{
throw new ArithmeticException();
throw new ArithmeticException("inverse(0) is undefined");
}
return expTable[size - logTable[a] - 1];
}
Expand Down
30 changes: 5 additions & 25 deletions ReedSolomon/GenericGFPoly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal GenericGFPoly(GenericGF field, int[] coefficients, bool encode)
{
if (coefficients.Length == 0)
{
throw new ArgumentException();
throw new ArgumentException("No coefficients provided", "coefficients");
}
this.field = field;
this.encoding = encode;
Expand Down Expand Up @@ -88,34 +88,14 @@ internal GenericGFPoly(GenericGF field, int[] coefficients, bool encode)
{
if (coefficients.Length == 0)
{
throw new ArgumentException();
throw new ArgumentException("No coefficients provided", "coefficients");
}
this.field = field;
this.encoding = encode;
this.coefficients = coefficients;
}
}

// Property added by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// replaces property originally defined in GenericGF.cs
internal GenericGFPoly Zero
{
get
{
return new GenericGFPoly(field, new int[] { 0 }, encoding);
}
}

// Property added by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// replaces property originally defined in GenericGF.cs
internal GenericGFPoly One
{
get
{
return new GenericGFPoly(field, new int[] { 1 }, encoding);
}
}

internal int[] Coefficients
{
get { return coefficients; }
Expand Down Expand Up @@ -164,7 +144,7 @@ internal GenericGFPoly buildMonomial(int degree, int coefficient)
// replaces method originally defined in GenericGF.cs
if (degree < 0)
{
throw new ArgumentException();
throw new ArgumentException("Degree must be positive", "degree");
}
if (coefficient == 0)
{
Expand Down Expand Up @@ -302,7 +282,7 @@ internal GenericGFPoly multiplyByMonomial(int degree, int coefficient)
{
if (degree < 0)
{
throw new ArgumentException();
throw new ArgumentException("Degree must be positive", "degree");
}
if (coefficient == 0)
{
Expand All @@ -325,7 +305,7 @@ internal GenericGFPoly[] divide(GenericGFPoly other)
}
if (other.isZero)
{
throw new ArgumentException("Divide by 0");
throw new ArgumentException("Divide by 0", "other");
}

GenericGFPoly quotient = new GenericGFPoly(field, new int[] { 0 }, encoding);
Expand Down
9 changes: 6 additions & 3 deletions ReedSolomon/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

Expand Down Expand Up @@ -32,5 +33,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

[assembly: CLSCompliant(true)]
51 changes: 45 additions & 6 deletions ReedSolomon/ReedSolomonDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,29 @@ public sealed class ReedSolomonDecoder
{
private readonly GenericGF field;

/// <summary>
/// Initializes a new instance of the <see cref="ReedSolomonDecoder"/> class.
/// </summary>
/// <param name="field">A <see cref="GenericGF"/> that represents the Galois field to use</param>
public ReedSolomonDecoder(GenericGF field)
{
this.field = field;
}

/// <summary>
/// <p>Decodes given set of received codewords, which include both data and error-correction
/// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
/// in the input.</p>
/// </summary>
/// <param name="received">data and error-correction codewords</param>
/// <param name="twoS">number of error-correction codewords available</param>
/// <returns>false: decoding fails</returns>
public bool Decode(int[] received, int twoS)
{
// Method added by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
return Decode(received, twoS, null);
}

/// <summary>
/// <p>Decodes given set of received codewords, which include both data and error-correction
/// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
Expand All @@ -59,15 +77,25 @@ public ReedSolomonDecoder(GenericGF field)
/// <param name="twoS">number of error-correction codewords available</param>
/// <param name="erasurePos">array of zero-based erasure indices</param>
/// <returns>false: decoding fails</returns>
public bool decode(int[] received, int twoS, int[] erasurePos = null)
public bool Decode(int[] received, int twoS, int[] erasurePos)
{
// Method modified by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// to add support for erasure and errata correction
// most code ported to C# from the python code at http://en.wikiversity.org/wiki/Reed–Solomon_codes_for_coders

if (received.Length >= field.Size)
{
return false;
throw new ArgumentException("Message is too long for this field", "received");
}

if (twoS <= 0)
{
throw new ArgumentException("No error correction bytes provided", "twoS");
}
var dataBytes = received.Length - twoS;
if (dataBytes <= 0)
{
throw new ArgumentException("No data bytes provided", "twoS");
}

var syndromeCoefficients = new int[twoS];
Expand Down Expand Up @@ -113,29 +141,33 @@ public bool decode(int[] received, int twoS, int[] erasurePos = null)
var sigma = runBerlekampMasseyAlgorithm(forneySyndrome, erasurePos.Length);

if (sigma == null)
{
return false;
}

var errorLocations = findErrorLocations(sigma);
if (errorLocations == null)
{
return false;
}

//Prepare errors
// Prepare errors
int[] errorPositions = new int[errorLocations.Length];

for (int i = 0; i < errorLocations.Length; i++)
{
errorPositions[i] = field.log(errorLocations[i]);
}

//Prepare erasures
// Prepare erasures
int[] erasurePositions = new int[erasurePos.Length];

for (int i = 0; i < erasurePos.Length; i++)
{
erasurePositions[i] = received.Length - 1 - erasurePos[i];
}

//Combine errors and erasures
// Combine errors and erasures
int[] errataPositions = new int[errorPositions.Length + erasurePositions.Length];

Array.Copy(errorPositions, 0, errataPositions, 0, errorPositions.Length);
Expand All @@ -145,7 +177,9 @@ public bool decode(int[] received, int twoS, int[] erasurePos = null)
var omega = findErrorEvaluator(syndrome, errataLocator);

if (omega == null)
{
return false;
}

int[] errata = new int[errataPositions.Length];

Expand All @@ -157,7 +191,9 @@ public bool decode(int[] received, int twoS, int[] erasurePos = null)
var errorMagnitudes = findErrorMagnitudes(omega, errata);

if (errorMagnitudes == null)
{
return false;
}

for (var i = 0; i < errata.Length; i++)
{
Expand Down Expand Up @@ -252,7 +288,10 @@ internal GenericGFPoly runBerlekampMasseyAlgorithm(GenericGFPoly syndrome, int e
}

List<int> sigmaList = new List<int>(sigma.Coefficients);
while (Convert.ToBoolean(sigmaList.Count) && sigmaList[0] == 0) sigmaList.RemoveAt(0);
while (Convert.ToBoolean(sigmaList.Count) && sigmaList[0] == 0)
{
sigmaList.RemoveAt(0);
}

sigma = new GenericGFPoly(field, sigmaList.ToArray(), false);

Expand Down
26 changes: 19 additions & 7 deletions ReedSolomon/ReedSolomonEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public sealed class ReedSolomonEncoder
private readonly GenericGF field;
private readonly IList<GenericGFPoly> cachedGenerators;

/// <summary>
/// Initializes a new instance of the <see cref="ReedSolomonEncoder"/> class.
/// </summary>
/// <param name="field">A <see cref="GenericGF"/> that represents the Galois field to use</param>
public ReedSolomonEncoder(GenericGF field)
{
this.field = field;
Expand All @@ -52,23 +56,31 @@ private GenericGFPoly buildGenerator(int degree)
return cachedGenerators[degree];
}

// Method modified by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// added check for messages that are too long for the used Galois field
public void encode(int[] toEncode, int ecBytes)
/// <summary>
/// Encodes given set of data codewords with Reed-Solomon.
/// </summary>
/// <param name="toEncode">data codewords and padding, the amount of padding should match
/// the number of error-correction codewords to generate. After encoding, the padding is
/// replaced with the error-correction codewords</param>
/// <param name="ecBytes">number of error-correction codewords to generate</param>
public void Encode(int[] toEncode, int ecBytes)
{
// Method modified by Sonic-The-Hedgehog-LNK1123 (github.com/Sonic-The-Hedgehog-LNK1123)
// added check for messages that are too long for the used Galois field

if (toEncode.Length >= field.Size)
{
throw new ArgumentException("Message is too long for this field");
throw new ArgumentException("Message is too long for this field", "toEncode");
}

if (ecBytes == 0)
if (ecBytes <= 0)
{
throw new ArgumentException("No error correction bytes");
throw new ArgumentException("No error correction bytes provided", "ecBytes");
}
var dataBytes = toEncode.Length - ecBytes;
if (dataBytes <= 0)
{
throw new ArgumentException("No data bytes provided");
throw new ArgumentException("No data bytes provided", "ecBytes");
}

var generator = buildGenerator(ecBytes);
Expand Down

0 comments on commit d2170f2

Please sign in to comment.