Esempio n. 1
0
        /// <summary>
        /// Reduz a fracção à forma canónica.
        /// </summary>
        /// <param name="domain">O domínio sobre o qual se processa a redução.</param>
        private void Reduce(IEuclidenDomain <T> domain)
        {
            T gcd = MathFunctions.GreatCommonDivisor(this.numerator, this.denominator, domain);

            this.numerator   = domain.Quo(this.numerator, gcd);
            this.denominator = domain.Quo(this.denominator, gcd);
        }
Esempio n. 2
0
 /// <summary>
 /// Obtém o resultado da diferença entre a fracção corrente e a fracção especificada.
 /// </summary>
 /// <param name="right">A fracção especificada.</param>
 /// <param name="domain">O domínio responsável pelas operações sobre os coeficientes.</param>
 /// <returns>O resultado da subtracção.</returns>
 /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
 public Fraction <T> Subtract(Fraction <T> right, IEuclidenDomain <T> domain)
 {
     if (domain == null)
     {
         throw new ArgumentNullException("domain");
     }
     else if (right == null)
     {
         throw new ArgumentNullException("right");
     }
     else
     {
         var gcd = MathFunctions.GreatCommonDivisor(this.denominator, right.denominator, domain);
         var currentReducedDenominator = domain.Quo(this.denominator, gcd);
         var rightReducedDenominator   = domain.Quo(right.denominator, gcd);
         var resultDenominator         = domain.Multiply(currentReducedDenominator, right.denominator);
         var currentAddNumerator       = domain.Multiply(this.numerator, rightReducedDenominator);
         var rightAddNumerator         = domain.Multiply(right.numerator, currentReducedDenominator);
         rightAddNumerator = domain.Multiply(
             domain.AdditiveInverse(domain.MultiplicativeUnity),
             rightAddNumerator);
         var resultNumerator = domain.Add(currentAddNumerator, rightAddNumerator);
         return(new Fraction <T>(resultNumerator, resultDenominator, domain));
     }
 }
