public IntegerPolynomial ToIntegerPolynomial() { IntegerPolynomial i = F1.Multiply(F2.ToIntegerPolynomial()); i.Add(F3.ToIntegerPolynomial()); return(i); }
public IntegerPolynomial Multiply(IntegerPolynomial poly2, int modulus) { IntegerPolynomial c = Multiply(poly2); c.Mod(modulus); return(c); }
public IntegerPolynomial Multiply(IntegerPolynomial b) { IntegerPolynomial c = F1.Multiply(b); c = F2.Multiply(c); c.Add(F3.Multiply(b)); return(c); }
/** * Constructs a <code>BigIntPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are * independent of each other. * * @param p the original polynomial */ public BigIntPolynomial(IntegerPolynomial p) { coeffs = new BigInteger[p.coeffs.Length]; for (int i = 0; i < coeffs.Length; i++) { coeffs[i] = BigInteger.ValueOf(p.coeffs[i]); } }
/** * Computes <code>this-b*c*(x^k) mod p</code> and stores the result in this polynomial.<br/> * See steps 4a,4b in EESS algorithm 2.2.7.1. * * @param b * @param c * @param k * @param p */ private void MultShiftSub(IntegerPolynomial b, int c, int k, int p) { int N = coeffs.Length; for (int i = k; i < N; i++) { coeffs[i] = (coeffs[i] - b.coeffs[i - k] * c) % p; } }
/** * Subtracts another polynomial which can have a different number of coefficients. * * @param b another polynomial */ public void Sub(IntegerPolynomial b) { if (b.coeffs.Length > coeffs.Length) { Array.Copy(coeffs, coeffs, b.coeffs.Length); } for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] -= b.coeffs[i]; } }
/** * Adds another polynomial which can have a different number of coefficients. * * @param b another polynomial */ public void Add(IntegerPolynomial b) { if (b.coeffs.Length > coeffs.Length) { int[] temp = new int[b.coeffs.Length]; Array.Copy(coeffs, temp, coeffs.Length); coeffs = temp; } for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] += b.coeffs[i]; } }
public new IntegerPolynomial Multiply(IntegerPolynomial poly2, int modulus) { // even on 32-bit systems, LongPolynomial5 multiplies faster than IntegerPolynomial if (modulus == 2048) { IntegerPolynomial poly2Pos = (IntegerPolynomial)poly2.Clone(); poly2Pos.ModPositive(2048); LongPolynomial5 poly5 = new LongPolynomial5(poly2Pos); return(poly5.Multiply(this).ToIntegerPolynomial()); } else { return(base.Multiply(poly2, modulus)); } }
/** * Constructs a <code>LongPolynomial5</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other. * * @param p the original polynomial. Coefficients must be between 0 and 2047. */ public LongPolynomial5(IntegerPolynomial p) { numCoeffs = p.coeffs.Length; coeffs = new long[(numCoeffs + 4) / 5]; int cIdx = 0; int shift = 0; for (int i = 0; i < numCoeffs; i++) { coeffs[cIdx] |= ((long)p.coeffs[i]) << shift; shift += 12; if (shift >= 60) { shift = 0; cIdx++; } } }
public IntegerPolynomial Multiply(IntegerPolynomial poly2) { int[] b = poly2.coeffs; if (b.Length != N) { throw new InvalidOperationException("Number of coefficients must be the same"); } int[] c = new int[N]; for (int idx = 0; idx != Ones.Length; idx++) { int i = Ones[idx]; int j = N - 1 - i; for (int k = N - 1; k >= 0; k--) { c[k] += b[j]; j--; if (j < 0) { j = N - 1; } } } for (int idx = 0; idx != NegOnes.Length; idx++) { int i = NegOnes[idx]; int j = N - 1 - i; for (int k = N - 1; k >= 0; k--) { c[k] -= b[j]; j--; if (j < 0) { j = N - 1; } } } return(new IntegerPolynomial(c)); }
/** * Computes the centered euclidean norm of the polynomial. * * @param q a modulus * @return the centered norm */ public long CenteredNormSq(int q) { int N = coeffs.Length; IntegerPolynomial p = (IntegerPolynomial)Clone(); p.ShiftGap(q); long sum = 0; long sqSum = 0; for (int i = 0; i != p.coeffs.Length; i++) { int c = p.coeffs[i]; sum += c; sqSum += c * c; } long centeredNormSq = sqSum - sum * sum / N; return(centeredNormSq); }
/** * Constructs a <code>LongPolynomial2</code> from a <code>IntegerPolynomial</code>. The two polynomials are independent of each other. * * @param p the original polynomial. Coefficients must be between 0 and 2047. */ public LongPolynomial2(IntegerPolynomial p) { numCoeffs = p.coeffs.Length; coeffs = new long[(numCoeffs + 1) / 2]; int idx = 0; for (int pIdx = 0; pIdx < numCoeffs;) { int c0 = p.coeffs[pIdx++]; while (c0 < 0) { c0 += 2048; } long c1 = pIdx < numCoeffs ? p.coeffs[pIdx++] : 0; while (c1 < 0) { c1 += 2048; } coeffs[idx] = c0 + (c1 << 24); idx++; } }
/** * Multiplies the polynomial with another, taking the indices mod N */ public IntegerPolynomial Multiply(IntegerPolynomial poly2) { int N = coeffs.Length; if (poly2.coeffs.Length != N) { throw new InvalidDataException("Number of coefficients must be the same"); } IntegerPolynomial c = MultiplyRecursive(poly2); if (c.coeffs.Length > N) { for (int k = N; k < c.coeffs.Length; k++) { c.coeffs[k - N] += c.coeffs[k]; } int[] myCoeffs = new int[N]; Array.Copy(c.coeffs, myCoeffs, N); c.coeffs = myCoeffs; } return(c); }
/** * Computes the inverse mod q from the inverse mod 2 * * @param Fq * @param q * @return The inverse of this polynomial mod q */ private IntegerPolynomial Mod2ToModq(IntegerPolynomial Fq, int q) { //if (Util.is64BitJVM() && q == 2048) if (true && q == 2048) { LongPolynomial2 thisLong = new LongPolynomial2(this); LongPolynomial2 FqLong = new LongPolynomial2(Fq); int v = 2; while (v < q) { v *= 2; LongPolynomial2 temp = (LongPolynomial2)FqLong.Clone(); temp.mult2And(v - 1); FqLong = thisLong.Multiply(FqLong).Multiply(FqLong); temp.SubAnd(FqLong, v - 1); FqLong = temp; } return(FqLong.ToIntegerPolynomial()); } else { int v = 2; while (v < q) { v *= 2; int[] copy = new int[Fq.coeffs.Length]; Array.Copy(Fq.coeffs, copy, Fq.coeffs.Length); IntegerPolynomial temp = new IntegerPolynomial(copy); temp.Multiply2(v); Fq = Multiply(Fq, v).Multiply(Fq, v); temp.Sub(Fq, v); Fq = temp; } return(Fq); } }
/** * Constructs a <code>DenseTernaryPolynomial</code> from a <code>IntegerPolynomial</code>. The two polynomials are * independent of each other. * * @param intPoly the original polynomial */ public SparseTernaryPolynomial(IntegerPolynomial intPoly) : this(intPoly.coeffs) { }
/** * Karazuba multiplication */ private IntegerPolynomial MultiplyRecursive(IntegerPolynomial poly2) { int[] a = coeffs; int[] b = poly2.coeffs; int n = poly2.coeffs.Length; if (n <= 32) { int cn = 2 * n - 1; IntegerPolynomial c = new IntegerPolynomial(new int[cn]); for (int k = 0; k < cn; k++) { for (int i = System.Math.Max(0, k - n + 1); i <= System.Math.Min(k, n - 1); i++) { c.coeffs[k] += b[i] * a[k - i]; } } return(c); } else { int n1 = n / 2; int[] a1temp = new int[n1]; int[] a2temp = new int[n - n1]; int[] b1temp = new int[n1]; int[] b2temp = new int[n - n1]; Array.Copy(a, a1temp, n1); Array.Copy(a, n1, a2temp, 0, n - n1); Array.Copy(b, b1temp, n1); Array.Copy(b, n1, b2temp, 0, n - n1); IntegerPolynomial a1 = new IntegerPolynomial(a1temp); IntegerPolynomial a2 = new IntegerPolynomial(a2temp); IntegerPolynomial b1 = new IntegerPolynomial(b1temp); IntegerPolynomial b2 = new IntegerPolynomial(b2temp); IntegerPolynomial A = (IntegerPolynomial)a1.Clone(); A.Add(a2); IntegerPolynomial B = (IntegerPolynomial)b1.Clone(); B.Add(b2); IntegerPolynomial c1 = a1.MultiplyRecursive(b1); IntegerPolynomial c2 = a2.MultiplyRecursive(b2); IntegerPolynomial c3 = A.MultiplyRecursive(B); c3.Sub(c1); c3.Sub(c2); IntegerPolynomial c = new IntegerPolynomial(2 * n - 1); for (int i = 0; i < c1.coeffs.Length; i++) { c.coeffs[i] = c1.coeffs[i]; } for (int i = 0; i < c3.coeffs.Length; i++) { c.coeffs[n1 + i] += c3.coeffs[i]; } for (int i = 0; i < c2.coeffs.Length; i++) { c.coeffs[2 * n1 + i] += c2.coeffs[i]; } return(c); } }
/** * Computes the inverse mod <code>q; q</code> must be a power of 2.<br> * Returns <code>null</code> if the polynomial is not invertible. * * @param q the modulus * @return a new polynomial */ public IntegerPolynomial InvertFq(int q) { int N = coeffs.Length; int k = 0; IntegerPolynomial b = new IntegerPolynomial(N + 1); b.coeffs[0] = 1; IntegerPolynomial c = new IntegerPolynomial(N + 1); IntegerPolynomial f = new IntegerPolynomial(N + 1); Array.Copy(coeffs, f.coeffs, N); f.ModPositive(2); // set g(x) = x^N − 1 IntegerPolynomial g = new IntegerPolynomial(N + 1); g.coeffs[0] = 1; g.coeffs[N] = 1; while (true) { while (f.coeffs[0] == 0) { for (int i = 1; i <= N; i++) { f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x } f.coeffs[N] = 0; c.coeffs[0] = 0; k++; if (f.EqualsZero()) { return(null); // not invertible } } if (f.EqualsOne()) { break; } if (f.Degree() < g.Degree()) { // exchange f and g IntegerPolynomial temp = f; f = g; g = temp; // exchange b and c temp = b; b = c; c = temp; } f.Add(g, 2); b.Add(c, 2); } if (b.coeffs[N] != 0) { return(null); } // Fq(x) = x^(N-k) * b(x) IntegerPolynomial Fq = new IntegerPolynomial(N); int j = 0; k %= N; for (int i = N - 1; i >= 0; i--) { j = i - k; if (j < 0) { j += N; } Fq.coeffs[j] = b.coeffs[i]; } return(Mod2ToModq(Fq, q)); }
/** * Subtracts another polynomial which can have a different number of coefficients, * and takes the coefficient values mod <code>modulus</code>. * * @param b another polynomial */ public void Sub(IntegerPolynomial b, int modulus) { Sub(b); Mod(modulus); }
/** * Adds another polynomial which can have a different number of coefficients, * and takes the coefficient values mod <code>modulus</code>. * * @param b another polynomial */ public void Add(IntegerPolynomial b, int modulus) { Add(b); Mod(modulus); }
/** * Computes the inverse mod 3. * Returns <code>null</code> if the polynomial is not invertible. * * @return a new polynomial */ public IntegerPolynomial InvertF3() { int N = coeffs.Length; int k = 0; IntegerPolynomial b = new IntegerPolynomial(N + 1); b.coeffs[0] = 1; IntegerPolynomial c = new IntegerPolynomial(N + 1); IntegerPolynomial f = new IntegerPolynomial(N + 1); Array.Copy(coeffs, f.coeffs, N); f.ModPositive(3); // set g(x) = x^N − 1 IntegerPolynomial g = new IntegerPolynomial(N + 1); g.coeffs[0] = -1; g.coeffs[N] = 1; while (true) { while (f.coeffs[0] == 0) { for (int i = 1; i <= N; i++) { f.coeffs[i - 1] = f.coeffs[i]; // f(x) = f(x) / x c.coeffs[N + 1 - i] = c.coeffs[N - i]; // c(x) = c(x) * x } f.coeffs[N] = 0; c.coeffs[0] = 0; k++; if (f.EqualsZero()) { return(null); // not invertible } } if (f.EqualsAbsOne()) { break; } if (f.Degree() < g.Degree()) { // exchange f and g IntegerPolynomial temp = f; f = g; g = temp; // exchange b and c temp = b; b = c; c = temp; } if (f.coeffs[0] == g.coeffs[0]) { f.Sub(g, 3); b.Sub(c, 3); } else { f.Add(g, 3); b.Add(c, 3); } } if (b.coeffs[N] != 0) { return(null); } // Fp(x) = [+-] x^(N-k) * b(x) IntegerPolynomial Fp = new IntegerPolynomial(N); int j = 0; k %= N; for (int i = N - 1; i >= 0; i--) { j = i - k; if (j < 0) { j += N; } Fp.coeffs[j] = f.coeffs[0] * b.coeffs[i]; } Fp.EnsurePositive(3); return(Fp); }
/** * 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))); }