/// <summary> /// Determina o produto de todos os factores modulares. /// </summary> /// <param name="modularFactors">Os factores modulares.</param> /// <param name="modularDomain">O domínio modular.</param> /// <returns>O resultado do produto dos factores modulares.</returns> private UnivariatePolynomialNormalForm <CoeffType> ComputeModularProduct( List <UnivariatePolynomialNormalForm <CoeffType> > modularFactors, UnivarPolynomEuclideanDomain <CoeffType> modularDomain) { if (modularFactors.Count > 0) { var result = modularFactors[0]; for (int i = 1; i < modularFactors.Count; ++i) { result = modularDomain.Multiply(result, modularFactors[i]); } return(result); } else { return(modularDomain.MultiplicativeUnity); } }
/// <summary> /// Permite processar as restantes combinações. /// </summary> /// <param name="modularFactors">Os factores modulares.</param> /// <param name="integerFactors">Os factores inteiros.</param> /// <param name="primePower">A potência de um número primo que servirá de módulo.</param> /// <param name="halfPrimePower">A metade da potência do número primo.</param> /// <param name="testValue">O valor de teste.</param> /// <param name="combinationsNumber">O número máximo de polinómios nas combinações.</param> /// <param name="modularPolynomialDomain">O corpo responsável pelas operações modulares.</param> private void ProcessRemainingPolynomials( List <UnivariatePolynomialNormalForm <CoeffType> > modularFactors, List <UnivariatePolynomialNormalForm <CoeffType> > integerFactors, CoeffType primePower, CoeffType halfPrimePower, CoeffType testValue, int combinationsNumber, UnivarPolynomEuclideanDomain <CoeffType> modularPolynomialDomain) { if (combinationsNumber > 1 && modularFactors.Count > 1) { var modularProduct = default(UnivariatePolynomialNormalForm <CoeffType>); var currentCombinationNumber = 2; var productStack = new Stack <UnivariatePolynomialNormalForm <CoeffType> >(); productStack.Push(modularFactors[0]); var pointers = new Stack <int>(); pointers.Push(0); pointers.Push(1); var state = 0; while (state != -1) { if (state == 0) { if (pointers.Count == currentCombinationNumber) { var topPointer = pointers.Pop(); var topPol = productStack.Pop(); // Obtém o produto de todos os polinómios. var currentPol = modularPolynomialDomain.Multiply( topPol, modularFactors[topPointer]); currentPol = currentPol.ApplyFunction( c => this.GetSymmetricRemainder( c, primePower, halfPrimePower), this.integerNumber); // Compara as normas com o valor de teste var firstNorm = this.GetPlynomialNorm(currentPol); if (this.integerNumber.Compare(firstNorm, testValue) < 0) { if (modularProduct == null) { modularProduct = this.ComputeModularProduct( modularFactors, modularPolynomialDomain); } var coPol = modularPolynomialDomain.Quo( modularProduct, currentPol); coPol = coPol.ApplyFunction( c => this.GetSymmetricRemainder( c, primePower, halfPrimePower), this.integerNumber); var secondNorm = this.GetPlynomialNorm(coPol); var normProd = this.integerNumber.Multiply(firstNorm, secondNorm); if (this.integerNumber.Compare(normProd, testValue) < 0) { integerFactors.Add(currentPol); modularFactors.RemoveAt(topPointer); while (pointers.Count > 0) { var removeIndex = pointers.Pop(); modularFactors.RemoveAt(removeIndex); } productStack.Clear(); if (modularFactors.Count < currentCombinationNumber) { state = -1; } else { productStack.Push(modularFactors[0]); pointers.Push(0); pointers.Push(1); } } else { productStack.Push(topPol); pointers.Push(topPointer); state = 1; } } else { productStack.Push(topPol); pointers.Push(topPointer); state = 1; } } else { var topPointer = pointers.Pop(); var topPol = productStack.Pop(); var currentPol = modularPolynomialDomain.Multiply( topPol, modularFactors[topPointer]); currentPol = currentPol.ApplyFunction( c => this.GetSymmetricRemainder( c, primePower, halfPrimePower), this.integerNumber); productStack.Push(topPol); productStack.Push(currentPol); pointers.Push(topPointer); pointers.Push(topPointer + 1); } } else if (state == 1) { var pointerLimit = modularFactors.Count - combinationsNumber + pointers.Count + 1; if (pointers.Count > 1) { var topPointer = pointers.Pop(); ++topPointer; if (topPointer < pointerLimit) { pointers.Push(topPointer); state = 0; } else { productStack.Pop(); } } else { var topPointer = pointers.Pop(); ++topPointer; if (topPointer < pointerLimit) { pointers.Push(topPointer); productStack.Push(modularFactors[topPointer]); pointers.Push(topPointer + 1); } else { ++currentCombinationNumber; if (currentCombinationNumber < combinationsNumber) { state = -1; } else if (modularFactors.Count < currentCombinationNumber) { state = -1; } else { pointers.Push(0); pointers.Push(1); productStack.Push(modularFactors[0]); } } } } } } }