Esempio n. 3
0
        /// <summary>
        /// Obtém o quociente da fracção corrente com um coeficiente independente.
        /// </summary>
        /// <param name="coeff">O coeficiente.</param>
        /// <param name="domain">O domínio responsável pelas operações sobre os coeficientes.</param>
        /// <returns>O resultado do quociente.</returns>
        /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
        public Fraction <T> Divide(T coeff, IEuclidenDomain <T> domain)
        {
            if (domain == null)
            {
                throw new ArgumentNullException("domain");
            }
            else if (coeff == null)
            {
                throw new ArgumentNullException("coeff");
            }
            else if (domain.IsAdditiveUnity(coeff))
            {
                throw new DivideByZeroException();
            }
            else if (domain.IsAdditiveUnity(this.numerator))
            {
                var result = new Fraction <T>(domain);
                result.numerator   = domain.AdditiveUnity;
                result.denominator = domain.MultiplicativeUnity;
                return(result);
            }
            else
            {
                var crossGcd        = MathFunctions.GreatCommonDivisor(this.numerator, coeff, domain);
                var secondNumerator = domain.Quo(coeff, crossGcd);
                var firstNumerator  = domain.Quo(this.numerator, crossGcd);

                var resultDenominator = domain.Multiply(this.denominator, secondNumerator);

                var result = new Fraction <T>(domain);
                result.numerator   = firstNumerator;
                result.denominator = resultDenominator;
                return(result);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Obtém a decomposição do módulo do número especificado num produto de factores.
        /// </summary>
        /// <remarks>
        /// A decomposição poderá consistir no produto do número especificado pela unidade. Neste caso,
        /// não é garantida a primalidade do número. Normalmente, é escolhido outro polinómio como gerador da
        /// sequência pseudo-aleatória.
        /// </remarks>
        /// <param name="number">O número especificado.</param>
        /// <returns>A decomposição do produto.</returns>
        /// <exception cref="MathematicsException">Se o número for zero.</exception>
        public Tuple <NumberType, NumberType> Run(NumberType number)
        {
            var innerNumber = this.integerNumber.GetNorm(number);

            if (this.integerNumber.IsAdditiveUnity(innerNumber))
            {
                throw new MathematicsException("Zero has no factors.");
            }
            else if (this.integerNumber.IsMultiplicativeUnity(innerNumber))
            {
                return(Tuple.Create(
                           this.integerNumber.MultiplicativeUnity,
                           this.integerNumber.MultiplicativeUnity));
            }
            else
            {
                var modularRing     = this.modularFieldFactory.CreateInstance(number);
                var innerStartValue = modularRing.GetReduced(this.startValue);

                foreach (var polynomial in this.polynomialsList)
                {
                    var firstSequenceValue  = modularRing.GetReduced(this.startValue);
                    var secondSequenceValue = modularRing.GetReduced(this.startValue);
                    var gcd = this.integerNumber.MultiplicativeUnity;
                    do
                    {
                        firstSequenceValue = polynomial.Replace(firstSequenceValue, modularRing);
                        var secondSequenceTemp = polynomial.Replace(secondSequenceValue, modularRing);
                        secondSequenceValue = polynomial.Replace(secondSequenceTemp, modularRing);
                        if (this.integerNumber.Equals(firstSequenceValue, secondSequenceValue))
                        {
                            gcd = this.integerNumber.AdditiveUnity;
                        }
                        else
                        {
                            gcd = MathFunctions.GreatCommonDivisor(
                                innerNumber,
                                this.integerNumber.GetNorm(
                                    this.integerNumber.Add(
                                        firstSequenceValue,
                                        this.integerNumber.AdditiveInverse(secondSequenceValue))),
                                this.integerNumber);
                        }
                    } while (this.integerNumber.IsMultiplicativeUnity(gcd));

                    if (!this.integerNumber.IsAdditiveUnity(gcd))
                    {
                        return(Tuple.Create(gcd, this.integerNumber.Quo(innerNumber, gcd)));
                    }
                }

                return(Tuple.Create(innerNumber, this.integerNumber.MultiplicativeUnity));
            }
        }
        /// <summary>
        /// Calcula o máximo divisor comum entre dois polinómios.
        /// </summary>
        /// <param name="first">O primeiro polinómio.</param>
        /// <param name="second">O segundo polinómio.</param>
        /// <param name="polynomDomain">O domínio responsável pelas operações sobre os polinómios.</param>
        /// <param name="field">O corpo responsável pelas operações sobre os coeficientes.</param>
        /// <returns>O máximo divisor comum.</returns>
        private UnivariatePolynomialNormalForm <CoeffType> GreatCommonDivisor(
            UnivariatePolynomialNormalForm <CoeffType> first,
            UnivariatePolynomialNormalForm <CoeffType> second,
            UnivarPolynomEuclideanDomain <CoeffType> polynomDomain,
            IField <CoeffType> field
            )
        {
            var result       = MathFunctions.GreatCommonDivisor(first, second, polynomDomain);
            var leadingCoeff = result.GetLeadingCoefficient(field);

            result = result.Multiply(field.MultiplicativeInverse(leadingCoeff), field);
            return(result);
        }
Esempio n. 6
0
        /// <summary>
        /// Obtém o resultado do produto da fracção corrente com a fracção especificada.
        /// </summary>
        /// <param name="right">A fracção especificada.</param>
        /// <param name="domain">O domínio responsável pelas operações sobre os coeficientes.</param>
        /// <returns>O resultado do produto.</returns>
        /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
        public Fraction <T> Multiply(Fraction <T> right, IEuclidenDomain <T> domain)
        {
            if (domain == null)
            {
                throw new ArgumentNullException("domain");
            }
            else if (right == null)
            {
                throw new ArgumentNullException("right");
            }
            else if (domain.IsAdditiveUnity(this.numerator))
            {
                var result = new Fraction <T>(domain);
                result.numerator   = domain.AdditiveUnity;
                result.denominator = domain.MultiplicativeUnity;
                return(result);
            }
            else if (domain.IsAdditiveUnity(right.numerator))
            {
                var result = new Fraction <T>(domain);
                result.numerator   = domain.AdditiveUnity;
                result.denominator = domain.MultiplicativeUnity;
                return(result);
            }
            else
            {
                var crossGcd          = MathFunctions.GreatCommonDivisor(this.numerator, right.denominator, domain);
                var firstNumerator    = domain.Quo(this.numerator, crossGcd);
                var secondDenominator = domain.Quo(right.denominator, crossGcd);
                crossGcd = MathFunctions.GreatCommonDivisor(this.denominator, right.numerator, domain);
                var secondNumerator  = domain.Quo(right.numerator, crossGcd);
                var firstDenominator = domain.Quo(this.denominator, crossGcd);

                var resultNumerator   = domain.Multiply(firstNumerator, secondNumerator);
                var resultDenominator = domain.Multiply(firstDenominator, secondDenominator);

                var result = new Fraction <T>(domain);
                result.numerator   = resultNumerator;
                result.denominator = resultDenominator;
                return(result);
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Obtém a decomposição do módulo do número especificado num produto de factores.
        /// </summary>
        /// <remarks>
        /// A decomposição poderá consistir no produto do número especificado pela unidade. Neste caso,
        /// não é garantida a primalidade do número. Normalmente, é escolhido outro polinómio como gerador da
        /// sequência pseudo-aleatória.
        /// </remarks>
        /// <param name="number">O número especificado.</param>
        /// <param name="block">
        /// A quantidade de factores bloqueados antes de se proceder à determinação do
        /// máximo divisor comum.
        /// </param>
        /// <returns>A decomposição do número em factores.</returns>
        /// <exception cref="ArgumentException">Se o número de blocos não for positivo.</exception>
        /// <exception cref="MathematicsException">Se o número proporcionado for zero.</exception>
        public Tuple <NumberType, NumberType> Run(NumberType number, NumberType block)
        {
            var innerNumber = this.integerNumber.GetNorm(number);

            if (this.integerNumber.Compare(block, this.integerNumber.AdditiveUnity) <= 0)
            {
                throw new ArgumentException("Blocks number must be a positive integer.");
            }
            else if (this.integerNumber.IsAdditiveUnity(innerNumber))
            {
                throw new MathematicsException("Zero has no factors.");
            }
            else if (this.integerNumber.IsMultiplicativeUnity(innerNumber))
            {
                return(Tuple.Create(
                           this.integerNumber.MultiplicativeUnity,
                           this.integerNumber.MultiplicativeUnity));
            }
            else
            {
                var modularRing     = this.modularFieldFactory.CreateInstance(innerNumber);
                var innerStartValue = modularRing.GetReduced(this.startValue);

                foreach (var polynomial in this.polynomialsList)
                {
                    var firstSequenceValue  = modularRing.GetReduced(this.startValue);
                    var secondSequenceValue = modularRing.GetReduced(this.startValue);
                    var gcd = this.integerNumber.MultiplicativeUnity;
                    do
                    {
                        var initialFirstSequence  = firstSequenceValue;
                        var initialSecondSequence = secondSequenceValue;
                        var blocksNumber          = this.integerNumber.AdditiveUnity;
                        var blockProduct          = this.integerNumber.MultiplicativeUnity;
                        while (this.integerNumber.Compare(blocksNumber, block) < 0 &&
                               !this.integerNumber.IsAdditiveUnity(blockProduct))
                        {
                            firstSequenceValue = polynomial.Replace(firstSequenceValue, modularRing);
                            var secondSequenceTemp = polynomial.Replace(secondSequenceValue, modularRing);
                            secondSequenceValue = polynomial.Replace(secondSequenceTemp, modularRing);
                            var temp = this.integerNumber.GetNorm(
                                this.integerNumber.Add(
                                    firstSequenceValue,
                                    this.integerNumber.AdditiveInverse(secondSequenceValue)));
                            blockProduct = modularRing.Multiply(blockProduct, temp);
                            blocksNumber = this.integerNumber.Successor(blocksNumber);
                        }

                        if (this.integerNumber.IsAdditiveUnity(blockProduct))
                        {
                            gcd = this.integerNumber.AdditiveUnity;
                        }
                        else
                        {
                            gcd = MathFunctions.GreatCommonDivisor(blockProduct, innerNumber, this.integerNumber);
                        }

                        if (this.integerNumber.IsAdditiveUnity(gcd))
                        {
                            gcd = this.integerNumber.MultiplicativeUnity;
                            while (!this.integerNumber.Equals(initialFirstSequence, firstSequenceValue) &&
                                   !this.integerNumber.Equals(initialSecondSequence, secondSequenceValue) &&
                                   this.integerNumber.IsMultiplicativeUnity(gcd))
                            {
                                initialFirstSequence = polynomial.Replace(initialFirstSequence, modularRing);
                                var secondSequenceTemp = polynomial.Replace(initialSecondSequence, modularRing);
                                initialSecondSequence = polynomial.Replace(secondSequenceTemp, modularRing);
                                if (this.integerNumber.Equals(initialFirstSequence, initialSecondSequence))
                                {
                                    gcd = this.integerNumber.AdditiveUnity;
                                }
                                else
                                {
                                    gcd = MathFunctions.GreatCommonDivisor(
                                        innerNumber,
                                        this.integerNumber.GetNorm(
                                            this.integerNumber.Add(
                                                firstSequenceValue,
                                                this.integerNumber.AdditiveInverse(secondSequenceValue))),
                                        this.integerNumber);
                                }
                            }
                        }
                    } while (this.integerNumber.IsAdditiveUnity(gcd));

                    if (!this.integerNumber.Equals(gcd, innerNumber) && !this.integerNumber.IsAdditiveUnity(gcd))
                    {
                        return(Tuple.Create(gcd, this.integerNumber.Quo(innerNumber, gcd)));
                    }
                }
            }

            return(Tuple.Create(innerNumber, this.integerNumber.MultiplicativeUnity));
        }
Esempio 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);
                }
            }
        }
        /// <summary>
        /// Multiplica um dos termos, dividindo o outro.
        /// </summary>
        /// <param name="main">O termo a ser multiplicado.</param>
        /// <param name="subsidiary">O termo a ser dividido.</param>
        /// <param name="factorValue">O valor a ser multiplicado.</param>
        private void MultiplyNumber(
            Dictionary <int, int> main,
            Dictionary <int, int> subsidiary,
            int factorValue)
        {
            var currentValue         = factorValue;
            var auxiliary            = new Dictionary <int, int>();
            var subsidiaryEnumerator = subsidiary.GetEnumerator();
            var state         = subsidiaryEnumerator.MoveNext();
            var currentKvp    = subsidiaryEnumerator.Current.Key;
            var currentDegree = subsidiaryEnumerator.Current.Value;

            while (state)
            {
                if (currentKvp == 0)
                {
                    currentKvp    = subsidiaryEnumerator.Current.Key;
                    currentDegree = subsidiaryEnumerator.Current.Value;
                }

                if (currentValue == 1)
                {
                    if (currentDegree != 0)
                    {
                        var degree = 0;
                        if (auxiliary.TryGetValue(currentKvp, out degree))
                        {
                            auxiliary[currentKvp] = degree + currentDegree;
                        }
                        else
                        {
                            auxiliary.Add(currentKvp, currentDegree);
                        }
                    }

                    state      = subsidiaryEnumerator.MoveNext();
                    currentKvp = 0;
                }
                else
                {
                    var gcd = MathFunctions.GreatCommonDivisor(currentValue, currentKvp, this.integerEuclideanDomain);
                    if (gcd == 1)
                    {
                        var degree = 0;
                        if (auxiliary.TryGetValue(currentKvp, out degree))
                        {
                            auxiliary[currentKvp] = degree + currentDegree;
                        }
                        else
                        {
                            auxiliary.Add(currentKvp, currentDegree);
                        }

                        state      = subsidiaryEnumerator.MoveNext();
                        currentKvp = 0;
                    }
                    else
                    {
                        var currentKvpAux = currentKvp / gcd;
                        currentValue  = currentValue / gcd;
                        currentDegree = currentDegree - 1;
                        if (currentDegree == 0)
                        {
                            if (currentKvpAux != 1)
                            {
                                var degree = 0;
                                if (auxiliary.TryGetValue(currentKvp, out degree))
                                {
                                    auxiliary[currentKvp] = degree + 1;
                                }
                                else
                                {
                                    auxiliary.Add(currentKvp, 1);
                                }

                                currentKvp = currentKvpAux;
                            }
                            else
                            {
                                state      = subsidiaryEnumerator.MoveNext();
                                currentKvp = 0;
                            }
                        }
                        else
                        {
                            if (currentValue == 1)
                            {
                                var degree = 0;
                                if (auxiliary.TryGetValue(currentKvp, out degree))
                                {
                                    auxiliary[currentKvp] = degree + currentDegree;
                                }
                                else
                                {
                                    auxiliary.Add(currentKvp, currentDegree);
                                }

                                subsidiaryEnumerator.MoveNext();
                                currentKvp = 0;
                            }
                        }
                    }
                }
            }

            subsidiary.Clear();
            foreach (var kvp in auxiliary)
            {
                subsidiary.Add(kvp.Key, kvp.Value);
            }

            if (currentValue != 1)
            {
                var mainDegree = 0;
                if (main.TryGetValue(currentValue, out mainDegree))
                {
                    main[currentValue] = mainDegree + 1;
                }
                else
                {
                    main.Add(currentValue, 1);
                }
            }
        }
