/// <summary> /// Resultant of this polynomial with <c>x^n-1 mod p</c>. /// </summary> /// /// <param name="P">P value</param> /// /// <returns>Returns <c>(rho, res)</c> satisfying <c>res = rho*this + t*(x^n-1) mod p</c> for some integer <c>t</c>.</returns> public ModularResultant Resultant(int P) { // Add a coefficient as the following operations involve polynomials of degree deg(f)+1 int[] fcoeffs = Coeffs.CopyOf(Coeffs.Length + 1); 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 = 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 *= 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 *= Pow(b.Coeffs[0], da, P); r %= P; c = 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 v2.Coeffs = v2.Coeffs.CopyOf(v2.Coeffs.Length - 1); return new ModularResultant(new BigIntPolynomial(v2), BigInteger.ValueOf(r), BigInteger.ValueOf(P)); }