Ejemplo n.º 1
0
        /// <summary>
        /// Verifica se o módulo do número especificado consiste numa potência perfeita.
        /// </summary>
        /// <param name="data">O número a testar.</param>
        /// <returns>Verdadeiro caso o número seja uma potência perfeita e falso no caso contrário.</returns>
        public bool Run(int data)
        {
            var innerData = Math.Abs(data);

            if (innerData == 0)
            {
                return(true);
            }
            else if (innerData == 1)
            {
                return(true);
            }
            else
            {
                var maximumTestValue     = (int)Math.Floor(Math.Log(innerData) / Math.Log(2));
                var primeNumbersIterator = this.primeNumbersIteratorFactory.CreatePrimeNumberIterator(
                    maximumTestValue + 1);
                foreach (var prime in primeNumbersIterator)
                {
                    var root  = (int)Math.Floor(Math.Pow(innerData, 1.0 / prime));
                    var power = MathFunctions.Power(root, prime, this.integerDomain);
                    if (power == innerData)
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Determina a potência do elemento.
 /// </summary>
 /// <param name="left">O elemento.</param>
 /// <param name="right">O expoente.</param>
 /// <returns>O resultado da potência.</returns>
 /// <exception cref="MathematicsException">
 /// Se nenhum objecto responsável pelas operações sobre inteiros foi providenciado.
 /// </exception>
 protected virtual ObjectType Power(
     ObjectType left,
     ObjectType right)
 {
     if (this.integerNumber == null)
     {
         throw new MathematicsException("No integer number arithmetic operations class was provided.");
     }
     else
     {
         return(MathFunctions.Power(left, right, this.ring, this.integerNumber));
     }
 }
        /// <summary>
        /// Obtém o valor da estimativa para o valor máximo dos números primos a serem gerados.
        /// </summary>
        /// <param name="polynomialNorm">A norma do polinómio.</param>
        /// <param name="degree">O grau do polinómio.</param>
        /// <returns>O valor para o número primo máximo.</returns>
        private CoeffType ComputeGamma(CoeffType polynomialNorm, int degree)
        {
            var result = this.integerNumber.Successor(
                this.integerNumber.MapFrom(degree));
            var doubleDegree = 2 * degree;

            result = MathFunctions.Power(result, doubleDegree, this.integerNumber);
            var temp = MathFunctions.Power(polynomialNorm, doubleDegree + 1, this.integerNumber);

            result = this.integerNumber.Multiply(result, temp);
            var doubleLogResult = this.logarithmAlgorithm.Run(result) * 2;

            doubleLogResult = Math.Ceiling(doubleLogResult);
            doubleLogResult = 2 * doubleLogResult * Math.Log(doubleLogResult);
            return(this.integerNumber.MapFrom((int)Math.Floor(doubleLogResult)));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Calcula o produto de um dicionário com os factores e respectivas potências.
        /// </summary>
        /// <param name="factors">O dicionário com os factores e respectivas potências.</param>
        /// <returns>O valor do produto.</returns>
        private int ComputeProduct(Dictionary <int, int> factors)
        {
            var result = 1;

            foreach (var kvp in factors)
            {
                if (kvp.Value == 1)
                {
                    result *= kvp.Key;
                }
                else if (kvp.Value == 2)
                {
                    result *= kvp.Key * kvp.Key;
                }
                else
                {
                    result *= MathFunctions.Power(kvp.Key, kvp.Value, this.integerEuclideanDomain);
                }
            }

            return(result);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Establece os parâmetros internos com base nos argumentos externos.
 /// </summary>
 /// <param name="integerPart">A parte inteira da raiz.</param>
 /// <param name="rootNumberFactorization">A factorização do radicando.</param>
 /// <param name="multipliable">O objecto responsável pela multiplicação de coeficientes.</param>
 /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
 private void SetupParameters(
     ObjectType integerPart,
     Dictionary <ObjectType, int> rootNumberFactorization,
     IMultiplication <ObjectType> multipliable)
 {
     if (integerPart == null)
     {
         throw new ArgumentNullException("integerPart");
     }
     else if (rootNumberFactorization == null)
     {
         throw new ArgumentNullException("rootNumberFactorization");
     }
     else if (multipliable == null)
     {
         throw new ArgumentNullException("multipliable");
     }
     else
     {
         this.integerPart             = integerPart;
         this.rootNumberFactorization = new Dictionary <ObjectType, int>(rootNumberFactorization.Comparer);
         foreach (var fact in rootNumberFactorization)
         {
             var factDegree       = fact.Value;
             var factSquaredValue = factDegree / 2;
             var factRem          = factDegree % 2;
             this.integerPart = multipliable.Multiply(
                 this.integerPart,
                 MathFunctions.Power(fact.Key, factSquaredValue, multipliable));
             if (factRem == 1)
             {
                 rootNumberFactorization.Add(fact.Key, 1);
             }
         }
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Obtém o último sub-resultante entre dois polinómios.
        /// </summary>
        /// <param name="first">O primeiro polinómio.</param>
        /// <param name="second">O segundo polinómio.</param>
        /// <param name="domain">O domínio responsável pelas operações sobre os coeficientes.</param>
        /// <returns>O polinómio que constitui o último sub-resultante.</returns>
        /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
        public UnivariatePolynomialNormalForm <CoeffType> Run(
            UnivariatePolynomialNormalForm <CoeffType> first,
            UnivariatePolynomialNormalForm <CoeffType> second,
            IEuclidenDomain <CoeffType> domain)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            else if (second == null)
            {
                throw new ArgumentNullException("second");
            }
            else if (domain == null)
            {
                throw new ArgumentNullException("domain");
            }
            else
            {
                var pseudoDomain   = new UnivarPolynomPseudoDomain <CoeffType>(first.VariableName, domain);
                var innerFirstPol  = first;
                var innerSecondPol = second;
                if (innerSecondPol.Degree > innerFirstPol.Degree)
                {
                    var swap = innerFirstPol;
                    innerFirstPol  = innerSecondPol;
                    innerSecondPol = swap;
                }

                if (!pseudoDomain.IsAdditiveUnity(innerSecondPol))
                {
                    var firstLeadingCoeff = innerFirstPol.GetLeadingCoefficient(pseudoDomain.CoeffsDomain);
                    var tempDegree        = innerFirstPol.Degree - innerSecondPol.Degree;
                    var temp = innerSecondPol;

                    innerSecondPol = pseudoDomain.Rem(innerFirstPol, innerSecondPol);
                    innerSecondPol = innerSecondPol.ApplyQuo(
                        firstLeadingCoeff,
                        pseudoDomain.CoeffsDomain);
                    if (tempDegree % 2 == 0)
                    {
                        innerSecondPol = innerSecondPol.GetSymmetric(pseudoDomain.CoeffsDomain);
                    }

                    innerFirstPol = temp;

                    // Ciclo relativo à determinação do primeiro valor de c
                    if (!pseudoDomain.IsAdditiveUnity(innerSecondPol))
                    {
                        firstLeadingCoeff = innerFirstPol.GetLeadingCoefficient(pseudoDomain.CoeffsDomain);
                        var c = MathFunctions.Power(firstLeadingCoeff, tempDegree, pseudoDomain.CoeffsDomain);

                        tempDegree = innerFirstPol.Degree - innerSecondPol.Degree;
                        temp       = innerSecondPol;

                        innerSecondPol = pseudoDomain.Rem(innerFirstPol, innerSecondPol);
                        var den = MathFunctions.Power(c, tempDegree, pseudoDomain.CoeffsDomain);
                        innerSecondPol = innerSecondPol.ApplyQuo(
                            pseudoDomain.CoeffsDomain.Multiply(firstLeadingCoeff, den),
                            pseudoDomain.CoeffsDomain);
                        if (tempDegree % 2 == 0)
                        {
                            innerSecondPol = innerSecondPol.GetSymmetric(pseudoDomain.CoeffsDomain);
                        }

                        innerFirstPol = temp;

                        // Início do ciclo para obter a sequência de sub-resultantes
                        while (!pseudoDomain.IsAdditiveUnity(innerSecondPol))
                        {
                            firstLeadingCoeff = innerFirstPol.GetLeadingCoefficient(pseudoDomain.CoeffsDomain);
                            c = pseudoDomain.CoeffsDomain.Quo(
                                MathFunctions.Power(firstLeadingCoeff, tempDegree, pseudoDomain.CoeffsDomain),
                                MathFunctions.Power(c, tempDegree - 1, pseudoDomain.CoeffsDomain));

                            tempDegree = innerFirstPol.Degree - innerSecondPol.Degree;
                            temp       = innerSecondPol;

                            innerSecondPol = pseudoDomain.Rem(innerFirstPol, innerSecondPol);
                            den            = MathFunctions.Power(c, tempDegree, pseudoDomain.CoeffsDomain);
                            innerSecondPol = innerSecondPol.ApplyQuo(
                                pseudoDomain.CoeffsDomain.Multiply(firstLeadingCoeff, den),
                                pseudoDomain.CoeffsDomain);
                            if (tempDegree % 2 == 0)
                            {
                                innerSecondPol = innerSecondPol.GetSymmetric(pseudoDomain.CoeffsDomain);
                            }

                            innerFirstPol = temp;
                        }
                    }
                }

                return(innerFirstPol);
            }
        }
Ejemplo n.º 7
0
        /// <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));
                }
            }
        }
Ejemplo n.º 8
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);
                }
            }
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Determina a potência do polinómio.
        /// </summary>
        /// <param name="left">O polinómio.</param>
        /// <param name="right">O expoente.</param>
        /// <returns>O resultado da potência.</returns>
        /// <exception cref="MathematicsException">Se a operação falhar por vários motivos.</exception>
        protected virtual ParsePolynomialItem <T> Power(ParsePolynomialItem <T> left, ParsePolynomialItem <T> right)
        {
            var result = new ParsePolynomialItem <T>();

            if (left.ValueType == EParsePolynomialValueType.COEFFICIENT)
            {
                if (right.ValueType == EParsePolynomialValueType.COEFFICIENT)
                {
                    var degree = this.conversion.DirectConversion(right.Coeff);
                    result.Coeff = MathFunctions.Power(left.Coeff, degree, this.ring);
                }
                else if (right.ValueType == EParsePolynomialValueType.INTEGER)
                {
                    result.Coeff = MathFunctions.Power(left.Coeff, right.Degree, this.ring);
                }
                else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL)
                {
                    if (right.Polynomial.IsValue)
                    {
                        var exponent = this.conversion.DirectConversion(right.Polynomial.GetAsValue(this.ring));
                        result.Coeff = MathFunctions.Power(left.Coeff, exponent, this.ring);
                    }
                    else
                    {
                        throw new MathematicsException("Polynomial exponents aren't allowed.");
                    }
                }
            }
            else if (left.ValueType == EParsePolynomialValueType.INTEGER)
            {
                if (right.ValueType == EParsePolynomialValueType.COEFFICIENT)
                {
                    var rightConversion = this.conversion.DirectConversion(right.Coeff);
                    result.Degree = MathFunctions.Power(left.Degree, rightConversion, this.integerRing);
                }
                else if (right.ValueType == EParsePolynomialValueType.INTEGER)
                {
                    result.Degree = MathFunctions.Power(left.Degree, right.Degree, this.integerRing);
                }
                else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL)
                {
                    if (right.Polynomial.IsValue)
                    {
                        var exponent = this.conversion.DirectConversion(right.Polynomial.GetAsValue(this.ring));
                        result.Degree = MathFunctions.Power(left.Degree, exponent, this.integerRing);
                    }
                    else
                    {
                        throw new MathematicsException("Polynomial exponents aren't allowed.");
                    }
                }
            }
            else if (left.ValueType == EParsePolynomialValueType.POLYNOMIAL)
            {
                if (right.ValueType == EParsePolynomialValueType.COEFFICIENT)
                {
                    var exponent = this.conversion.DirectConversion(right.Coeff);
                    result.Polynomial = left.Polynomial.Power(exponent, this.ring);
                }
                else if (right.ValueType == EParsePolynomialValueType.INTEGER)
                {
                    result.Polynomial = left.Polynomial.Power(right.Degree, this.ring);
                }
                else if (right.ValueType == EParsePolynomialValueType.POLYNOMIAL)
                {
                    if (right.Polynomial.IsValue)
                    {
                        var exponent = this.conversion.DirectConversion(right.Polynomial.GetAsValue(this.ring));
                        result.Polynomial = left.Polynomial.Power(exponent, this.ring);
                    }
                    else
                    {
                        throw new MathematicsException("Polynomial exponents aren't allowed.");
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Executa o algoritmo que permite obter uma factorização livre de quadrados.
        /// </summary>
        /// <param name="polynomial">O polinómio de entrada.</param>
        /// <returns>A factorização livre de quadrados.</returns>
        /// <exception cref="ArgumentNullException">
        /// Se o argumento for nulo.
        /// </exception>
        public SquareFreeFactorizationResult <Fraction <CoeffType>, CoeffType> Run(
            UnivariatePolynomialNormalForm <Fraction <CoeffType> > polynomial)
        {
            if (polynomial == null)
            {
                throw new ArgumentNullException("polynomial");
            }
            else
            {
                var independentCoeff = this.fractionField.MultiplicativeUnity;
                var result           = new Dictionary <int, UnivariatePolynomialNormalForm <CoeffType> >();
                var currentDegree    = 1;
                var polynomDomain    = new UnivarPolynomEuclideanDomain <Fraction <CoeffType> >(
                    polynomial.VariableName,
                    this.fractionField);

                var lagAlg         = new LagrangeAlgorithm <CoeffType>(this.integerNumber);
                var dataDerivative = polynomial.GetPolynomialDerivative(this.fractionField);
                var gcd            = this.GreatCommonDivisor(polynomial, dataDerivative, polynomDomain);
                if (gcd.Degree == 0)
                {
                    var lcm = this.GetDenominatorLcm(polynomial, lagAlg);
                    if (this.integerNumber.IsMultiplicativeUnity(lcm))
                    {
                        var integerPol = this.GetIntegerPol(polynomial);
                        result.Add(currentDegree, integerPol);
                    }
                    else
                    {
                        independentCoeff = new Fraction <CoeffType>(
                            this.integerNumber.MultiplicativeUnity,
                            lcm,
                            this.integerNumber);
                        var multipliable = new Fraction <CoeffType>(
                            lcm,
                            this.integerNumber.MultiplicativeUnity,
                            this.integerNumber);
                        var multipliedPol = polynomial.Multiply(independentCoeff, this.fractionField);
                        var integerPol    = this.GetIntegerPol(multipliedPol);
                        result.Add(currentDegree, integerPol);
                    }
                }
                else
                {
                    var polyCoffactor    = polynomDomain.Quo(polynomial, gcd);
                    var nextGcd          = this.GreatCommonDivisor(gcd, polyCoffactor, polynomDomain);
                    var squareFreeFactor = polynomDomain.Quo(polyCoffactor, nextGcd);
                    polyCoffactor = gcd;
                    gcd           = nextGcd;
                    if (squareFreeFactor.Degree > 0)
                    {
                        var lcm = this.GetDenominatorLcm(squareFreeFactor, lagAlg);
                        if (this.integerNumber.IsMultiplicativeUnity(lcm))
                        {
                            var integerPol = this.GetIntegerPol(squareFreeFactor);
                            result.Add(currentDegree, integerPol);
                        }
                        else if (this.fractionField.IsAdditiveUnity(independentCoeff))
                        {
                            independentCoeff = new Fraction <CoeffType>(
                                this.integerNumber.MultiplicativeUnity,
                                MathFunctions.Power(lcm, currentDegree, this.integerNumber),
                                this.integerNumber);
                            var multipliable = new Fraction <CoeffType>(
                                lcm,
                                this.integerNumber.MultiplicativeUnity,
                                this.integerNumber);
                            var multipliedPol = squareFreeFactor.Multiply(independentCoeff, this.fractionField);
                            var integerPol    = this.GetIntegerPol(multipliedPol);
                            result.Add(currentDegree, integerPol);
                        }
                        else
                        {
                            var multiplicationCoeff = new Fraction <CoeffType>(
                                this.integerNumber.MultiplicativeUnity,
                                MathFunctions.Power(lcm, currentDegree, this.integerNumber),
                                this.integerNumber);
                            independentCoeff = this.fractionField.Multiply(independentCoeff, multiplicationCoeff);
                            var multipliable = new Fraction <CoeffType>(
                                lcm,
                                this.integerNumber.MultiplicativeUnity,
                                this.integerNumber);
                            var multipliedPol = squareFreeFactor.Multiply(independentCoeff, this.fractionField);
                            var integerPol    = this.GetIntegerPol(multipliedPol);
                            result.Add(currentDegree, integerPol);
                        }
                    }
                    else
                    {
                        var value = squareFreeFactor.GetAsValue(this.fractionField);
                        if (!this.fractionField.IsMultiplicativeUnity(value))
                        {
                            if (this.fractionField.IsMultiplicativeUnity(independentCoeff))
                            {
                                independentCoeff = value;
                            }
                            else
                            {
                                independentCoeff = this.fractionField.Multiply(independentCoeff, value);
                            }
                        }
                    }

                    ++currentDegree;
                    while (gcd.Degree > 0)
                    {
                        polyCoffactor    = polynomDomain.Quo(polyCoffactor, gcd);
                        nextGcd          = MathFunctions.GreatCommonDivisor(gcd, polyCoffactor, polynomDomain);
                        squareFreeFactor = polynomDomain.Quo(gcd, nextGcd);
                        gcd = nextGcd;
                        if (squareFreeFactor.Degree > 0)
                        {
                            var lcm = this.GetDenominatorLcm(squareFreeFactor, lagAlg);
                            if (this.integerNumber.IsMultiplicativeUnity(lcm))
                            {
                                var integerPol = this.GetIntegerPol(squareFreeFactor);
                                result.Add(currentDegree, integerPol);
                            }
                            else if (this.fractionField.IsAdditiveUnity(independentCoeff))
                            {
                                independentCoeff = new Fraction <CoeffType>(
                                    this.integerNumber.MultiplicativeUnity,
                                    MathFunctions.Power(lcm, currentDegree, this.integerNumber),
                                    this.integerNumber);
                                var multipliable = new Fraction <CoeffType>(
                                    lcm,
                                    this.integerNumber.MultiplicativeUnity,
                                    this.integerNumber);
                                var multipliedPol = squareFreeFactor.Multiply(independentCoeff, this.fractionField);
                                var integerPol    = this.GetIntegerPol(multipliedPol);
                                result.Add(currentDegree, integerPol);
                            }
                            else
                            {
                                var multiplicationCoeff = new Fraction <CoeffType>(
                                    this.integerNumber.MultiplicativeUnity,
                                    MathFunctions.Power(lcm, currentDegree, this.integerNumber),
                                    this.integerNumber);
                                independentCoeff = this.fractionField.Multiply(independentCoeff, multiplicationCoeff);
                                var multipliable = new Fraction <CoeffType>(
                                    lcm,
                                    this.integerNumber.MultiplicativeUnity,
                                    this.integerNumber);
                                var multipliedPol = squareFreeFactor.Multiply(multipliable, this.fractionField);
                                var integerPol    = this.GetIntegerPol(multipliedPol);
                                result.Add(currentDegree, integerPol);
                            }
                        }
                        else
                        {
                            var value = squareFreeFactor.GetAsValue(this.fractionField);
                            if (!this.fractionField.IsMultiplicativeUnity(value))
                            {
                                if (this.fractionField.IsMultiplicativeUnity(independentCoeff))
                                {
                                    independentCoeff = value;
                                }
                                else
                                {
                                    independentCoeff = this.fractionField.Multiply(independentCoeff, value);
                                }
                            }
                        }

                        ++currentDegree;
                    }

                    var cofactorValue = polyCoffactor.GetAsValue(this.fractionField);
                    if (!this.fractionField.IsMultiplicativeUnity(cofactorValue))
                    {
                        if (this.fractionField.IsMultiplicativeUnity(independentCoeff))
                        {
                            independentCoeff = cofactorValue;
                        }
                        else
                        {
                            independentCoeff = this.fractionField.Multiply(independentCoeff, cofactorValue);
                        }
                    }
                }

                return(new SquareFreeFactorizationResult <Fraction <CoeffType>, CoeffType>(
                           independentCoeff,
                           result));
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Obtém os valores da solução.
        /// </summary>
        /// <param name="solution">A solução do sistema modular.</param>
        /// <param name="matrixList">A matriz.</param>
        /// <param name="primesList">A lista dos números primos da base.</param>
        /// <param name="innerData">O número que está a ser factorizado.</param>
        /// <returns>Os factores.</returns>
        private Tuple <NumberType, NumberType> GetSolution(
            LinearSystemSolution <int> solution,
            List <int[]> matrixList,
            List <int> primesList,
            NumberType innerData)
        {
            var innerDataModularField = this.modularFieldFactory.CreateInstance(innerData);
            var countFactors          = primesList.Count - 1;

            foreach (var solutionBase in solution.VectorSpaceBasis)
            {
                var firstValue   = this.integerNumber.MultiplicativeUnity;
                var factorsCount = new Dictionary <int, int>();
                for (int i = 0; i < matrixList.Count; ++i)
                {
                    var currentMatrixLine = matrixList[i];
                    if (solutionBase[i] == 1)
                    {
                        firstValue = innerDataModularField.Multiply(
                            firstValue,
                            this.integerNumber.GetNorm(this.integerNumber.MapFrom(currentMatrixLine[currentMatrixLine.Length - 1])));

                        for (int j = 0; j < countFactors; ++j)
                        {
                            if (currentMatrixLine[j] != 0)
                            {
                                var countValue = 0;
                                if (factorsCount.TryGetValue(primesList[j], out countValue))
                                {
                                    countValue += currentMatrixLine[j];
                                    factorsCount[primesList[j]] = countValue;
                                }
                                else
                                {
                                    factorsCount.Add(primesList[j], currentMatrixLine[j]);
                                }
                            }
                        }
                    }
                }

                var secondValue = this.integerNumber.MultiplicativeUnity;
                foreach (var factorCountKvp in factorsCount)
                {
                    var primePower = MathFunctions.Power(
                        this.integerNumber.MapFrom(factorCountKvp.Key),
                        factorCountKvp.Value / 2,
                        innerDataModularField);

                    secondValue = innerDataModularField.Multiply(
                        secondValue,
                        primePower);
                }

                if (!this.integerNumber.Equals(firstValue, secondValue))
                {
                    var firstFactor = MathFunctions.GreatCommonDivisor(
                        innerData,
                        this.integerNumber.GetNorm(this.integerNumber.Add(firstValue, this.integerNumber.AdditiveInverse(secondValue))),
                        this.integerNumber);
                    if (!this.integerNumber.IsMultiplicativeUnity(firstFactor))
                    {
                        var secondFactor = this.integerNumber.Quo(innerData, firstFactor);
                        return(Tuple.Create(firstFactor, secondFactor));
                    }
                }
            }

            return(Tuple.Create(this.integerNumber.MultiplicativeUnity, innerData));
        }
Ejemplo n.º 13
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))
                    });
                }
            }
        }
        /// <summary>
        /// Determina o corte de um número sobre as potências de um número primo.
        /// </summary>
        /// <param name="value">O valor do qual se pretende obter o corte.</param>
        /// <param name="prime">O número primo.</param>
        /// <param name="firstExponent">O expoente inferior do corte.</param>
        /// <param name="secondExponent">O expoente superior do corte.</param>
        /// <returns>O resultado do corte.</returns>
        private CoeffType ComputeTwoSidedCut(
            CoeffType value,
            CoeffType prime,
            CoeffType firstExponent,
            CoeffType secondExponent)
        {
            var difference = this.integerNumber.Add(
                secondExponent,
                this.integerNumber.AdditiveInverse(firstExponent));

            if (this.integerNumber.Compare(firstExponent, difference) < 0)
            {
                // Cálculo da primeira potência.
                var firstExponentFactor = MathFunctions.Power(
                    prime,
                    firstExponent,
                    this.integerNumber,
                    this.integerNumber);

                // Cálculo da segunda potência com base na primeira.
                var increment = this.integerNumber.Add(
                    firstExponent,
                    this.integerNumber.AdditiveInverse(difference));
                var differenceExponentFactor = MathFunctions.Power(
                    prime,
                    increment,
                    this.integerNumber,
                    this.integerNumber);
                differenceExponentFactor = this.integerNumber.Multiply(
                    differenceExponentFactor,
                    firstExponentFactor);

                var result = this.integerNumber.Rem(value, firstExponentFactor);
                result = this.integerNumber.Add(
                    value,
                    this.integerNumber.AdditiveInverse(result));
                result = this.integerNumber.Quo(result, firstExponentFactor);
                result = this.integerNumber.Rem(result, differenceExponentFactor);
                return(result);
            }
            else
            {
                // Cálculo da primeira potência.
                var differenceExponentFactor = MathFunctions.Power(
                    prime,
                    difference,
                    this.integerNumber,
                    this.integerNumber);

                // Cálculo da segunda potência com base na primeira.
                var increment = this.integerNumber.Add(
                    difference,
                    this.integerNumber.AdditiveInverse(firstExponent));
                var firstExponentFactor = MathFunctions.Power(
                    prime,
                    increment,
                    this.integerNumber,
                    this.integerNumber);
                firstExponentFactor = this.integerNumber.Multiply(
                    firstExponentFactor,
                    firstExponentFactor);

                var result = this.integerNumber.Rem(value, firstExponentFactor);
                result = this.integerNumber.Add(
                    value,
                    this.integerNumber.AdditiveInverse(result));
                result = this.integerNumber.Quo(result, firstExponentFactor);
                result = this.integerNumber.Rem(result, differenceExponentFactor);
                return(result);
            }
        }
        /// <summary>
        /// Permite calcular a aproximação de Mignotte relativamente à factorização de polinómios.
        /// </summary>
        /// <remarks>
        /// A aproximaçáo calculada consiste num limite superior para os coeficientes de um polinómio
        /// módulo a potência de um número primo caso este seja factor do polinómio proposto.
        /// </remarks>
        /// <param name="polynomialNorm">A norma do polinómio.</param>
        /// <param name="leadingCoeff">O coeficiente principal do polinómio.</param>
        /// <param name="degree">O grau do polinómio.</param>
        /// <returns>O valor da aproximação.</returns>
        private CoeffType ComputeMignotteApproximation(
            CoeffType polynomialNorm,
            CoeffType leadingCoeff,
            int degree)
        {
            var result = MathFunctions.Power(this.integerNumber.MapFrom(2), degree, this.integerNumber);

            result = this.integerNumber.Multiply(result, leadingCoeff);
            result = this.integerNumber.Multiply(result, polynomialNorm);

            // Utilização da expansão em série para a determinação do valor inteiro da raiz quadrada.
            // a_1=1, b_1=2, a_{n+1}=-(2n+1)a_n, b_{n+1}=2(n+1)b_n
            var integerSquareRoot = this.integerNumber.MapFrom(this.integerSquareRootAlgorithm.Run(degree + 1));
            var difference        = this.integerNumber.Multiply(integerSquareRoot, integerSquareRoot);
            var squared           = this.integerNumber.Multiply(integerSquareRoot, integerSquareRoot);

            difference = this.integerNumber.Add(
                this.integerNumber.MapFrom(degree + 1),
                this.integerNumber.AdditiveInverse(squared));
            if (this.integerNumber.IsAdditiveUnity(difference))
            {
                result = this.integerNumber.Multiply(result, integerSquareRoot);
            }
            else
            {
                var db               = this.integerNumber.MapFrom(2);
                var numMult          = this.integerNumber.MultiplicativeUnity;
                var denMult          = this.integerNumber.MultiplicativeUnity;
                var sign             = true;
                var numeratorCoeff   = this.integerNumber.Multiply(result, difference);
                var denominatorCoeff = db;
                denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, integerSquareRoot);
                var gcd = MathFunctions.GreatCommonDivisor(numeratorCoeff, denominatorCoeff, this.integerNumber);
                if (!this.integerNumber.IsMultiplicativeUnity(gcd))
                {
                    numeratorCoeff   = this.integerNumber.Quo(numeratorCoeff, gcd);
                    denominatorCoeff = this.integerNumber.Quo(denominatorCoeff, gcd);
                }

                result = this.integerNumber.Multiply(result, integerSquareRoot);
                if (this.integerNumber.Compare(numeratorCoeff, denominatorCoeff) > 0)
                {
                    // Adicionar a primeira parcela da expansão em série.
                    var divide = this.integerNumber.Quo(numeratorCoeff, denominatorCoeff);
                    if (!sign)
                    {
                        divide = this.integerNumber.AdditiveInverse(divide);
                    }

                    result = this.integerNumber.Add(result, divide);

                    // Actualiza com a nova informação.
                    sign             = !sign;
                    denMult          = this.integerNumber.Successor(denMult);
                    numeratorCoeff   = this.integerNumber.Multiply(numeratorCoeff, difference);
                    numeratorCoeff   = this.integerNumber.Multiply(numeratorCoeff, numMult);
                    denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, denMult);
                    denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, squared);
                    denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, db);
                    gcd = MathFunctions.GreatCommonDivisor(numeratorCoeff, denominatorCoeff, this.integerNumber);
                    if (!this.integerNumber.IsMultiplicativeUnity(gcd))
                    {
                        numeratorCoeff   = this.integerNumber.Quo(numeratorCoeff, gcd);
                        denominatorCoeff = this.integerNumber.Quo(denominatorCoeff, gcd);
                    }

                    while (this.integerNumber.Compare(numeratorCoeff, denominatorCoeff) > 0)
                    {
                        // Adicionar a primeira parcela da expansão em série.
                        divide = this.integerNumber.Quo(numeratorCoeff, denominatorCoeff);
                        if (!sign)
                        {
                            divide = this.integerNumber.AdditiveInverse(divide);
                        }

                        result = this.integerNumber.Add(result, divide);

                        // Actualiza com a nova informação.
                        sign             = !sign;
                        numMult          = this.integerNumber.Successor(this.integerNumber.Successor(numMult));
                        denMult          = this.integerNumber.Successor(denMult);
                        numeratorCoeff   = this.integerNumber.Multiply(numeratorCoeff, difference);
                        numeratorCoeff   = this.integerNumber.Multiply(numeratorCoeff, numMult);
                        denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, denMult);
                        denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, squared);
                        denominatorCoeff = this.integerNumber.Multiply(denominatorCoeff, db);
                        this.integerNumber.Multiply(denominatorCoeff, db);
                        gcd = MathFunctions.GreatCommonDivisor(numeratorCoeff, denominatorCoeff, this.integerNumber);
                        if (!this.integerNumber.IsMultiplicativeUnity(gcd))
                        {
                            numeratorCoeff   = this.integerNumber.Quo(numeratorCoeff, gcd);
                            denominatorCoeff = this.integerNumber.Quo(denominatorCoeff, gcd);
                        }
                    }
                }

                if (sign)
                {
                    result = this.integerNumber.Successor(result);
                }
            }

            return(result);
        }
        /// <summary>
        /// Permite determinar a factorização racional de um polinómio.
        /// </summary>
        /// <param name="polynomial">O polinómio.</param>
        /// <returns>O resultado da factorização.</returns>
        public PolynomialFactorizationResult <Fraction <CoeffType>, CoeffType> Run(
            UnivariatePolynomialNormalForm <Fraction <CoeffType> > polynomial)
        {
            if (polynomial == null)
            {
                throw new ArgumentNullException("polynomial");
            }
            else
            {
                var squareFreeResult        = this.squareFreeAlg.Run(polynomial);
                var independentCoeff        = squareFreeResult.IndependentCoeff;
                var factorizationDictionary =
                    new Dictionary <int, List <UnivariatePolynomialNormalForm <CoeffType> > >();
                foreach (var squareFreeFactorKvp in squareFreeResult.Factors)
                {
                    if (squareFreeFactorKvp.Value.Degree == 1)
                    {
                        factorizationDictionary.Add(
                            squareFreeFactorKvp.Key,
                            new List <UnivariatePolynomialNormalForm <CoeffType> >()
                        {
                            squareFreeFactorKvp.Value
                        });
                    }
                    else
                    {
                        var currentPolynomial      = squareFreeFactorKvp.Value;
                        var polynomialLeadingCoeff = currentPolynomial.GetLeadingCoefficient(this.integerNumber);
                        var polynomialNorm         = this.GetPolynomialNorm(currentPolynomial);
                        var bound = this.ComputeMignotteApproximation(
                            polynomialNorm,
                            polynomialLeadingCoeff,
                            polynomial.Degree);

                        var primeNumbersBound    = this.ComputeGamma(polynomialNorm, polynomial.Degree);
                        var primeNumbersIterator = this.primeNumbersIteratorFactory.CreatePrimeNumberIterator(
                            primeNumbersBound);
                        var primeNumbersEnumerator = primeNumbersIterator.GetEnumerator();
                        var discriminant           = this.resultantAlg.Run(
                            currentPolynomial,
                            currentPolynomial.GetPolynomialDerivative(this.integerNumber));
                        var currentPrime = this.integerNumber.MultiplicativeUnity;
                        var status       = 0;
                        while (status == 0)
                        {
                            if (primeNumbersEnumerator.MoveNext())
                            {
                                currentPrime = primeNumbersEnumerator.Current;
                                if (!this.integerNumber.IsAdditiveUnity(
                                        this.integerNumber.Rem(polynomialLeadingCoeff, currentPrime)) &&
                                    !this.integerNumber.IsAdditiveUnity(this.integerNumber.Rem(
                                                                            discriminant,
                                                                            currentPrime)))
                                {
                                    status = 1;
                                }
                            }
                            else
                            {
                                status = -1;
                            }
                        }

                        if (status == 1) // Encontrou um número primo sobre o qual é possível proceder à elevação.
                        {
                            var factorList       = new List <UnivariatePolynomialNormalForm <CoeffType> >();
                            var iterationsNumber = this.GetHenselLiftingIterationsNumber(bound, currentPrime);
                            var coeff            = this.FactorizePolynomial(
                                currentPolynomial,
                                currentPrime,
                                bound,
                                iterationsNumber,
                                factorList);

                            var multiplicationCoeff = this.fractionField.InverseConversion(coeff);
                            multiplicationCoeff = MathFunctions.Power(
                                multiplicationCoeff,
                                squareFreeFactorKvp.Key,
                                this.fractionField);

                            independentCoeff = this.fractionField.Multiply(independentCoeff, multiplicationCoeff);
                            factorizationDictionary.Add(
                                squareFreeFactorKvp.Key,
                                factorList);
                        }
                        else
                        {
                            factorizationDictionary.Add(
                                squareFreeFactorKvp.Key,
                                new List <UnivariatePolynomialNormalForm <CoeffType> >()
                            {
                                squareFreeFactorKvp.Value
                            });
                        }
                    }
                }

                return(new PolynomialFactorizationResult <Fraction <CoeffType>, CoeffType>(
                           independentCoeff,
                           factorizationDictionary));
            }
        }