/** * 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); } }
/** * 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); }
/** * 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); } }