/// <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)); } } }
/// <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); }
/// <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); } } }
/// <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)) }); } } }