/// <summary> /// Method for recursive search of bivariate polynomial's <paramref name="polynomial"/> factors with max degree <paramref name="maxFactorDegree"/> /// </summary> /// <param name="polynomial">Bivariate polynomial for factorization</param> /// <param name="maxFactorDegree">Maximum degree of factor</param> /// <param name="xSubstitution">Substitution for x variable</param> /// <param name="ySubstitution">Substitution for y variable</param> /// <param name="factors">Array of finded factors</param> /// <param name="currentFactorCoefficients">Stack with current factor's coefficients</param> private void Factorize(BiVariablePolynomial polynomial, int maxFactorDegree, BiVariablePolynomial xSubstitution, BiVariablePolynomial ySubstitution, ISet <Polynomial> factors, Stack <int> currentFactorCoefficients) { if (polynomial.EvaluateY(polynomial.Field.Zero()).IsZero) { factors.Add(new Polynomial(polynomial.Field, currentFactorCoefficients.Reverse().ToArray())); } if (currentFactorCoefficients.Count > maxFactorDegree) { return; } var roots = FindPolynomialRoots(polynomial.EvaluateX(polynomial.Field.Zero())); foreach (var root in roots) { currentFactorCoefficients.Push(root.Representation); ySubstitution[_zeroMonomial] = root; Factorize(polynomial .PerformVariablesSubstitution(xSubstitution, ySubstitution) .DivideByMaxPossibleXDegree(), maxFactorDegree, xSubstitution, ySubstitution, factors, currentFactorCoefficients); currentFactorCoefficients.Pop(); } }
/// <summary> /// Method for calculatin (<paramref name="r"/>, <paramref name="s"/>) Hasse derivative value for bivariate polynomial <paramref name="polynomial"/> at point the (<paramref name="xValue"/>, <paramref name="yValue"/>) /// </summary> /// <param name="polynomial">Polynomial which Hasse derivative'll be calculated</param> /// <param name="r">Hasse derivative order by x variable</param> /// <param name="s">Hasse derivative order by y variable</param> /// <param name="xValue">Value for x variable</param> /// <param name="yValue">Value fro y variable</param> /// <param name="combinationsCountCalculator">Combinations calculator contract implementation</param> /// <param name="combinationsCache">Cache for storing calculated numbers of combinations</param> /// <returns>Hasse derivative value</returns> public static FieldElement CalculateHasseDerivative(this BiVariablePolynomial polynomial, int r, int s, FieldElement xValue, FieldElement yValue, ICombinationsCountCalculator combinationsCountCalculator, FieldElement[][] combinationsCache = null) { var field = polynomial.Field; var derivativeValue = 0; foreach (var coefficient in polynomial) { if (coefficient.Key.Item1 < r || coefficient.Key.Item2 < s) { continue; } var currentAddition = combinationsCountCalculator.Calculate(field, coefficient.Key.Item1, r, combinationsCache).Representation; currentAddition = field.Multiply(currentAddition, combinationsCountCalculator.Calculate(field, coefficient.Key.Item2, s, combinationsCache).Representation); currentAddition = field.Multiply(currentAddition, coefficient.Value.Representation); currentAddition = field.Multiply(currentAddition, field.Pow(xValue.Representation, coefficient.Key.Item1 - r)); currentAddition = field.Multiply(currentAddition, field.Pow(yValue.Representation, coefficient.Key.Item2 - s)); derivativeValue = field.Add(derivativeValue, currentAddition); } return(new FieldElement(field, derivativeValue)); }
/// <summary> /// Method Calculating results of replacement bivariate polynomial <paramref name="polynomial"/> variable y by value <paramref name="yValue"/> /// </summary> /// <param name="polynomial">Modified polynomial</param> /// <param name="yValue">Value for y variable</param> /// <returns>Replacement results</returns> public static Polynomial EvaluateY(this BiVariablePolynomial polynomial, FieldElement yValue) { if (polynomial == null) { throw new ArgumentNullException(NameOfExtension.nameof(() => polynomial)); } if (yValue == null) { throw new ArgumentNullException(NameOfExtension.nameof(() => yValue)); } if (polynomial.Field.Equals(yValue.Field) == false) { throw new AggregateException(NameOfExtension.nameof(() => yValue)); } var field = polynomial.Field; var resultCoefficients = new int[polynomial.MaxXDegree + 1]; foreach (var coefficient in polynomial) { resultCoefficients[coefficient.Key.Item1] = field.Add(resultCoefficients[coefficient.Key.Item1], field.Multiply(coefficient.Value.Representation, field.Pow(yValue.Representation, coefficient.Key.Item2))); } return(new Polynomial(field, resultCoefficients)); }
public void ShouldPerformFactorization(BiVariablePolynomial polynomial, int maxFactorDegree, Polynomial[] expectedFactors) { // When var actualFactors = _factorizator.Factorize(polynomial, maxFactorDegree); // Then Assert.Equal(expectedFactors.Length, actualFactors.Length); Assert.True(actualFactors.All(expectedFactors.Contains)); }
public void ShouldSetCoefficients(int coefficientValueRepresentation) { // Given var polynomial = new BiVariablePolynomial(Gf5); var monomial = new Tuple <int, int>(1, 1); var coefficientValue = new FieldElement(Gf5, coefficientValueRepresentation); // When polynomial[monomial] = coefficientValue; // Then Assert.Equal(coefficientValue, polynomial[monomial]); }
/// <summary> /// Method for creation interpolation polynomial from linear system solution /// </summary> /// <param name="field">Finite field from which system coefficients were taken</param> /// <param name="systemSolution">Solution of the linear equations system</param> /// <param name="monomialByVariableIndex">Mapping from numbers to bivariate monomials</param> /// <returns>Interpolation polynomial</returns> private static BiVariablePolynomial ConstructInterpolationPolynomial( GaloisField field, SystemSolution systemSolution, IReadOnlyDictionary <int, Tuple <int, int> > monomialByVariableIndex) { var interpolationPolynomial = new BiVariablePolynomial(field); for (var i = 0; i < systemSolution.VariablesValues.Length; i++) { interpolationPolynomial[monomialByVariableIndex[i]] = systemSolution.VariablesValues[i]; } if (interpolationPolynomial.IsZero) { throw new NonTrivialPolynomialNotFoundException(); } return(interpolationPolynomial); }
/// <summary> /// Exponentiation of bivariate polynomial <paramref name="polynomial"/> to the degree <paramref name="degree"/> /// </summary> /// <param name="powersCache">Cache for storing Exponentiation results </param> /// <param name="polynomial">Bivariate polynomial for exponentiation</param> /// <param name="degree">Power for exponentiation</param> private static BiVariablePolynomial Pow(IDictionary <int, BiVariablePolynomial> powersCache, BiVariablePolynomial polynomial, int degree) { BiVariablePolynomial result; if (powersCache.TryGetValue(degree, out result) == false) { if (degree == 0) { result = new BiVariablePolynomial(polynomial.Field); var pos = new Tuple <int, int>(0, 0); result[pos] = polynomial.Field.One(); } else { result = Pow(powersCache, polynomial, degree - 1) * polynomial; } powersCache[degree] = result; } return(result); }
/// <summary> /// Method for finding bivariate polynomial's <paramref name="interpolationPolynomial"/> factors with max degree <paramref name="maxFactorDegree"/> /// </summary> /// <param name="interpolationPolynomial">Bivariate polynomial for factorization</param> /// <param name="maxFactorDegree">Maximum degree of factor</param> /// <returns>Array of finded factors</returns> public Polynomial[] Factorize(BiVariablePolynomial interpolationPolynomial, int maxFactorDegree) { var xSubstitution = new BiVariablePolynomial(interpolationPolynomial.Field) { [new Tuple <int, int>(1, 0)] = interpolationPolynomial.Field.One() }; var ySubstitution = new BiVariablePolynomial(interpolationPolynomial.Field) { [new Tuple <int, int>(0, 0)] = interpolationPolynomial.Field.One(), [new Tuple <int, int>(1, 1)] = interpolationPolynomial.Field.One() }; var factors = new HashSet <Polynomial>(); var currentFactorCoefficients = new Stack <int>(); Factorize(interpolationPolynomial, maxFactorDegree, xSubstitution, ySubstitution, factors, currentFactorCoefficients); return(factors.ToArray()); }
/// <summary> /// Method for dividing bivariate polynomial <paramref name="polynomial"/> by variable x in maximum possible degree /// </summary> /// <param name="polynomial">Modified polynomial</param> /// <returns>Dividing result</returns> public static BiVariablePolynomial DivideByMaxPossibleXDegree(this BiVariablePolynomial polynomial) { if (polynomial == null) { throw new ArgumentNullException(NameOfExtension.nameof(() => polynomial)); } var result = new BiVariablePolynomial(polynomial.Field); if (polynomial.IsZero) { return(result); } var minXDegree = polynomial.Min(x => x.Key.Item1); foreach (var coefficient in polynomial) { result[new Tuple <int, int>(coefficient.Key.Item1 - minXDegree, coefficient.Key.Item2)] = new FieldElement(coefficient.Value); } return(result); }
/// <summary> /// Method for calculating results of replacement bivariate polynomial <paramref name="polynomial"/> variable x by <paramref name="xSubstitution"/> and y by <paramref name="ySubstitution"/> /// </summary> /// <param name="polynomial">Modified polynomial</param> /// <param name="xSubstitution">Substitution for x variable</param> /// <param name="ySubstitution">Substitution for x variable</param> /// <returns>Replacement results</returns> public static BiVariablePolynomial PerformVariablesSubstitution(this BiVariablePolynomial polynomial, BiVariablePolynomial xSubstitution, BiVariablePolynomial ySubstitution) { if (polynomial == null) { throw new ArgumentNullException(NameOfExtension.nameof(() => polynomial)); } if (xSubstitution == null) { throw new ArgumentNullException(NameOfExtension.nameof(() => xSubstitution)); } if (ySubstitution == null) { throw new ArgumentNullException(NameOfExtension.nameof(() => ySubstitution)); } if (polynomial.Field.Equals(xSubstitution.Field) == false) { throw new ArithmeticException(NameOfExtension.nameof(() => xSubstitution)); } if (polynomial.Field.Equals(ySubstitution.Field) == false) { throw new ArithmeticException(NameOfExtension.nameof(() => ySubstitution)); } var result = new BiVariablePolynomial(polynomial.Field, polynomial.CoefficientsCount * (Math.Max(xSubstitution.CoefficientsCount, ySubstitution.CoefficientsCount) + 1)); var xCache = new Dictionary <int, BiVariablePolynomial>(polynomial.CoefficientsCount); var yCache = new Dictionary <int, BiVariablePolynomial>(polynomial.CoefficientsCount); foreach (var coefficient in polynomial) { result.Add(coefficient.Value, Pow(xCache, xSubstitution, coefficient.Key.Item1) * Pow(yCache, ySubstitution, coefficient.Key.Item2)); } return(result); }
/// <summary> /// Method for bivariate interpolation polynomial building /// </summary> /// <param name="degreeWeight">Weight of bivariate monomials degree</param> /// <param name="maxWeightedDegree">Maximum value of bivariate monomial degree</param> /// <param name="roots">Roots of the interpolation polynomial</param> /// <param name="rootsMultiplicity">Multiplicity of bivariate polynomial's roots</param> /// <returns>Builded interpolation polynomial</returns> public BiVariablePolynomial Build(Tuple <int, int> degreeWeight, int maxWeightedDegree, Tuple <FieldElement, FieldElement>[] roots, int rootsMultiplicity) { if (degreeWeight == null) { throw new ArgumentNullException(nameof(degreeWeight)); } if (roots == null) { throw new ArgumentNullException(nameof(roots)); } if (roots.Length == 0) { throw new ArgumentException($"{nameof(roots)} is empty"); } var field = roots[0].Item1.Field; var maxXDegree = maxWeightedDegree / degreeWeight.Item1; var maxYDegree = maxWeightedDegree / degreeWeight.Item2; var combinationsCache = new FieldElement[Math.Max(maxXDegree, maxYDegree) + 1][].MakeSquare(); var transformationMultiplier = new BiVariablePolynomial(field) { [new Tuple <int, int>(1, 0)] = field.One() }; var monomialsComparer = new BiVariableMonomialsComparer(degreeWeight); var buildingPolynomials = new BiVariablePolynomial[maxYDegree + 1]; var leadMonomials = new Tuple <int, int> [maxYDegree + 1]; for (var i = 0; i < buildingPolynomials.Length; i++) { var leadMonomial = new Tuple <int, int>(0, i); buildingPolynomials[i] = new BiVariablePolynomial(field, (maxXDegree + 1) * (maxYDegree + 1)) { [leadMonomial] = field.One() }; leadMonomials[i] = leadMonomial; } foreach (var root in roots) { for (var r = 0; r < rootsMultiplicity; r++) { for (var s = 0; r + s < rootsMultiplicity; s++) { var anyCompatiblePolynomialFound = false; var nonZeroDerivatives = new List <Tuple <int, FieldElement> >(); for (var i = 0; i < buildingPolynomials.Length; i++) { if (CalculateMonomialWeight(leadMonomials[i], degreeWeight) > maxWeightedDegree) { continue; } anyCompatiblePolynomialFound = true; var hasseDerivative = buildingPolynomials[i].CalculateHasseDerivative(r, s, root.Item1, root.Item2, _combinationsCountCalculator, combinationsCache); if (hasseDerivative.Representation != 0) { nonZeroDerivatives.Add(new Tuple <int, FieldElement>(i, hasseDerivative)); } } if (anyCompatiblePolynomialFound == false) { throw new NonTrivialPolynomialNotFoundException(); } if (nonZeroDerivatives.Count == 0) { continue; } var minimumIndex = FindMinimumIndexByLeadMonomial(nonZeroDerivatives, i => leadMonomials[nonZeroDerivatives[i].Item1], monomialsComparer); var minimumPolynomialIndex = nonZeroDerivatives[minimumIndex].Item1; var minimumPolynomial = buildingPolynomials[minimumPolynomialIndex]; var minimumDerivative = nonZeroDerivatives[minimumIndex].Item2; for (var i = 0; i < nonZeroDerivatives.Count; i++) { if (i != minimumIndex) { buildingPolynomials[nonZeroDerivatives[i].Item1] .Subtract(nonZeroDerivatives[i].Item2.Divide(minimumDerivative), minimumPolynomial); } } transformationMultiplier[_zeroMonomial] = FieldElement.InverseForAddition(root.Item1); minimumPolynomial .Multiply(minimumDerivative * transformationMultiplier); leadMonomials[minimumPolynomialIndex] = new Tuple <int, int>(leadMonomials[minimumPolynomialIndex].Item1 + 1, leadMonomials[minimumPolynomialIndex].Item2); } } } var resultPolynomialIndex = FindMinimumIndexByLeadMonomial(buildingPolynomials, i => leadMonomials[i], monomialsComparer); if (CalculateMonomialWeight(leadMonomials[resultPolynomialIndex], degreeWeight) > maxWeightedDegree) { throw new NonTrivialPolynomialNotFoundException(); } return(buildingPolynomials[resultPolynomialIndex]); }
public void ShouldCalculateHasseDerivative(BiVariablePolynomial polynomial, int r, int s, FieldElement xValue, FieldElement yValue, FieldElement expectedValue) { Assert.Equal(expectedValue, polynomial.CalculateHasseDerivative(r, s, xValue, yValue, _combinationsCountCalculator)); }
public void ShouldEvaluateY(BiVariablePolynomial polynomial, FieldElement yValue, Polynomial expectedResult) { Assert.Equal(expectedResult, polynomial.EvaluateY(yValue)); }
public void ShouldDivideByMaxPossibleXDegree(BiVariablePolynomial polynomial, BiVariablePolynomial expectedResult) { Assert.Equal(expectedResult, polynomial.DivideByMaxPossibleXDegree(), EqualityComparer <BiVariablePolynomial> .Default); }
public void ShouldPerformVariablesSubstitution(BiVariablePolynomial polynomial, BiVariablePolynomial xSubstitution, BiVariablePolynomial ySubstitution, BiVariablePolynomial expectedResult) { Assert.Equal(expectedResult, polynomial.PerformVariablesSubstitution(xSubstitution, ySubstitution), EqualityComparer <BiVariablePolynomial> .Default); }
public void ShouldMultiplyByFieldElement(BiVariablePolynomial a, FieldElement b, BiVariablePolynomial expectedResult) { Assert.Equal(expectedResult, a * b, EqualityComparer <BiVariablePolynomial> .Default); }
public void ShouldMultiplyTwoPolynomials(BiVariablePolynomial a, BiVariablePolynomial b, BiVariablePolynomial expectedResult) { Assert.Equal(expectedResult, a * b, EqualityComparer <BiVariablePolynomial> .Default); }
static BiVariablePolynomialTests() { Gf5 = new PrimeOrderField(5); var polynomialForEvoluation = new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 4) }; EvaluateTestsData = new[] { new object[] { polynomialForEvoluation, new FieldElement(Gf5, 1), new FieldElement(Gf5, 3), Gf5.Zero() }, new object[] { polynomialForEvoluation, new FieldElement(Gf5, 2), new FieldElement(Gf5, 4), Gf5.Zero() }, new object[] { polynomialForEvoluation, new FieldElement(Gf5, 3), new FieldElement(Gf5, 2), Gf5.Zero() }, new object[] { polynomialForEvoluation, new FieldElement(Gf5, 2), new FieldElement(Gf5, 3), Gf5.Zero() }, }; AddTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1) } } }; SubtractTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 1) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 4) } } }; MultiplyPolynomialsTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 2) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 2)] = new FieldElement(Gf5, 3) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4) }, new BiVariablePolynomial(Gf5), new BiVariablePolynomial(Gf5) } }; var polynomialForMultiplication = new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1) }; MultiplyByFieldElementTestsData = new[] { new object[] { polynomialForMultiplication, Gf5.Zero(), new BiVariablePolynomial(Gf5) }, new object[] { polynomialForMultiplication, new FieldElement(Gf5, 2), new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 2) } } }; SubstitutionTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 2) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 4), [new Tuple <int, int>(2, 1)] = new FieldElement(Gf5, 1) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2) }, new BiVariablePolynomial(Gf5), new BiVariablePolynomial(Gf5), new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 1) } } }; DivideByXDegreeTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 3) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3) } }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3) }, new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 3) } }, new object[] { new BiVariablePolynomial(Gf5), new BiVariablePolynomial(Gf5) } }; EvaluateXTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 1) }, new FieldElement(Gf5, 1), new Polynomial(Gf5, 0, 1) }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1) }, Gf5.Zero(), new Polynomial(Gf5, 3) }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 2)] = new FieldElement(Gf5, 1) }, new FieldElement(Gf5, 3), new Polynomial(Gf5, 4, 4, 1) } }; EvaluateYTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2) }, new FieldElement(Gf5, 1), new Polynomial(Gf5, 0, 1) }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1) }, Gf5.Zero(), new Polynomial(Gf5, 3) }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 3), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(1, 1)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 2)] = new FieldElement(Gf5, 1) }, new FieldElement(Gf5, 2), new Polynomial(Gf5, 3, 0, 2) } }; CalculateHasseDerivativeTestsData = new[] { new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 0)] = new FieldElement(Gf5, 1), [new Tuple <int, int>(0, 2)] = new FieldElement(Gf5, 1) }, 1, 1, Gf5.One(), Gf5.One(), Gf5.Zero() }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 2)] = new FieldElement(Gf5, 1) }, 1, 1, Gf5.One(), Gf5.One(), new FieldElement(Gf5, 4) }, new object[] { new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(0, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(1, 0)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(0, 1)] = new FieldElement(Gf5, 2), [new Tuple <int, int>(2, 2)] = new FieldElement(Gf5, 1) }, 2, 1, Gf5.One(), Gf5.One(), new FieldElement(Gf5, 2) } }; }
static BiVariablePolynomialTests() { Gf5 = new PrimeOrderField(5); var polynomialForEvoluation = new BiVariablePolynomial(Gf5) { [new Tuple <int, int>(1, 1)] = Gf5.CreateElement(2), [new Tuple <int, int>(0, 1)] = Gf5.One(), [new Tuple <int, int>(2, 0)] = Gf5.One(), [new Tuple <int, int>(1, 0)] = Gf5.One(), [new Tuple <int, int>(0, 0)] = Gf5.CreateElement(4) }; EvaluateTestsData = new TheoryData <EvaluationTestCase> { new EvaluationTestCase { Polynomial = polynomialForEvoluation, XValue = Gf5.One(), YValue = Gf5.CreateElement(3), Expected = Gf5.Zero() }, new EvaluationTestCase { Polynomial = polynomialForEvoluation, XValue = Gf5.CreateElement(2), YValue = new FieldElement(Gf5, 4), Expected = Gf5.Zero() }, new EvaluationTestCase { Polynomial = polynomialForEvoluation, XValue = Gf5.CreateElement(3), YValue = Gf5.CreateElement(2), Expected = Gf5.Zero() }, new EvaluationTestCase { Polynomial = polynomialForEvoluation, XValue = Gf5.CreateElement(2), YValue = Gf5.CreateElement(3), Expected = Gf5.Zero() }, }; AddTestsData = new TheoryData <BinaryOperationTestCase> { new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3) }, SecondOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) } }, new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, SecondOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 1)] = Gf5.CreateElement(4), [Tuple.Create(0, 0)] = Gf5.CreateElement(4), [Tuple.Create(1, 0)] = Gf5.CreateElement(4) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.CreateElement(3), [Tuple.Create(0, 0)] = Gf5.One() } } }; SubtractTestsData = new TheoryData <BinaryOperationTestCase> { new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3) }, SecondOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(4), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.One() } }, new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, SecondOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(4), [Tuple.Create(1, 0)] = Gf5.CreateElement(4), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 0)] = Gf5.CreateElement(4) } } }; MultiplyPolynomialsTestsData = new TheoryData <BinaryOperationTestCase> { new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3) }, SecondOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One(), [Tuple.Create(1, 0)] = Gf5.CreateElement(4), [Tuple.Create(0, 1)] = Gf5.CreateElement(3), [Tuple.Create(1, 1)] = Gf5.CreateElement(2) } }, new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, SecondOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(4), [Tuple.Create(1, 0)] = Gf5.One(), [Tuple.Create(0, 1)] = Gf5.CreateElement(2) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 0)] = Gf5.CreateElement(4), [Tuple.Create(2, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 2)] = Gf5.CreateElement(3) } }, new BinaryOperationTestCase { FirstOperand = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(4) }, SecondOperand = new BiVariablePolynomial(Gf5), Expected = new BiVariablePolynomial(Gf5) } }; var polynomialForMultiplication = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.CreateElement(4), [Tuple.Create(1, 1)] = Gf5.One() }; MultiplyByFieldElementTestsData = new TheoryData <MultiplicationByFieldElementTestCase> { new MultiplicationByFieldElementTestCase { Polynomial = polynomialForMultiplication, Multiplier = Gf5.Zero(), Expected = new BiVariablePolynomial(Gf5) }, new MultiplicationByFieldElementTestCase { Polynomial = polynomialForMultiplication, Multiplier = Gf5.CreateElement(2), Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One(), [Tuple.Create(1, 0)] = Gf5.CreateElement(4), [Tuple.Create(0, 1)] = Gf5.CreateElement(3), [Tuple.Create(1, 1)] = Gf5.CreateElement(2) } } }; SubstitutionTestsData = new TheoryData <SubstitutionTestCase> { new SubstitutionTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One(), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(2) }, XSubstitution = new BiVariablePolynomial(Gf5) { [Tuple.Create(1, 0)] = Gf5.One() }, YSubstitution = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 1)] = Gf5.One() }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 1)] = Gf5.CreateElement(2) } }, new SubstitutionTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One(), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(2, 0)] = Gf5.One(), [Tuple.Create(0, 1)] = Gf5.CreateElement(3), [Tuple.Create(1, 1)] = Gf5.One() }, XSubstitution = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One(), [Tuple.Create(1, 0)] = Gf5.One() }, YSubstitution = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 1)] = Gf5.One() }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.One(), [Tuple.Create(2, 0)] = Gf5.One(), [Tuple.Create(1, 1)] = Gf5.CreateElement(4), [Tuple.Create(2, 1)] = Gf5.One() } }, new SubstitutionTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One(), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(2) }, XSubstitution = new BiVariablePolynomial(Gf5), YSubstitution = new BiVariablePolynomial(Gf5), Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.One() } } }; DivideByXDegreeTestsData = new TheoryData <DivideByXDegreeTestCase> { new DivideByXDegreeTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(2, 0)] = Gf5.One(), [Tuple.Create(1, 1)] = Gf5.CreateElement(3) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.One(), [Tuple.Create(0, 1)] = Gf5.CreateElement(3) } }, new DivideByXDegreeTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(2, 0)] = Gf5.One(), [Tuple.Create(0, 1)] = Gf5.CreateElement(3) }, Expected = new BiVariablePolynomial(Gf5) { [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(2, 0)] = Gf5.One(), [Tuple.Create(0, 1)] = Gf5.CreateElement(3) } }, new DivideByXDegreeTestCase { Polynomial = new BiVariablePolynomial(Gf5), Expected = new BiVariablePolynomial(Gf5) } }; EvaluateXTestsData = new TheoryData <PartialEvaluationTestCase> { new PartialEvaluationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.One() }, VariableValue = Gf5.One(), Expected = new Polynomial(Gf5, 0, 1) }, new PartialEvaluationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 1)] = Gf5.One() }, VariableValue = Gf5.Zero(), Expected = new Polynomial(Gf5, 3) }, new PartialEvaluationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(2, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.One(), [Tuple.Create(1, 1)] = Gf5.One(), [Tuple.Create(0, 2)] = Gf5.One() }, VariableValue = Gf5.CreateElement(3), Expected = new Polynomial(Gf5, 4, 4, 1) } }; EvaluateYTestsData = new TheoryData <PartialEvaluationTestCase> { new PartialEvaluationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(1, 0)] = Gf5.One(), [Tuple.Create(0, 1)] = Gf5.CreateElement(2) }, VariableValue = Gf5.One(), Expected = new Polynomial(Gf5, 0, 1) }, new PartialEvaluationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(3), [Tuple.Create(0, 1)] = Gf5.CreateElement(2), [Tuple.Create(1, 1)] = Gf5.One() }, VariableValue = Gf5.Zero(), Expected = new Polynomial(Gf5, 3) }, new PartialEvaluationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(3), [Tuple.Create(2, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.One(), [Tuple.Create(1, 1)] = Gf5.One(), [Tuple.Create(0, 2)] = Gf5.One() }, VariableValue = Gf5.CreateElement(2), Expected = new Polynomial(Gf5, 3, 0, 2) } }; HasseDerivativeCalculationTestsData = new TheoryData <HasseDerivativeCalculationTestCase> { new HasseDerivativeCalculationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.CreateElement(2), [Tuple.Create(2, 0)] = Gf5.One(), [Tuple.Create(0, 2)] = Gf5.One() }, R = 1, S = 1, XValue = Gf5.One(), YValue = Gf5.One(), Expected = Gf5.Zero() }, new HasseDerivativeCalculationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.CreateElement(2), [Tuple.Create(2, 2)] = Gf5.One() }, R = 1, S = 1, XValue = Gf5.One(), YValue = Gf5.One(), Expected = new FieldElement(Gf5, 4) }, new HasseDerivativeCalculationTestCase { Polynomial = new BiVariablePolynomial(Gf5) { [Tuple.Create(0, 0)] = Gf5.CreateElement(2), [Tuple.Create(1, 0)] = Gf5.CreateElement(2), [Tuple.Create(0, 1)] = Gf5.CreateElement(2), [Tuple.Create(2, 2)] = Gf5.One() }, R = 2, S = 1, XValue = Gf5.One(), YValue = Gf5.One(), Expected = Gf5.CreateElement(2) } }; }