/** * 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 ModularResultant call() { return(ModularResultant.CombineRho(modRes1, modRes2)); }