Esempio n. 10
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);
        }
        /// <summary>
        /// Multiplica um dos termos, dividindo o outro.
        /// </summary>
        /// <param name="main">O termo a ser multiplicado.</param>
        /// <param name="subsidiary">O termo a ser dividido.</param>
        /// <param name="factorialValue">O valor do factorial a ser multiplicado.</param>
        /// <exception cref="ArgumentOutOfRangeException">Se o valor do factorial for negativo.</exception>
        private void Multiply(Dictionary <int, int> main,
                              Dictionary <int, int> subsidiary,
                              int factorialValue)
        {
            if (factorialValue < 0)
            {
                throw new ArgumentOutOfRangeException("Factorial value must be non-negative.");
            }
            else
            {
                var factorsList = new List <int>();
                var auxiliary   = new Dictionary <int, int>();
                for (int i = 2; i <= factorialValue; ++i)
                {
                    var currentValue         = i;
                    var subsidiaryEnumerator = subsidiary.GetEnumerator();
                    var state         = subsidiaryEnumerator.MoveNext();
                    var currentKvp    = subsidiaryEnumerator.Current.Key;
                    var currentDegree = subsidiaryEnumerator.Current.Value;
                    while (state)
                    {
                        if (currentKvp == 0)
                        {
                            currentKvp    = subsidiaryEnumerator.Current.Key;
                            currentDegree = subsidiaryEnumerator.Current.Value;
                        }

                        if (currentValue == 1)
                        {
                            if (currentDegree != 0)
                            {
                                var degree = 0;
                                if (auxiliary.TryGetValue(currentKvp, out degree))
                                {
                                    auxiliary[currentKvp] = degree + currentDegree;
                                }
                                else
                                {
                                    auxiliary.Add(currentKvp, currentDegree);
                                }
                            }

                            state      = subsidiaryEnumerator.MoveNext();
                            currentKvp = 0;
                        }
                        else
                        {
                            var gcd = MathFunctions.GreatCommonDivisor(currentValue, currentKvp, this.integerEuclideanDomain);
                            if (gcd == 1)
                            {
                                var degree = 0;
                                if (auxiliary.TryGetValue(currentKvp, out degree))
                                {
                                    auxiliary[currentKvp] = degree + currentDegree;
                                }
                                else
                                {
                                    auxiliary.Add(currentKvp, currentDegree);
                                }

                                state      = subsidiaryEnumerator.MoveNext();
                                currentKvp = 0;
                            }
                            else
                            {
                                var currentKvpAux = currentKvp / gcd;
                                currentValue  = currentValue / gcd;
                                currentDegree = currentDegree - 1;
                                if (currentDegree == 0)
                                {
                                    if (currentKvpAux != 1)
                                    {
                                        var degree = 0;
                                        if (auxiliary.TryGetValue(currentKvpAux, out degree))
                                        {
                                            auxiliary[currentKvpAux] = degree + 1;
                                        }
                                        else
                                        {
                                            auxiliary.Add(currentKvpAux, 1);
                                        }

                                        currentKvp = currentKvpAux;
                                    }
                                    else
                                    {
                                        state      = subsidiaryEnumerator.MoveNext();
                                        currentKvp = 0;
                                    }
                                }
                                else
                                {
                                    if (currentValue == 1)
                                    {
                                        var degree = 0;
                                        if (auxiliary.TryGetValue(currentKvp, out degree))
                                        {
                                            auxiliary[currentKvp] = degree + currentDegree;
                                        }
                                        else
                                        {
                                            auxiliary.Add(currentKvp, currentDegree);
                                        }

                                        subsidiaryEnumerator.MoveNext();
                                        currentKvp = 0;
                                    }
                                }
                            }
                        }
                    }

                    if (currentValue != 1)
                    {
                        factorsList.Add(currentValue);
                    }

                    subsidiary.Clear();
                    foreach (var kvp in auxiliary)
                    {
                        subsidiary.Add(kvp.Key, kvp.Value);
                    }

                    auxiliary.Clear();
                }

                foreach (var factor in factorsList)
                {
                    var degree = 0;
                    if (main.TryGetValue(factor, out degree))
                    {
                        main[factor] = degree + 1;
                    }
                    else
                    {
                        main.Add(factor, 1);
                    }
                }
            }
        }
        /// <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));
            }
        }
        /// <summary>
        /// Calcula o determinante.
        /// </summary>
        /// <param name="data">A matriz.</param>
        /// <returns>O valor do determinante.</returns>
        protected override ObjectType ComputeDeterminant(IMatrix <ObjectType> data)
        {
            var positiveResult     = true;
            var determinantFactors = new List <ObjectType>();
            var matrixDimension    = data.GetLength(0);

            if (matrixDimension == 0)
            {
                return(this.ring.AdditiveUnity);
            }
            else
            {
                // Copia a matriz uma vez que o algoritmo a vai alterar
                var temporaryArray = new ArrayMathMatrix <ObjectType>(matrixDimension, matrixDimension);
                for (int i = 0; i < matrixDimension; ++i)
                {
                    for (int j = 0; j < matrixDimension; ++j)
                    {
                        temporaryArray[i, j] = data[i, j];
                    }
                }

                for (int i = 0; i < matrixDimension - 1; ++i)
                {
                    var pivotValue = temporaryArray[i, i];
                    if (this.ring.IsAdditiveUnity(pivotValue))
                    {
                        var nextPivotCandidate = this.GetNextNonEmptyPivotLineNumber(i, temporaryArray);
                        if (nextPivotCandidate == -1)
                        {
                            return(this.ring.AdditiveUnity);
                        }
                        else
                        {
                            positiveResult = !positiveResult;
                            temporaryArray.SwapLines(i, nextPivotCandidate);
                            pivotValue = temporaryArray[i, i];
                        }
                    }

                    if (this.ring.IsMultiplicativeUnity(pivotValue))
                    {
                        for (int j = i + 1; j < matrixDimension; ++j)
                        {
                            var value = temporaryArray[j, i];
                            if (!this.ring.IsAdditiveUnity(value))
                            {
                                temporaryArray[j, i] = this.ring.AdditiveUnity;
                                for (int k = i + 1; k < matrixDimension; ++k)
                                {
                                    var temp = this.ring.Multiply(value, temporaryArray[i, k]);
                                    temporaryArray[j, k] = this.ring.Add(temporaryArray[j, k], this.ring.AdditiveInverse(temp));
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = i + 1; j < matrixDimension; ++j)
                        {
                            var value = temporaryArray[j, i];
                            if (!this.ring.IsAdditiveUnity(value))
                            {
                                var gcd = MathFunctions.GreatCommonDivisor(pivotValue, value, this.domain);
                                var lcm = this.ring.Multiply(pivotValue, value);
                                lcm = this.domain.Quo(lcm, gcd);
                                var pivotCoffactor = this.domain.Quo(pivotValue, gcd);
                                var valueCoffactor = this.domain.Quo(value, gcd);
                                determinantFactors.Add(pivotCoffactor);
                                temporaryArray[j, i] = this.ring.AdditiveUnity;
                                for (int k = i + 1; k < matrixDimension; ++k)
                                {
                                    var positive = this.ring.Multiply(pivotCoffactor, temporaryArray[j, k]);
                                    var negative = this.ring.Multiply(valueCoffactor, temporaryArray[i, k]);
                                    temporaryArray[j, k] = this.ring.Add(positive, this.ring.AdditiveInverse(negative));
                                }
                            }
                        }
                    }
                }

                return(this.GetDeterminantValue(temporaryArray, determinantFactors, positiveResult));
            }
        }
Esempio n. 14
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));
        }
        /// <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);
        }