private void MultTest()
        {
            IntegerPolynomial i1 = new IntegerPolynomial(new int[] { 1368, 2047, 672, 871, 1662, 1352, 1099, 1608 });
            IntegerPolynomial i2 = new IntegerPolynomial(new int[] { 1729, 1924, 806, 179, 1530, 1381, 1695, 60 });
            LongPolynomial2 a = new LongPolynomial2(i1);
            LongPolynomial2 b = new LongPolynomial2(i2);
            IntegerPolynomial c1 = i1.Multiply(i2, 2048);
            IntegerPolynomial c2 = a.Multiply(b).ToIntegerPolynomial();

            if (!Compare.AreEqual(c1.Coeffs, c2.Coeffs))
                throw new Exception("LongPolynomial2 multiply test failed!");

            // test 10 random polynomials
            Random rng = new Random();
            for (int i = 0; i < 10; i++)
            {
                int N = 2 + rng.Next(2000);
                i1 = (IntegerPolynomial)PolynomialGeneratorForTesting.GenerateRandom(N, 2048);
                i2 = (IntegerPolynomial)PolynomialGeneratorForTesting.GenerateRandom(N, 2048);
                a = new LongPolynomial2(i1);
                b = new LongPolynomial2(i2);
                c1 = i1.Multiply(i2);
                c1.ModPositive(2048);
                c2 = a.Multiply(b).ToIntegerPolynomial();

                if (!Compare.AreEqual(c1.Coeffs, c2.Coeffs))
                    throw new Exception("LongPolynomial2 multiply test failed!");
            }
        }
        /// <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));
        }
        private void MultTest(int[] coeffs1, int[] coeffs2)
        {
            IntegerPolynomial i1 = new IntegerPolynomial(coeffs1);
            IntegerPolynomial i2 = new IntegerPolynomial(coeffs2);
            LongPolynomial5 a = new LongPolynomial5(i1);
            DenseTernaryPolynomial b = new DenseTernaryPolynomial(i2);
            IntegerPolynomial c1 = i1.Multiply(i2, 2048);
            IntegerPolynomial c2 = a.Multiply(b).ToIntegerPolynomial();

            if (!EqualsMod(c1.Coeffs, c2.Coeffs, 2048))
                throw new Exception("LongPolynomial5 multiply test failed!");
        }
        private void Mult2AndTest()
        {
            IntegerPolynomial i1 = new IntegerPolynomial(new int[] { 1368, 2047, 672, 871, 1662, 1352, 1099, 1608 });
            LongPolynomial2 i2 = new LongPolynomial2(i1);
            i2.Mult2And(2047);
            i1.Multiply(2);
            i1.ModPositive(2048);

            if (!Compare.AreEqual(i1.Coeffs, i2.ToIntegerPolynomial().Coeffs))
                throw new Exception("LongPolynomial2 Mult2And test failed!");
        }
        private void MultTest()
        {
            // multiplication modulo q
            IntegerPolynomial a = new IntegerPolynomial(new int[] { -1, 1, 1, 0, -1, 0, 1, 0, 0, 1, -1 });
            IntegerPolynomial b = new IntegerPolynomial(new int[] { 14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19 });
            IntegerPolynomial c = a.Multiply(b, 32);
            AssertEqualsMod(new int[] { 3, -7, -10, -11, 10, 7, 6, 7, 5, -3, -7 }, c.Coeffs, 32);

            a = new IntegerPolynomial(new int[] { 15, 27, 18, 16, 12, 13, 16, 2, 28, 22, 26 });
            b = new IntegerPolynomial(new int[] { -1, 0, 1, 1, 0, 1, 0, 0, -1, 0, -1 });
            c = a.Multiply(b, 32);
            AssertEqualsMod(new int[] { 8, 25, 22, 20, 12, 24, 15, 19, 12, 19, 16 }, c.Coeffs, 32);

            // multiplication without a modulus
            a = new IntegerPolynomial(new int[] { 1, 1, 0, 0, -1, -1, 0, 0, -1, 0, 1 });
            b = new IntegerPolynomial(new int[] { 2, 14, -10, 10, -4, -10, 2, 12, 11, -2, 8 });
            c = a.Multiply(b);

            if (!Compare.AreEqual(new int[] { 0, -13, 15, -12, -26, -39, 2, 17, 13, 17, 26 }, c.Coeffs))
                throw new Exception("IntegerPolynomial multiplication test failed!");

            // mult(p, modulus) should give the same result as mult(p) followed by modulus
            a = new IntegerPolynomial(new int[] { 1, 0, -1, 1, 0, 1, 1, 1, -1, 1, -1 });
            b = new IntegerPolynomial(new int[] { 0, 1, 1, 0, 0, -1, -1, 1, 1, -1, 1 });
            c = a.Multiply(b);
            c.ModPositive(20);
            IntegerPolynomial d = a.Multiply(b, 20);
            d.ModPositive(20);

            if (!Compare.AreEqual(c.Coeffs, d.Coeffs))
                throw new Exception("IntegerPolynomial multiplication test failed!");
        }
        // tests if a*b=1 (mod modulus)
        private void VerifyInverse(IntegerPolynomial a, IntegerPolynomial b, int modulus)
        {
            IntegerPolynomial c = a.Multiply(b, modulus);
            for (int i = 1; i < c.Coeffs.Length; i++)
                c.Coeffs[i] %= modulus;

            c.EnsurePositive(modulus);
            if (!c.EqualsOne())
                throw new Exception("IntegerPolynomialTest Modulus inverse test failed!");
        }