/// <summary>
        /// Method for calculating number of combinations from <paramref name="n"/> by <paramref name="k"/> over field <paramref name="field"/>
        /// </summary>
        /// <param name="field">Field over which combinations count'll calculated</param>
        /// <param name="n">Total elements count</param>
        /// <param name="k">Selected elements count</param>
        /// <param name="combinationsCache">Cache for storing combinations count</param>
        /// <returns>Combinations count</returns>
        public FieldElement Calculate(GaloisField field, int n, int k, FieldElement[][] combinationsCache = null)
        {
            var combinationsCount = combinationsCache?[n][k];

            if (combinationsCount == null)
            {
                if (k == 0 || n == k)
                {
                    combinationsCount = field.One();
                }
                else
                {
                    if (n < k)
                    {
                        combinationsCount = field.Zero();
                    }
                    else
                    {
                        combinationsCount = Calculate(field, n - 1, k - 1, combinationsCache)
                                            + Calculate(field, n - 1, k, combinationsCache);
                    }
                }

                if (combinationsCache != null && n < combinationsCache.Length && k < combinationsCache[n].Length)
                {
                    combinationsCache[n][k] = combinationsCount;
                }
            }

            return(combinationsCount);
        }
        public void ShouldChangeCoefficients(int coefficientValueRepresentation)
        {
            // Given
            var monomial   = new Tuple <int, int>(1, 1);
            var polynomial = new BiVariablePolynomial(Gf5)
            {
                [monomial] = Gf5.One()
            };
            var coefficientValue = new FieldElement(Gf5, coefficientValueRepresentation);

            // When
            polynomial[monomial] = coefficientValue;

            // Then
            Assert.Equal(coefficientValue, polynomial[monomial]);
        }
        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)
                }
            };
        }
Exemple #4
0
        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)
                }
                };
        }