/** * Calculates a <code>rho</code> modulo <code>m1*m2</code> from * two resultants whose <code>rho</code>s are modulo <code>m1</code> and <code>m2</code>.<br/> * </code>res</code> is set to <code>null</code>. * * @param modRes1 * @param modRes2 * @return <code>rho</code> modulo <code>modRes1.modulus * modRes2.modulus</code>, and <code>null</code> for </code>res</code>. */ public static ModularResultant CombineRho(ModularResultant modRes1, ModularResultant modRes2) { BigInteger mod1 = modRes1.modulus; BigInteger mod2 = modRes2.modulus; BigInteger prod = mod1.Multiply(mod2); BigIntEuclidean er = BigIntEuclidean.Calculate(mod2, mod1); BigIntPolynomial rho1 = (BigIntPolynomial)modRes1.Rho.Clone(); rho1.Multiply(er.x.Multiply(mod2)); BigIntPolynomial rho2 = (BigIntPolynomial)modRes2.Rho.Clone(); rho2.Multiply(er.y.Multiply(mod1)); rho1.Add(rho2); rho1.Mod(prod); return(new ModularResultant(rho1, null, prod)); }
public ModularResultant call() { return(ModularResultant.CombineRho(modRes1, modRes2)); }
/** * Resultant of this polynomial with <code>x^n-1</code> using a probabilistic algorithm. * <p> * Unlike EESS, this implementation does not compute all resultants modulo primes * such that their product exceeds the maximum possible resultant, but rather stops * when <code>NUM_EQUAL_RESULTANTS</code> consecutive modular resultants are equal.<br> * This means the return value may be incorrect. Experiments show this happens in * about 1 out of 100 cases when <code>N=439</code> and <code>NUM_EQUAL_RESULTANTS=2</code>, * so the likelyhood of leaving the loop too early is <code>(1/100)^(NUM_EQUAL_RESULTANTS-1)</code>. * <p> * Because of the above, callers must verify the output and try a different polynomial if necessary. * * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>. */ public Resultant Resultant() { int N = coeffs.Length; // Compute resultants modulo prime numbers. Continue until NUM_EQUAL_RESULTANTS consecutive modular resultants are equal. LinkedList <ModularResultant> modResultants = new LinkedList <ModularResultant>(); BigInteger pProd = Constants.BIGINT_ONE; BigInteger res = Constants.BIGINT_ONE; int numEqual = 1; // number of consecutive modular resultants equal to each other PrimeGenerator primes = new PrimeGenerator(); BigInteger pProd2; BigInteger pProd2n; while (true) { BigInteger prime = primes.nextPrime(); ModularResultant crr = Resultant(prime.IntValue); modResultants.AddLast(crr); //Was just add in Java BigInteger temp = pProd.Multiply(prime); BigIntEuclidean er = BigIntEuclidean.Calculate(prime, pProd); BigInteger resPrev = res; res = res.Multiply(er.x.Multiply(prime)); BigInteger res2 = crr.Res.Multiply(er.y.Multiply(pProd)); res = res.Add(res2).Mod(temp); pProd = temp; pProd2 = pProd.Divide(BigInteger.ValueOf(2)); pProd2n = pProd2.Negate(); if (res.CompareTo(pProd2) > 0) { res = res.Subtract(pProd); } else if (res.CompareTo(pProd2n) < 0) { res = res.Add(pProd); } if (res.Equals(resPrev)) { numEqual++; if (numEqual >= NUM_EQUAL_RESULTANTS) { break; } } else { numEqual = 1; } } // Combine modular rho's to obtain the final rho. // For efficiency, first combine all pairs of small resultants to bigger resultants, // then combine pairs of those, etc. until only one is left. while (modResultants.Count > 1) { ModularResultant modRes1 = modResultants.First.Value; modResultants.RemoveFirst(); ModularResultant modRes2 = modResultants.First.Value; modResultants.RemoveFirst(); ModularResultant modRes3 = ModularResultant.CombineRho(modRes1, modRes2); modResultants.AddLast(modRes3); } BigIntPolynomial rhoP = modResultants.First.Value.Rho; pProd2 = pProd.Divide(BigInteger.ValueOf(2)); pProd2n = pProd2.Negate(); if (res.CompareTo(pProd2) > 0) { res = res.Subtract(pProd); } if (res.CompareTo(pProd2n) < 0) { res = res.Add(pProd); } for (int i = 0; i < N; i++) { BigInteger c = rhoP.coeffs[i]; if (c.CompareTo(pProd2) > 0) { rhoP.coeffs[i] = c.Subtract(pProd); } if (c.CompareTo(pProd2n) < 0) { rhoP.coeffs[i] = c.Add(pProd); } } return(new Resultant(rhoP, res)); }
public CombineTask(ModularResultant modRes1, ModularResultant modRes2) { this.modRes1 = modRes1; this.modRes2 = modRes2; }