/// <summary>
        /// Method for transforming linear system matrix into rectangular form and finding system solution
        /// </summary>
        /// <param name="field">Finite field from which system coefficients were taken</param>
        /// <param name="variablesCount">Variables count</param>
        /// <param name="equationsSystem">Linear system's representation</param>
        /// <returns>Linear system's solution</returns>
        private SystemSolution SolveEquationsSystem(
            GaloisField field,
            int variablesCount,
            IReadOnlyList <List <Tuple <int, FieldElement> > > equationsSystem)
        {
            var linearSystemMatrix = new FieldElement[equationsSystem.Count, variablesCount];
            var zeros = new FieldElement[equationsSystem.Count];

            for (var i = 0; i < equationsSystem.Count; i++)
            {
                zeros[i] = field.Zero();
                for (var j = 0; j < variablesCount; j++)
                {
                    linearSystemMatrix[i, j] = field.Zero();
                }
            }
            for (var i = 0; i < equationsSystem.Count; i++)
            {
                for (var j = 0; j < equationsSystem[i].Count; j++)
                {
                    linearSystemMatrix[i, equationsSystem[i][j].Item1] = equationsSystem[i][j].Item2;
                }
            }

            return(_linearSystemSolver.Solve(linearSystemMatrix, zeros));
        }
        /// <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);
        }
Exemple #3
0
        private static IEnumerable <FieldElement[]> PlaceErrors(GaloisField field,
                                                                int codewordLength,
                                                                IReadOnlyList <int> errorsPositions,
                                                                IList <int> noiseValue,
                                                                int currentErrorPosition)
        {
            if (currentErrorPosition == errorsPositions.Count)
            {
                var additiveNoise = Enumerable.Repeat(field.Zero(), codewordLength).ToArray();
                for (var i = 0; i < errorsPositions.Count; i++)
                {
                    additiveNoise[errorsPositions[i]] = field.CreateElement(noiseValue[i]);
                }
                yield return(additiveNoise);

                yield break;
            }

            for (var i = noiseValue[currentErrorPosition]; i < field.Order; i++)
            {
                noiseValue[currentErrorPosition] = i;

                foreach (var additiveNoise in PlaceErrors(field, codewordLength, errorsPositions, noiseValue, currentErrorPosition + 1))
                {
                    yield return(additiveNoise);
                }
            }
            noiseValue[currentErrorPosition] = 1;
        }
        /// <summary>
        /// Indexing property for obtain bivariate polynomial coefficient by <paramref name="monomial"/>
        /// </summary>
        /// <param name="monomial">Monomial which coefficient is required</param>
        /// <returns>Bivariate polynomial coefficient</returns>
        public FieldElement this[Tuple <int, int> monomial]
        {
            get
            {
                FieldElement coefficient;
                if (_coefficients.TryGetValue(monomial, out coefficient) == false)
                {
                    coefficient = Field.Zero();
                }
                return(coefficient);
            }
            set
            {
                if (Field.Equals(value.Field) == false)
                {
                    throw new ArgumentException("Incorrect field");
                }

                if (value.Representation != 0)
                {
                    _coefficients[monomial] = value;
                }
                else
                {
                    _coefficients.Remove(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 #6
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)
                }
                };
        }