public IntegerPolynomial Multiply(IntegerPolynomial poly2, int modulus) { IntegerPolynomial c = Multiply(poly2); c.Mod(modulus); return(c); }
/** * Multithreaded version of {@link #resultant()}. * * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>. */ /* Taking out Async for now, harder problem than just translating. * public async Task<Resultant> ResultantMultiThread() * { * int N = coeffs.Length; * * // upper bound for resultant(f, g) = ||f, 2||^deg(g) * ||g, 2||^deg(f) = squaresum(f)^(N/2) * 2^(deg(f)/2) because g(x)=x^N-1 * // see http://jondalon.mathematik.uni-osnabrueck.de/staff/phpages/brunsw/CompAlg.pdf chapter 3 * BigInteger max = squareSum().pow((N + 1) / 2); * max = max.multiply(BigInteger.ValueOf(2).pow((degree() + 1) / 2)); * BigInteger max2 = max.multiply(BigInteger.ValueOf(2)); * * // compute resultants modulo prime numbers * BigInteger prime = BigInteger.ValueOf(10000); * BigInteger pProd = Constants.BIGINT_ONE; * LinkedBlockingQueue<Task<ModularResultant>> resultantTasks = new LinkedBlockingQueue<Task<ModularResultant>>(); * Iterator<BigInteger> primes = BIGINT_PRIMES.Iterator(); * ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); * while (pProd.CompareTo(max2) < 0) * { * if (primes.hasNext()) * { * prime = primes.next(); * } * else * { * prime = prime.NextProbablePrime(); * } * Task<ModularResultant> task = executor.submit(new ModResultantTask(prime.IntValue)); * resultantTasks.add(task); * pProd = pProd.Multiply(prime); * } * * // Combine modular resultants to obtain the resultant. * // For efficiency, first combine all pairs of small resultants to bigger resultants, * // then combine pairs of those, etc. until only one is left. * ModularResultant overallResultant = null; * while (!resultantTasks.isEmpty()) * { * try * { * Task<ModularResultant> modRes1 = resultantTasks.take(); * Task<ModularResultant> modRes2 = resultantTasks.poll(); * if (modRes2 == null) * { * // modRes1 is the only one left * overallResultant = await modRes1; //modRes1..get(); * break; * } * Task<ModularResultant> newTask = executor.submit(new CombineTask(modRes1.get(), modRes2.get())); * resultantTasks.add(newTask); * } * catch (Exception e) * { * throw new InvalidOperationException(e.ToString()); * } * } * executor.shutdown(); * BigInteger res = overallResultant.res; * BigIntPolynomial rhoP = overallResultant.rho; * * BigInteger pProd2 = pProd.divide(BigInteger.ValueOf(2)); * BigInteger 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); * } */ /** * Resultant of this polynomial with <code>x^n-1 mod p</code>. * * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1) mod p</code> for some integer <code>t</code>. */ public ModularResultant Resultant(int p) { // Add a coefficient as the following operations involve polynomials of degree deg(f)+1 int[] fcoeffs = new int[coeffs.Length + 1]; Array.Copy(coeffs, fcoeffs, coeffs.Length); IntegerPolynomial f = new IntegerPolynomial(fcoeffs); int N = fcoeffs.Length; IntegerPolynomial a = new IntegerPolynomial(N); a.coeffs[0] = -1; a.coeffs[N - 1] = 1; IntegerPolynomial b = new IntegerPolynomial(f.coeffs); IntegerPolynomial v1 = new IntegerPolynomial(N); IntegerPolynomial v2 = new IntegerPolynomial(N); v2.coeffs[0] = 1; int da = N - 1; int db = b.Degree(); int ta = da; int c = 0; int r = 1; while (db > 0) { c = Util.Util.Invert(b.coeffs[db], p); c = (c * a.coeffs[da]) % p; a.MultShiftSub(b, c, da - db, p); v1.MultShiftSub(v2, c, da - db, p); da = a.Degree(); if (da < db) { r *= Util.Util.Pow(b.coeffs[db], ta - da, p); r %= p; if (ta % 2 == 1 && db % 2 == 1) { r = (-r) % p; } IntegerPolynomial temp = a; a = b; b = temp; int tempdeg = da; da = db; temp = v1; v1 = v2; v2 = temp; ta = db; db = tempdeg; } } r *= Util.Util.Pow(b.coeffs[0], da, p); r %= p; c = Util.Util.Invert(b.coeffs[0], p); v2.Multiply(c); v2.Mod(p); v2.Multiply(r); v2.Mod(p); // drop the highest coefficient so #coeffs matches the original input int[] newCoeffs = new int[v2.coeffs.Length - 1]; Array.Copy(v2.coeffs, newCoeffs, v2.coeffs.Length - 1); v2.coeffs = newCoeffs; return(new ModularResultant(new BigIntPolynomial(v2), BigInteger.ValueOf(r), BigInteger.ValueOf(p))); }