/// <summary>
        /// Obtém o quociente e o resto da pseudo-divisão entre dois polinómios.
        /// </summary>
        /// <param name="dividend">O dividendo.</param>
        /// <param name="divisor">O divisor.</param>
        /// <returns>O quociente e o resto.</returns>
        /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
        /// <exception cref="ArgumentException">
        /// Se algum dos polinómio contiver uma variável diferente da estipulada para o
        /// domínio corrente.
        /// </exception>
        public DomainResult <UnivariatePolynomialNormalForm <CoeffType> > GetQuotientAndRemainder(
            UnivariatePolynomialNormalForm <CoeffType> dividend,
            UnivariatePolynomialNormalForm <CoeffType> 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 (divisor.Degree > dividend.Degree)
                {
                    return(new DomainResult <UnivariatePolynomialNormalForm <CoeffType> >(
                               new UnivariatePolynomialNormalForm <CoeffType>(this.variableName),
                               dividend));
                }
                else
                {
                    var remainderSortedCoeffs  = dividend.GetOrderedCoefficients(Comparer <int> .Default);
                    var divisorSorteCoeffs     = divisor.GetOrderedCoefficients(Comparer <int> .Default);
                    var quotientCoeffs         = new UnivariatePolynomialNormalForm <CoeffType>(this.variableName);
                    var remainderLeadingDegree = remainderSortedCoeffs.Keys[remainderSortedCoeffs.Keys.Count - 1];
                    var divisorLeadingDegree   = divisorSorteCoeffs.Keys[divisorSorteCoeffs.Keys.Count - 1];
                    var divisorLeadingCoeff    = divisorSorteCoeffs.Values[divisorSorteCoeffs.Values.Count - 1];
                    var multiplyNumber         = MathFunctions.Power(
                        divisorLeadingCoeff,
                        remainderLeadingDegree - divisorLeadingDegree + 1,
                        this.ring);
                    var temporaryRemainderCoeffs = new SortedList <int, CoeffType>(Comparer <int> .Default);
                    foreach (var kvp in remainderSortedCoeffs)
                    {
                        temporaryRemainderCoeffs.Add(
                            kvp.Key,
                            this.ring.Multiply(kvp.Value, multiplyNumber));
                    }

                    remainderSortedCoeffs = temporaryRemainderCoeffs;
                    while (remainderLeadingDegree >= divisorLeadingDegree && remainderSortedCoeffs.Count > 0)
                    {
                        var remainderLeadingCoeff = remainderSortedCoeffs[remainderLeadingDegree];
                        var differenceDegree      = remainderLeadingDegree - divisorLeadingDegree;
                        var factor = this.coeffsDomain.Quo(remainderLeadingCoeff, divisorLeadingCoeff);
                        quotientCoeffs = quotientCoeffs.Add(factor, differenceDegree, this.ring);
                        remainderSortedCoeffs.Remove(remainderLeadingDegree);
                        for (int i = 0; i < divisorSorteCoeffs.Keys.Count - 1; ++i)
                        {
                            var currentDivisorDegree = divisorSorteCoeffs.Keys[i];
                            var currentCoeff         = this.ring.Multiply(
                                divisorSorteCoeffs[currentDivisorDegree],
                                factor);
                            currentDivisorDegree += differenceDegree;
                            var addCoeff = default(CoeffType);
                            if (remainderSortedCoeffs.TryGetValue(currentDivisorDegree, out addCoeff))
                            {
                                addCoeff = this.ring.Add(
                                    addCoeff,
                                    this.ring.AdditiveInverse(currentCoeff));
                                if (this.ring.IsAdditiveUnity(addCoeff))
                                {
                                    remainderSortedCoeffs.Remove(currentDivisorDegree);
                                }
                                else
                                {
                                    remainderSortedCoeffs[currentDivisorDegree] = addCoeff;
                                }
                            }
                            else
                            {
                                remainderSortedCoeffs.Add(
                                    currentDivisorDegree,
                                    this.ring.AdditiveInverse(currentCoeff));
                            }
                        }

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

                    var remainder = new UnivariatePolynomialNormalForm <CoeffType>(
                        remainderSortedCoeffs,
                        this.variableName,
                        this.ring);
                    return(new DomainResult <UnivariatePolynomialNormalForm <CoeffType> >(
                               quotientCoeffs,
                               remainder));
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Processa o polinómio determinando os respectivos factores.
        /// </summary>
        /// <remarks>
        /// Os factores constantes são ignorados, os factores lineares são anexados ao resultado e os factores
        /// cujos graus são superiores são retornados para futuro processamento. Se o polinómio a ser processado
        /// for irredutível, é adicionado ao resultado.
        /// </remarks>
        /// <param name="polynom">O polinómio a ser processado.</param>
        /// <param name="result">O contentor dos factores sucessivamente processados.</param>
        /// <param name="integerModule">O objecto responsável pelas operações sobre inteiros.</param>
        /// <param name="polynomField">O objecto responsável pelas operações sobre os polinómios.</param>
        /// <param name="inverseAlgorithm">O algoritmo inverso.</param>
        /// <returns></returns>
        List <UnivariatePolynomialNormalForm <CoeffType> > Process(
            UnivariatePolynomialNormalForm <CoeffType> polynom,
            List <UnivariatePolynomialNormalForm <CoeffType> > result,
            IModularField <CoeffType> integerModule,
            UnivarPolynomEuclideanDomain <CoeffType> polynomField,
            LagrangeAlgorithm <UnivariatePolynomialNormalForm <CoeffType> > inverseAlgorithm)
        {
            var resultPol = new List <UnivariatePolynomialNormalForm <CoeffType> >();

            if (polynom.Degree < 2)
            {
                result.Add(polynom);
            }
            else
            {
                var module = new ModularBachetBezoutField <UnivariatePolynomialNormalForm <CoeffType> >(
                    polynom,
                    inverseAlgorithm);

                var degree      = polynom.Degree;
                var arrayMatrix = new ArrayMathMatrix <CoeffType>(degree, degree, integerModule.AdditiveUnity);
                arrayMatrix[0, 0] = integerModule.AdditiveUnity;
                var pol = new UnivariatePolynomialNormalForm <CoeffType>(
                    integerModule.MultiplicativeUnity,
                    1,
                    polynom.VariableName,
                    integerModule);

                var integerModuleValue = this.integerNumber.ConvertToInt(integerModule.Module);

                pol = MathFunctions.Power(pol, integerModuleValue, module);
                foreach (var term in pol)
                {
                    arrayMatrix[term.Key, 1] = term.Value;
                }

                var auxPol = pol;
                for (int i = 2; i < degree; ++i)
                {
                    auxPol = module.Multiply(auxPol, pol);
                    foreach (var term in auxPol)
                    {
                        arrayMatrix[term.Key, i] = term.Value;
                    }
                }

                for (int i = 1; i < degree; ++i)
                {
                    var value = arrayMatrix[i, i];
                    value = integerModule.Add(
                        value,
                        integerModule.AdditiveInverse(integerModule.MultiplicativeUnity));
                    arrayMatrix[i, i] = value;
                }

                var emtpyMatrix          = new ZeroMatrix <CoeffType>(degree, 1, integerModule);
                var linearSystemSolution = this.linearSystemSolver.Run(arrayMatrix, emtpyMatrix);

                var numberOfFactors = linearSystemSolution.VectorSpaceBasis.Count;
                if (numberOfFactors < 2)
                {
                    result.Add(polynom);
                }
                else
                {
                    var hPol = default(UnivariatePolynomialNormalForm <CoeffType>);
                    var linearSystemCount = linearSystemSolution.VectorSpaceBasis.Count;
                    for (int i = 0; i < linearSystemCount; ++i)
                    {
                        var currentBaseSolution = linearSystemSolution.VectorSpaceBasis[i];
                        var rowsLength          = currentBaseSolution.Length;
                        for (int j = 1; j < rowsLength; ++j)
                        {
                            if (!integerModule.IsAdditiveUnity(currentBaseSolution[j]))
                            {
                                hPol = this.GetPolynomial(currentBaseSolution, integerModule, polynom.VariableName);
                                j    = rowsLength;
                            }

                            if (hPol != null)
                            {
                                j = rowsLength;
                            }
                        }

                        if (hPol != null)
                        {
                            i = linearSystemCount;
                        }
                    }

                    for (int i = 0, k = 0; k < numberOfFactors && i < integerModuleValue; ++i)
                    {
                        var converted  = this.integerNumber.MapFrom(i);
                        var currentPol = MathFunctions.GreatCommonDivisor(
                            polynom,
                            hPol.Subtract(converted, integerModule),
                            polynomField);
                        var currentDegree = currentPol.Degree;
                        if (currentDegree == 1)
                        {
                            result.Add(currentPol);
                            ++k;
                        }
                        else if (currentDegree > 1)
                        {
                            resultPol.Add(currentPol);
                            ++k;
                        }
                    }
                }
            }

            return(resultPol);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Averigua se o número especificado é primo.
        /// </summary>
        /// <param name="data">O número.</param>
        /// <returns>Verdadeiro caso o número seja primo e falso caso este seja composto.</returns>
        public bool Run(int data)
        {
            if (this.integerNumber.IsAdditiveUnity(data))
            {
                return(false);
            }
            else if (
                this.integerNumber.IsMultiplicativeUnity(data) ||
                this.integerNumber.IsMultiplicativeUnity(this.integerNumber.AdditiveInverse(data)))
            {
                return(false);
            }
            else
            {
                var innerData = this.integerNumber.GetNorm(data);
                var two       = this.integerNumber.MapFrom(2);
                if (this.integerNumber.Equals(innerData, two))
                {
                    return(true);
                }
                else if (this.perfectPowerTest.Run(data))
                {
                    return(false);
                }
                else
                {
                    var log = Math.Log(innerData) / Math.Log(2);
                    var r   = this.EvaluateLimitValue(innerData, log);
                    r = this.totientFunctionAlg.Run(r);
                    var i = two;
                    for (; this.integerNumber.Compare(i, r) <= 0; i = this.integerNumber.Successor(i))
                    {
                        var gcd = MathFunctions.GreatCommonDivisor(innerData, i, this.integerNumber);
                        if (this.integerNumber.Compare(gcd, this.integerNumber.MultiplicativeUnity) > 0 &&
                            this.integerNumber.Compare(gcd, innerData) < 0)
                        {
                            return(false);
                        }
                    }

                    var limit        = (int)Math.Floor(Math.Sqrt(r) * log);
                    var modularField = this.modularFactory.CreateInstance(innerData);
                    var terms        = new Dictionary <int, int>();

                    var modularPolynomialRing = new AuxAksModArithmRing <int>(
                        r,
                        "x",
                        modularField);
                    for (int j = 1; j <= limit; ++j)
                    {
                        terms.Clear();
                        terms.Add(0, j);
                        terms.Add(1, 1);
                        var polynomial = new UnivariatePolynomialNormalForm <int>(
                            terms,
                            "x",
                            modularField);

                        terms.Clear();
                        terms.Add(0, j);
                        terms.Add(innerData, 1);
                        var comparisionPol = new UnivariatePolynomialNormalForm <int>(
                            terms,
                            "x",
                            modularField);

                        var poweredPol = MathFunctions.Power(polynomial, innerData, modularPolynomialRing);
                        if (!poweredPol.Equals(modularPolynomialRing.GetReduced(comparisionPol)))
                        {
                            return(false);
                        }
                    }

                    return(true);
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Determina o resíduo quadrático de um número módulo o número primo ímpar especificado.
        /// </summary>
        /// <remarks>
        /// Se o módulo não for um número primo ímpar, os resultados estarão errados. Esta verificação
        /// não é realizada sobre esse módulo.
        /// </remarks>
        /// <param name="number">O número.</param>
        /// <param name="primeModule">O número primo que servirá de módulo.</param>
        /// <returns>A lista com os dois resíduos.</returns>
        /// <exception cref="ArgumentException">
        /// Se o módulo não for superior a dois, se o módulo for par ou se a solução não existir.
        /// </exception>
        public List <NumberType> Run(NumberType number, NumberType primeModule)
        {
            var two = this.integerNumber.MapFrom(2);

            if (this.integerNumber.Compare(primeModule, two) < 0)
            {
                throw new ArgumentException("The prime module must be a number greater than two.");
            }
            if (this.integerNumber.IsAdditiveUnity(this.integerNumber.Rem(primeModule, two)))
            {
                throw new ArgumentException("The prime module must be an even number.");
            }
            else if (!this.integerNumber.IsMultiplicativeUnity(this.legendreJacobiSymAlg.Run(number, primeModule)))
            {
                throw new ArgumentException("Solution doesn't exist.");
            }
            else
            {
                var innerNumber     = this.integerNumber.Rem(number, primeModule);
                var firstStepModule = this.integerNumber.Predecessor(primeModule);
                var power           = this.integerNumber.AdditiveUnity;
                var remQuoResult    = this.integerNumber.GetQuotientAndRemainder(firstStepModule, two);
                while (this.integerNumber.IsAdditiveUnity(remQuoResult.Remainder))
                {
                    power           = this.integerNumber.Successor(power);
                    firstStepModule = remQuoResult.Quotient;
                    remQuoResult    = this.integerNumber.GetQuotientAndRemainder(firstStepModule, two);
                }

                var modularIntegerField = this.modularFieldFactory.CreateInstance(primeModule);
                if (this.integerNumber.IsMultiplicativeUnity(power))
                {
                    var tempPower = this.integerNumber.Successor(primeModule);
                    tempPower = this.integerNumber.Quo(tempPower, this.integerNumber.MapFrom(4));
                    var value  = MathFunctions.Power(number, tempPower, modularIntegerField, this.integerNumber);
                    var result = new List <NumberType>()
                    {
                        value,
                        this.integerNumber.Add(primeModule, this.integerNumber.AdditiveInverse(value))
                    };
                    return(result);
                }
                else
                {
                    var nonQuadraticResidue       = this.FindNonQuadraticResidue(primeModule);
                    var poweredNonQuadraticResult = MathFunctions.Power(
                        nonQuadraticResidue,
                        firstStepModule,
                        modularIntegerField,
                        this.integerNumber);

                    var innerPower = this.integerNumber.Successor(firstStepModule);
                    innerPower = this.integerNumber.Quo(innerPower, two);
                    var result = MathFunctions.Power(innerNumber, innerPower, modularIntegerField, this.integerNumber);
                    var temp   = MathFunctions.Power(innerNumber, firstStepModule, modularIntegerField, this.integerNumber);
                    while (!this.integerNumber.IsMultiplicativeUnity(temp))
                    {
                        var lowestIndex = this.FindLowestIndex(temp, power, modularIntegerField);
                        var aux         = this.SquareValue(
                            poweredNonQuadraticResult,
                            this.integerNumber.Add(power, this.integerNumber.AdditiveInverse(this.integerNumber.Successor(lowestIndex))),
                            modularIntegerField);
                        result = modularIntegerField.Multiply(result, aux);
                        aux    = modularIntegerField.Multiply(aux, aux);
                        temp   = modularIntegerField.Multiply(temp, aux);
                        poweredNonQuadraticResult = aux;
                        power = lowestIndex;
                    }

                    return(new List <NumberType>()
                    {
                        result,
                        this.integerNumber.Add(primeModule, this.integerNumber.AdditiveInverse(result))
                    });
                }
            }
        }