/** * Method based on FFT to find the determinant and the first coefficient of w(x) this suffices to * find w(x) completely * * @param q the polynomial * @param n the degree * @return The determinant and the first coefficient of w(x). */ static BigInteger[] gzModZ2(Polynomial q, int n) { int i; int N = 1 << n; Polynomial V = new Polynomial(q.coeffs); // V = q Polynomial U = new Polynomial(1); // U = 1 U.setCoeff(0, new BigInteger("1")); Polynomial F = new Polynomial(N); // F(x) = x^N +1 F.setCoeff(0, new BigInteger("1")); F.setCoeff(N, new BigInteger("1")); Polynomial V2 = new Polynomial(N); while (N > 1) { V2 = new Polynomial(V.coeffs); for (i = 1; i <= V2.degree; i += 2) { // set V2(x) := V(-x) V2.coeffs[i] = V2.coeffs[i].negate(); // negate odd coefficients } V = Polynomial.mod(Polynomial.mult(V, V2), F); // V := V(x) * V(-x) mod f(x) U = Polynomial.mod(Polynomial.mult(U, V2), F); // U := U(x) * V(-x) mod f(x) // Sanity-check: verify that the odd coefficients in V are zero for (i = 1; i <= V.degree; i += 2) if (!V.coeffs[i].equals(new BigInteger("0"))) { return null; } // "Compress" the non-zero coefficients of V for (i = 1; i <= V.degree / 2; i++) V.coeffs[i] = V.coeffs[2 * i]; for (; i <= V.degree; i++) V.coeffs[i] = new BigInteger("0"); V.normalize(); // Set U to the "compressed" ( U(x) + U(-x) ) /2 for (i = 0; i <= U.degree / 2; i++) U.coeffs[i] = U.coeffs[2 * i]; for (; i <= U.degree; i++) U.coeffs[i] = new BigInteger("0"); U.normalize(); // Set N := N/2 and update F accordingly F.coeffs[N] = new BigInteger("0"); N >>= 1; F.coeffs[N] = new BigInteger("1"); F.normalize(); } return new BigInteger[] {V.coeffs[0], U.coeffs[0]}; }