コード例 #1
0
        /// <summary>
        /// Calcula o resto da divisão entre dois polinómios.
        /// </summary>
        /// <param name="dividend">O dividendo.</param>
        /// <param name="divisor">O divisor.</param>
        /// <returns>O resto.</returns>
        /// <exception cref="ArgumentNullException">Caso algum dos argumentos seja nulo.</exception>
        /// <exception cref="ArgumentException">Se os polinómios contiverem variáveis cujos nomes são diferentes.</exception>
        /// <exception cref="DivideByZeroException">Se o divisor for uma unidade aditiva.</exception>
        public GeneralDegUnivarPolynomNormalForm <CoeffType, DegreeType> Rem(
            GeneralDegUnivarPolynomNormalForm <CoeffType, DegreeType> dividend,
            GeneralDegUnivarPolynomNormalForm <CoeffType, DegreeType> divisor)
        {
            if (dividend == null)
            {
                throw new ArgumentNullException("dividend");
            }
            else if (divisor == null)
            {
                throw new ArgumentNullException("divisor");
            }
            else if (divisor.VariableName != divisor.VariableName)
            {
                throw new ArgumentException("Polynomials must share the same variable name in order to be operated.");
            }
            else
            {
                if (this.IsAdditiveUnity(divisor))
                {
                    throw new DivideByZeroException("Can't divide by the null polynomial.");
                }
                else if (this.IsAdditiveUnity(dividend))
                {
                    return(this.AdditiveUnity);
                }
                else if (this.integerNumber.Compare(divisor.Degree, dividend.Degree) > 0)
                {
                    return(dividend.Clone());
                }
                else
                {
                    var remainderSortedCoeffs      = dividend.GetOrderedCoefficients(this.integerNumber);
                    var divisorSorteCoeffs         = divisor.GetOrderedCoefficients(this.integerNumber);
                    var remainderLeadingDegree     = remainderSortedCoeffs.Keys[remainderSortedCoeffs.Keys.Count - 1];
                    var divisorLeadingDegree       = divisorSorteCoeffs.Keys[divisorSorteCoeffs.Keys.Count - 1];
                    var inverseDivisorLeadingCoeff = this.field.MultiplicativeInverse(divisorSorteCoeffs[divisorLeadingDegree]);
                    while (this.integerNumber.Compare(remainderLeadingDegree, divisorLeadingDegree) >= 0 &&
                           remainderSortedCoeffs.Count > 0)
                    {
                        var remainderLeadingCoeff = remainderSortedCoeffs[remainderLeadingDegree];
                        var differenceDegree      = this.integerNumber.Add(
                            remainderLeadingDegree,
                            this.integerNumber.AdditiveInverse(divisorLeadingDegree));
                        var factor = this.field.Multiply(
                            remainderLeadingCoeff,
                            inverseDivisorLeadingCoeff);
                        remainderSortedCoeffs.Remove(remainderLeadingDegree);
                        for (int i = 0; i < divisorSorteCoeffs.Keys.Count - 1; ++i)
                        {
                            var currentDivisorDegree = divisorSorteCoeffs.Keys[i];
                            var currentCoeff         = this.field.Multiply(
                                divisorSorteCoeffs[currentDivisorDegree],
                                factor);
                            currentDivisorDegree = this.integerNumber.Add(currentDivisorDegree, differenceDegree);
                            var addCoeff = default(CoeffType);
                            if (remainderSortedCoeffs.TryGetValue(currentDivisorDegree, out addCoeff))
                            {
                                addCoeff = this.field.Add(
                                    addCoeff,
                                    this.field.AdditiveInverse(currentCoeff));
                                if (this.field.IsAdditiveUnity(addCoeff))
                                {
                                    remainderSortedCoeffs.Remove(currentDivisorDegree);
                                }
                                else
                                {
                                    remainderSortedCoeffs[currentDivisorDegree] = addCoeff;
                                }
                            }
                            else
                            {
                                remainderSortedCoeffs.Add(
                                    currentDivisorDegree,
                                    this.field.AdditiveInverse(currentCoeff));
                            }
                        }

                        if (remainderSortedCoeffs.Count > 0)
                        {
                            remainderLeadingDegree = remainderSortedCoeffs.Keys[remainderSortedCoeffs.Keys.Count - 1];
                        }
                        else
                        {
                            remainderLeadingDegree = this.integerNumber.AdditiveUnity;
                        }
                    }

                    var remainder = new GeneralDegUnivarPolynomNormalForm <CoeffType, DegreeType>(
                        remainderSortedCoeffs,
                        this.variableName,
                        this.field,
                        this.integerNumber);
                    return(remainder);
                }
            }
        }