Toolkit.UI.Controls.Avalonia
This commit is contained in:
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
|
||||
namespace Gma.QrCodeNet.Encoding.ReedSolomon;
|
||||
|
||||
internal sealed class Polynomial
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
internal int[] Coefficients { get; }
|
||||
|
||||
internal GaloisField256 GField { get; }
|
||||
|
||||
internal int Degree => Coefficients.Length - 1;
|
||||
|
||||
internal int Primitive { get; }
|
||||
|
||||
internal bool IsMonomialZero => Coefficients[0] == 0;
|
||||
|
||||
/// <returns>
|
||||
/// Coefficient position. where (coefficient)x^degree
|
||||
/// </returns>
|
||||
internal int GetCoefficient(int degree)
|
||||
{
|
||||
// Eg: x^2 + x + 1. degree 1, reverse position = degree + 1 = 2.
|
||||
// Pos = 3 - 2 = 1
|
||||
return Coefficients[^(degree + 1)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add another Polynomial to current one
|
||||
/// </summary>
|
||||
/// <param name="other">The polynomial need to add or subtract to current one</param>
|
||||
/// <returns>Result polynomial after add or subtract</returns>
|
||||
internal Polynomial AddOrSubtract(Polynomial other)
|
||||
{
|
||||
if (Primitive != other.Primitive)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(Polynomial)} cannot perform {nameof(AddOrSubtract)} as they do not have the same {nameof(Primitive)}" +
|
||||
$" for {nameof(GaloisField256)}.");
|
||||
}
|
||||
if (IsMonomialZero)
|
||||
{
|
||||
return other;
|
||||
}
|
||||
else if (other.IsMonomialZero)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
int otherLength = other.Coefficients.Length;
|
||||
int thisLength = Coefficients.Length;
|
||||
|
||||
if (otherLength > thisLength)
|
||||
{
|
||||
return CoefficientXor(Coefficients, other.Coefficients);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CoefficientXor(other.Coefficients, Coefficients);
|
||||
}
|
||||
}
|
||||
|
||||
internal Polynomial CoefficientXor(int[] smallerCoefficients, int[] largerCoefficients)
|
||||
{
|
||||
if (smallerCoefficients.Length > largerCoefficients.Length)
|
||||
{
|
||||
throw new ArgumentException($"Cannot perform {nameof(CoefficientXor)} method as smaller {nameof(Coefficients)} length is greater than the larger one.");
|
||||
}
|
||||
|
||||
int targetLength = largerCoefficients.Length;
|
||||
int[] xorCoefficient = new int[targetLength];
|
||||
int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length;
|
||||
|
||||
Array.Copy(largerCoefficients, 0, xorCoefficient, 0, lengthDiff);
|
||||
|
||||
for (int index = lengthDiff; index < targetLength; index++)
|
||||
{
|
||||
xorCoefficient[index] = GField.Addition(largerCoefficients[index], smallerCoefficients[index - lengthDiff]);
|
||||
}
|
||||
|
||||
return new Polynomial(GField, xorCoefficient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply current Polynomial to another one.
|
||||
/// </summary>
|
||||
/// <returns>Result polynomial after multiply</returns>
|
||||
internal Polynomial Multiply(Polynomial other)
|
||||
{
|
||||
if (Primitive != other.Primitive)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(Polynomial)} cannot perform {nameof(Multiply)} as they do not have the same {nameof(Primitive)}" +
|
||||
$" for {nameof(GaloisField256)}.");
|
||||
}
|
||||
if (IsMonomialZero || other.IsMonomialZero)
|
||||
{
|
||||
return new Polynomial(GField, new int[] { 0 });
|
||||
}
|
||||
|
||||
int[] aCoefficients = Coefficients;
|
||||
int aLength = aCoefficients.Length;
|
||||
int[] bCoefficient = other.Coefficients;
|
||||
int bLength = bCoefficient.Length;
|
||||
int[] rCoefficients = new int[aLength + bLength - 1];
|
||||
|
||||
for (int aIndex = 0; aIndex < aLength; aIndex++)
|
||||
{
|
||||
int aCoeff = aCoefficients[aIndex];
|
||||
for (int bIndex = 0; bIndex < bLength; bIndex++)
|
||||
{
|
||||
rCoefficients[aIndex + bIndex] =
|
||||
GField.Addition(rCoefficients[aIndex + bIndex], GField.Product(aCoeff, bCoefficient[bIndex]));
|
||||
}
|
||||
}
|
||||
return new Polynomial(GField, rCoefficients);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiplay scalar to current polynomial
|
||||
/// </summary>
|
||||
/// <returns>Result of polynomial after multiply scalar</returns>
|
||||
internal Polynomial MultiplyScalar(int scalar)
|
||||
{
|
||||
if (scalar == 0)
|
||||
{
|
||||
return new Polynomial(GField, new int[] { 0 });
|
||||
}
|
||||
else if (scalar == 1)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
int length = Coefficients.Length;
|
||||
int[] rCoefficient = new int[length];
|
||||
|
||||
for (int index = 0; index < length; index++)
|
||||
{
|
||||
rCoefficient[index] = GField.Product(Coefficients[index], scalar);
|
||||
}
|
||||
|
||||
return new Polynomial(GField, rCoefficient);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide current polynomial by "other"
|
||||
/// </summary>
|
||||
/// <returns>Result polynomial after divide</returns>
|
||||
internal PolyDivideStruct Divide(Polynomial other)
|
||||
{
|
||||
if (Primitive != other.Primitive)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(Polynomial)} cannot perform {nameof(Divide)} as they do not have the same {nameof(Primitive)}" +
|
||||
$" for {nameof(GaloisField256)}.");
|
||||
}
|
||||
if (other.IsMonomialZero)
|
||||
{
|
||||
throw new ArgumentException($"Cannot divide by {nameof(Polynomial)} Zero.");
|
||||
}
|
||||
|
||||
// This divide by other = a divide by b
|
||||
int aLength = Coefficients.Length;
|
||||
|
||||
// We will make change to aCoefficient. It will return as remainder
|
||||
int[] aCoefficients = new int[aLength];
|
||||
Array.Copy(Coefficients, 0, aCoefficients, 0, aLength);
|
||||
|
||||
int bLength = other.Coefficients.Length;
|
||||
|
||||
if (aLength < bLength)
|
||||
{
|
||||
return new PolyDivideStruct(new Polynomial(GField, new int[] { 0 }), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Quotient coefficients
|
||||
// qLastIndex = alength - blength qlength = qLastIndex + 1
|
||||
int[] qCoefficients = new int[(aLength - bLength) + 1];
|
||||
|
||||
// Denominator
|
||||
int otherLeadingTerm = other.GetCoefficient(other.Degree);
|
||||
int inverseOtherLeadingTerm = GField.Inverse(otherLeadingTerm);
|
||||
|
||||
for (int aIndex = 0; aIndex <= aLength - bLength; aIndex++)
|
||||
{
|
||||
if (aCoefficients[aIndex] != 0)
|
||||
{
|
||||
int aScalar = GField.Product(inverseOtherLeadingTerm, aCoefficients[aIndex]);
|
||||
Polynomial term = other.MultiplyScalar(aScalar);
|
||||
qCoefficients[aIndex] = aScalar;
|
||||
|
||||
int[] bCoefficient = term.Coefficients;
|
||||
if (bCoefficient[0] != 0)
|
||||
{
|
||||
for (int bIndex = 0; bIndex < bLength; bIndex++)
|
||||
{
|
||||
aCoefficients[aIndex + bIndex] = GField.Subtraction(aCoefficients[aIndex + bIndex], bCoefficient[bIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new PolyDivideStruct(new Polynomial(GField, qCoefficients), new Polynomial(GField, aCoefficients));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user