/// <summary> /// Cria instâncias de objectos do tipo <see cref="ModularBachetBezoutField{ObjectType}"/>. /// </summary> /// <remarks> /// A determinação da inversa multiplicativa é efectuada por intermédio de algoritmos relacionados /// com o algoritmo que permite determinar o máximo divisor comum. Neste caso, é necessário indicar /// qual será o algoritmo responsável por essa operação. /// </remarks> /// <param name="module">O módulo.</param> /// <param name="bachetBezoutAlgorithm"> /// O algoritmo responsável pela determinação da inversa multiplicativa. /// </param> /// <exception cref="ArgumentNullException"> /// Se pelo menos um dos argumentos for nulo. /// </exception> public ModularBachetBezoutField( ObjectType module, IBachetBezoutAlgorithm <ObjectType> bachetBezoutAlgorithm) { if (bachetBezoutAlgorithm == null) { throw new ArgumentNullException("bachetBezoutAlgorithm"); } else if (module == null) { throw new ArgumentNullException("module"); } else { this.bachetBezoutAlgorithm = bachetBezoutAlgorithm; this.module = module; } }
/// <summary> /// Obtém o mínimo múltiplo comum entre os denominadores do polinómio. /// </summary> /// <param name="polynom">O polinómio.</param> /// <param name="gcdCAlg">O domínio responsável pelas operações sobre os coeficientes.</param> /// <returns>O valor do mínimo múltiplo comum.</returns> private CoeffType GetDenominatorLcm( UnivariatePolynomialNormalForm <Fraction <CoeffType> > polynom, IBachetBezoutAlgorithm <CoeffType> gcdCAlg) { var termsEnumerator = polynom.GetEnumerator(); var state = termsEnumerator.MoveNext(); if (state) { var coeff = termsEnumerator.Current.Value.Denominator; state = termsEnumerator.MoveNext(); while (state && gcdCAlg.Domain.IsMultiplicativeUnity(coeff)) { coeff = termsEnumerator.Current.Value.Denominator; state = termsEnumerator.MoveNext(); } while (state) { var current = termsEnumerator.Current.Value.Denominator; if (!gcdCAlg.Domain.IsMultiplicativeUnity(current)) { var status = gcdCAlg.Run(coeff, current); coeff = gcdCAlg.Domain.Multiply(status.FirstItem, status.SecondCofactor); } state = termsEnumerator.MoveNext(); } return(coeff); } else { return(gcdCAlg.Domain.MultiplicativeUnity); } }
/// <summary> /// Obtém a congruência que soluciona o problema do resto chinês associado à lista de congruências /// proporcionada. /// </summary> /// <param name="congruences">A lista de congruências.</param> /// <param name="domain">O domínio.</param> /// <returns>A solução do problema caso exista e nulo caso contrário.</returns> /// <exception cref="MathematicsException"> /// Se o algoritmo já se encontrar em execução ou não forem providenciadas quaisquer congruências. /// </exception> /// <exception cref="ArgumentNullException">Se o domínio for nulo.</exception> public Congruence <ObjectType> Run( List <Congruence <ObjectType> > congruences, IEuclidenDomain <ObjectType> domain) { lock (this.lockObject) { if (this.running) { throw new MathematicsException("The chinese remainder algorithm is running."); } else if (domain == null) { throw new ArgumentNullException("domain"); } else if (congruences == null || congruences.Count == 0) { throw new MathematicsException("No congruence was provided."); } else { this.running = true; } } try { this.foundError = false; if (this.SetupCongruences(congruences, domain)) { this.domain = domain; this.extendedAlgorithm = new LagrangeAlgorithm <ObjectType>(domain); this.SolveTwo(); lock (this.lockObject) { this.running = false; if (this.foundError) { return(null); } else { return(this.processingCongruences[0]); } } } else { lock (this.lockObject) { this.running = false; } return(null); } } catch (Exception exception) { lock (this.lockObject) { this.running = false; } throw exception; } }