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