Example #1
0
        /// <summary>
        /// Multiplies the polynomial by another, taking the indices mod N.
        /// <para>Does not change this polynomial but returns the result as a new polynomial.
        /// Both polynomials must have the same number of coefficients.
        /// This method uses the <a href="http://en.wikipedia.org/wiki/Schönhage–Strassen_algorithm"/>
        /// Schönhage–Strassen algorithm.</para>
        /// </summary>
        ///
        /// <param name="Factor">Multiplication factor</param>
        ///
        /// <returns>Multiplied polynomial</returns>
        ///
        /// <exception cref="CryptoAsymmetricException">Thrown if the two polynomials differ in the number of coefficients</exception>
        public BigDecimalPolynomial Multiply(BigIntPolynomial Factor)
        {
            if (Factor.Coeffs.Length != Coeffs.Length)
            {
                throw new CryptoAsymmetricException("BigDecimalPolynomial:Multiply", "Number of coefficients must be the same!", new FormatException());
            }

            BigIntPolynomial poly1 = new BigIntPolynomial(Coeffs.Length);

            for (int i = 0; i < Coeffs.Length; i++)
            {
                poly1.Coeffs[i] = Coeffs[i].UnScaledValue;
            }

            int scale = Coeffs[0].Scale;

            BigIntPolynomial     cBigInt = poly1.MultBig(Factor);
            BigDecimalPolynomial c       = new BigDecimalPolynomial(cBigInt.Coeffs.Length);

            for (int i = 0; i < c.Coeffs.Length; i++)
            {
                c.Coeffs[i] = new BigDecimal(cBigInt.Coeffs[i], scale);
            }

            return(c);
        }
        /// <summary>
        /// Multiplies the polynomial by an <c>IntegerPolynomial</c>,
        /// taking the indices mod <c>N</c>.
        /// </summary>
        ///
        /// <param name="Factor">A polynomial factor</param>
        ///
        /// <returns>The product of the two polynomials</returns>
        public BigIntPolynomial Multiply(BigIntPolynomial Factor)
        {
            BigIntPolynomial c = m_f1.Multiply(Factor);

            c = m_f2.Multiply(c);
            c.Add(m_f3.Multiply(Factor));

            return(c);
        }
        private BigIntPolynomial MultRecursive(BigIntPolynomial Factor)
        {
            // Karatsuba multiplication
            BigInteger[] a = Coeffs;
            BigInteger[] b = Factor.Coeffs;

            int n = Factor.Coeffs.Length;

            if (n <= 1)
            {
                BigInteger[] c = (BigInteger[])Coeffs.Clone();
                for (int i = 0; i < Coeffs.Length; i++)
                {
                    c[i] = c[i].Multiply(Factor.Coeffs[0]);
                }

                return(new BigIntPolynomial(c));
            }
            else
            {
                int n1 = n / 2;

                BigIntPolynomial a1 = new BigIntPolynomial(a.CopyOf(n1));
                BigIntPolynomial a2 = new BigIntPolynomial(a.CopyOfRange(n1, n));
                BigIntPolynomial b1 = new BigIntPolynomial(b.CopyOf(n1));
                BigIntPolynomial b2 = new BigIntPolynomial(b.CopyOfRange(n1, n));

                BigIntPolynomial A = (BigIntPolynomial)a1.Clone();
                A.Add(a2);
                BigIntPolynomial B = (BigIntPolynomial)b1.Clone();
                B.Add(b2);

                BigIntPolynomial c1 = a1.MultRecursive(b1);
                BigIntPolynomial c2 = a2.MultRecursive(b2);
                BigIntPolynomial c3 = A.MultRecursive(B);
                c3.Subtract(c1);
                c3.Subtract(c2);
                BigIntPolynomial c = new BigIntPolynomial(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] = c.Coeffs[n1 + i].Add(c3.Coeffs[i]);
                }
                for (int i = 0; i < c2.Coeffs.Length; i++)
                {
                    c.Coeffs[2 * n1 + i] = c.Coeffs[2 * n1 + i].Add(c2.Coeffs[i]);
                }

                return(c);
            }
        }
Example #4
0
        /// <summary>
        /// Rounds all coefficients to the nearest integer
        /// </summary>
        ///
        /// <returns>A new polynomial with <c>BigInteger</c> coefficients</returns>
        public BigIntPolynomial Round()
        {
            int N = Coeffs.Length;
            BigIntPolynomial p = new BigIntPolynomial(N);

            for (int i = 0; i < N; i++)
            {
                p.Coeffs[i] = Coeffs[i].SetScale(0, RoundingModes.HalfEven).ToBigInteger();
            }

            return(p);
        }
Example #5
0
        /// <summary>
        /// Adds another polynomial which can have a different number of coefficients.
        /// </summary>
        /// 
        /// <param name="B">The polynomial to add</param>
        public void Add(BigIntPolynomial B)
        {
            if (B.Coeffs.Length > Coeffs.Length)
            {
                int N = Coeffs.Length;
                Coeffs = Coeffs.CopyOf(B.Coeffs.Length);

                for (int i = N; i < Coeffs.Length; i++)
                    Coeffs[i] = BigInteger.Zero;
            }

            for (int i = 0; i < B.Coeffs.Length; i++)
                Coeffs[i] = Coeffs[i].Add(B.Coeffs[i]);
        }
Example #6
0
        /// <summary>
        /// Multiplies the polynomial by a <c>BigIntPolynomial</c>, taking the indices mod N. Does not
        /// change this polynomial but returns the result as a new polynomial.
        /// <para>Both polynomials must have the same number of coefficients.</para>
        /// </summary>
        ///
        /// <param name="Factor">The polynomial to multiply by</param>
        ///
        /// <returns>The product of the two polynomials</returns>
        public BigIntPolynomial Multiply(BigIntPolynomial Factor)
        {
            BigInteger[] b = Factor.Coeffs;

            if (b.Length != m_N)
            {
                throw new CryptoAsymmetricException("SparseTernaryPolynomial:Multiply", "Number of coefficients must be the same!", new FormatException());
            }

            BigInteger[] c = new BigInteger[m_N];
            for (int i = 0; i < m_N; i++)
            {
                c[i] = BigInteger.Zero;
            }

            for (int i = 0; i < m_ones.Length; i++)
            {
                int j = m_N - 1 - m_ones[i];
                for (int k = m_N - 1; k >= 0; k--)
                {
                    c[k] = c[k].Add(b[j]);
                    j--;

                    if (j < 0)
                    {
                        j = m_N - 1;
                    }
                }
            }

            for (int i = 0; i < m_negOnes.Length; i++)
            {
                int j = m_N - 1 - m_negOnes[i];
                for (int k = m_N - 1; k >= 0; k--)
                {
                    c[k] = c[k].Subtract(b[j]);
                    j--;

                    if (j < 0)
                    {
                        j = m_N - 1;
                    }
                }
            }

            return(new BigIntPolynomial(c));
        }
        /// <summary>
        /// Test the validity of the BigIntPolynomial implementation
        /// </summary>
        /// 
        /// <returns>State</returns>
        public string Test()
        {
            try
            {
                BigIntPolynomial a = new BigIntPolynomial(new IntegerPolynomial(new int[] { 4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5 }));
                BigIntPolynomial b = new BigIntPolynomial(new IntegerPolynomial(new int[] { -6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1 }));
                BigIntPolynomial expected = new BigIntPolynomial(new IntegerPolynomial(new int[] { 2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34 }));
                if (!Compare.AreEqual(expected.Coeffs, a.MultSmall(b).Coeffs))
                    throw new Exception("BigIntPolynomial known value test failed!");
                OnProgress(new TestEventArgs("Passed round 1 BigIntPolynomial known value"));

                if (!Compare.AreEqual(expected.Coeffs, a.MultBig(b).Coeffs))
                    throw new Exception("BigIntPolynomial known value test failed!");
                OnProgress(new TestEventArgs("Passed round 2 BigIntPolynomial known value"));

                Random rng = new Random();
                BigInteger[] aCoeffs = new BigInteger[10 + rng.Next(50)];
                BigInteger[] bCoeffs = new BigInteger[aCoeffs.Length];

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < aCoeffs.Length; j++)
                    {
                        byte[] aArr = new byte[600 + rng.Next(100)];
                        rng.NextBytes(aArr);
                        aCoeffs[j] = new BigInteger(aArr);
                        byte[] bArr = new byte[600 + rng.Next(100)];
                        rng.NextBytes(bArr);
                        bCoeffs[j] = new BigInteger(bArr);
                    }
                    a = new BigIntPolynomial(aCoeffs);
                    b = new BigIntPolynomial(bCoeffs);
                    if (!Compare.AreEqual(a.MultSmall(b).Coeffs, a.MultBig(b).Coeffs))
                        throw new Exception("BigIntPolynomial coefficient comparison test failed!");
                }
                OnProgress(new TestEventArgs("Passed BigIntPolynomial coefficient comparison"));

                return SUCCESS;
            }
            catch (Exception Ex)
            {
                string message = Ex.Message == null ? "" : Ex.Message;
                throw new Exception(FAILURE + message);
            }
        }
Example #8
0
        /// <summary>
        /// Calculates a <c>rho</c> modulo <c>m1*m2</c> from two resultants whose
        /// <c>rho</c>s are modulo <c>m1</c> and <c>m2</c>.
        /// <para><c>res</c> is set to <c>null</c>.</para>
        /// </summary>
        ///
        /// <param name="ModRes1">M1 resultant</param>
        /// <param name="ModRes2">M2 resultant</param>
        ///
        /// <returns><c>Rho</c> modulo <c>modRes1.modulus * modRes2.modulus</c>, and <c>null</c> for <c>res</c></returns>
        public static ModularResultant CombineRho(ModularResultant ModRes1, ModularResultant ModRes2)
        {
            BigInteger      mod1 = ModRes1.m_modulus;
            BigInteger      mod2 = ModRes2.m_modulus;
            BigInteger      prod = mod1.Multiply(mod2);
            BigIntEuclidean er   = BigIntEuclidean.Calculate(mod2, mod1);

            BigIntPolynomial rho1 = ModRes1.Rho.Clone();

            rho1.Multiply(er.X.Multiply(mod2));
            BigIntPolynomial rho2 = ModRes2.Rho.Clone();

            rho2.Multiply(er.Y.Multiply(mod1));
            rho1.Add(rho2);
            rho1.Mod(prod);

            return(new ModularResultant(rho1, null, prod));
        }
        /// <summary>
        /// Adds another polynomial which can have a different number of coefficients.
        /// </summary>
        ///
        /// <param name="B">The polynomial to add</param>
        public void Add(BigIntPolynomial B)
        {
            if (B.Coeffs.Length > Coeffs.Length)
            {
                int N = Coeffs.Length;
                Coeffs = Coeffs.CopyOf(B.Coeffs.Length);

                for (int i = N; i < Coeffs.Length; i++)
                {
                    Coeffs[i] = BigInteger.Zero;
                }
            }

            for (int i = 0; i < B.Coeffs.Length; i++)
            {
                Coeffs[i] = Coeffs[i].Add(B.Coeffs[i]);
            }
        }
        /** tests mult(IntegerPolynomial) and mult(BigIntPolynomial) */
        private void MultTest()
        {
            CSPRng rng = new CSPRng();
            SparseTernaryPolynomial p1 = SparseTernaryPolynomial.GenerateRandom(1000, 500, 500, rng);
            IntegerPolynomial p2 = PolynomialGeneratorForTesting.generateRandom(1000);

            IntegerPolynomial prod1 = p1.Multiply(p2);
            prod1 = p1.Multiply(p2);
            IntegerPolynomial prod2 = p1.Multiply(p2);

            if (!Compare.Equals(prod1, prod2))
                throw new Exception("SparseTernaryPolynomial multiplication test failed!");

            BigIntPolynomial p3 = new BigIntPolynomial(p2);
            BigIntPolynomial prod3 = p1.Multiply(p3);

            if (!Compare.Equals(new BigIntPolynomial(prod1), prod3))
                throw new Exception("SparseTernaryPolynomial multiplication test failed!");
        }
        /// <summary>
        /// Multiplies the polynomial by another, taking the indices mod N.
        /// <para>Does not change this polynomial but returns the result as a new polynomial.
        /// Both polynomials must have the same number of coefficients.
        /// This method is designed for smaller polynomials and uses
        /// <a href="http://en.wikipedia.org/wiki/Karatsuba_algorithm">Karatsuba multiplication</a>.</para>
        /// </summary>
        ///
        /// <param name="Factor">he polynomial to multiply by</param>
        ///
        /// <returns>The product polynomial</returns>
        ///
        /// <exception cref="CryptoAsymmetricException">Throws if the two polynomials have a different number of coefficients</exception>
        public BigIntPolynomial MultSmall(BigIntPolynomial Factor)
        {
            int N = Coeffs.Length;

            if (Factor.Coeffs.Length != N)
            {
                throw new CryptoAsymmetricException("BigIntPolynomial:Multiply", "Number of coefficients must be the same!", new FormatException());
            }

            BigIntPolynomial c = MultRecursive(Factor);

            if (c.Coeffs.Length > N)
            {
                for (int k = N; k < c.Coeffs.Length; k++)
                {
                    c.Coeffs[k - N] = c.Coeffs[k - N].Add(c.Coeffs[k]);
                }
                c.Coeffs = c.Coeffs.CopyOf(N);
            }

            return(c);
        }
        private int[] ToIntArray(BigIntPolynomial A, int K)
        {
            int N    = A.Coeffs.Length;
            int sign = A.Coeffs[A.Degree()].Signum();

            int[] aInt = new int[N * K];

            for (int i = N - 1; i >= 0; i--)
            {
                int[] cArr = SchonhageStrassen.ToIntArray(A.Coeffs[i].Abs());

                if (A.Coeffs[i].Signum() * sign < 0)
                {
                    SubShifted(aInt, cArr, i * K);
                }
                else
                {
                    AddShifted(aInt, cArr, i * K);
                }
            }

            return(aInt);
        }
        /// <summary>
        /// Compare this big integer polynomial to another for equality
        /// </summary>
        ///
        /// <param name="Obj">Object to compare</param>
        ///
        /// <returns>True if equal, otherwise false</returns>
        public override bool Equals(Object Obj)
        {
            if (this == Obj)
            {
                return(true);
            }
            if (Obj == null)
            {
                return(false);
            }

            BigIntPolynomial other = (BigIntPolynomial)Obj;

            for (int i = 0; i < Coeffs.Length; i++)
            {
                if (!Coeffs[i].Equals(other.Coeffs[i]))
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Test the validity of the BigDecimalPolynomial implementation
        /// </summary>
        /// 
        /// <returns>State</returns>
        public string Test()
        {
            try
            {
                BigDecimalPolynomial a = CreateBigDecimalPolynomial(new int[] { 4, -1, 9, 2, 1, -5, 12, -7, 0, -9, 5 });
                BigIntPolynomial b = new BigIntPolynomial(new IntegerPolynomial(new int[] { -6, 0, 0, 13, 3, -2, -4, 10, 11, 2, -1 }));
                BigDecimalPolynomial c = a.Multiply(b);
                if(!Compare.AreEqual(c.Coeffs, CreateBigDecimalPolynomial(new int[] { 2, -189, 77, 124, -29, 0, -75, 124, -49, 267, 34 }).Coeffs))
                    throw new Exception("The BigDecimalPolynomial test failed!");
                // multiply a polynomial by its inverse modulo 2048 and check that the result is 1
                IntegerPolynomial d, dInv;
                CSPRng rng = new CSPRng();

                do
                {
                    d = DenseTernaryPolynomial.GenerateRandom(1001, 333, 334, rng);
                    dInv = d.InvertFq(2048);
                } while (dInv == null);

                d.Mod(2048);
                BigDecimalPolynomial e = CreateBigDecimalPolynomial(d.Coeffs);
                BigIntPolynomial f = new BigIntPolynomial(dInv);
                IntegerPolynomial g = new IntegerPolynomial(e.Multiply(f).Round());
                g.ModPositive(2048);

                if (!g.EqualsOne())
                    throw new Exception("The BigDecimalPolynomial test failed!");
                OnProgress(new TestEventArgs("Passed BigDecimalPolynomial tests"));

                return SUCCESS;
            }
            catch (Exception Ex)
            {
                string message = Ex.Message == null ? "" : Ex.Message;
                throw new Exception(FAILURE + message);
            }
        }
Example #15
0
 /// <summary>
 /// Stores the Rho and resultant values
 /// </summary>
 ///
 /// <param name="Rho">A polynomial such that <c>res = rho*this + t*(x^n-1) for some integer t</c></param>
 /// <param name="Res">A polynomial with <c>x^n-1</c> </param>
 public Resultant(BigIntPolynomial Rho, BigInteger Res)
 {
     this.Rho = Rho;
     this.Res = Res;
 }
        /// <summary>
        /// Rounds all coefficients to the nearest integer
        /// </summary>
        /// 
        /// <returns>A new polynomial with <c>BigInteger</c> coefficients</returns>
        public BigIntPolynomial Round()
        {
            int N = Coeffs.Length;
            BigIntPolynomial p = new BigIntPolynomial(N);

            for (int i = 0; i < N; i++)
                p.Coeffs[i] = Coeffs[i].SetScale(0, RoundingModes.HalfEven).ToBigInteger();

            return p;
        }
        /// <summary>
        /// Multiplies the polynomial by another, taking the indices mod N.
        /// <para>Does not change this polynomial but returns the result as a new polynomial.
        /// Both polynomials must have the same number of coefficients.
        /// This method uses the <a href="http://en.wikipedia.org/wiki/Schönhage–Strassen_algorithm"/> 
        /// Schönhage–Strassen algorithm.</para>
        /// </summary>
        /// 
        /// <param name="Factor">Multiplication factor</param>
        /// 
        /// <returns>Multiplied polynomial</returns>
        /// 
        /// <exception cref="NTRUException">Thrown if the two polynomials differ in the number of coefficients</exception>
        public BigDecimalPolynomial Multiply(BigIntPolynomial Factor)
        {
            if (Factor.Coeffs.Length != Coeffs.Length)
                throw new CryptoAsymmetricException("BigDecimalPolynomial:Multiply", "Number of coefficients must be the same!", new FormatException());

            BigIntPolynomial poly1 = new BigIntPolynomial(Coeffs.Length);

            for (int i = 0; i < Coeffs.Length; i++)
                poly1.Coeffs[i] = Coeffs[i].UnScaledValue;

            int scale = Coeffs[0].Scale;

            BigIntPolynomial cBigInt = poly1.MultBig(Factor);
            BigDecimalPolynomial c = new BigDecimalPolynomial(cBigInt.Coeffs.Length);

            for (int i = 0; i < c.Coeffs.Length; i++)
                c.Coeffs[i] = new BigDecimal(cBigInt.Coeffs[i], scale);

            return c;
        }
        /// <summary>
        /// Multiplies the polynomial by a <c>BigIntPolynomial</c>, taking the indices mod N. Does not
        /// change this polynomial but returns the result as a new polynomial.
        /// <para>Both polynomials must have the same number of coefficients.</para>
        /// </summary>
        /// 
        /// <param name="Factor">The polynomial to multiply by</param>
        /// 
        /// <returns>The product of the two polynomials</returns>
        public BigIntPolynomial Multiply(BigIntPolynomial Factor)
        {
            BigInteger[] b = Factor.Coeffs;

            if (b.Length != _N)
                throw new CryptoAsymmetricException("SparseTernaryPolynomial:Multiply", "Number of coefficients must be the same!", new FormatException());

            BigInteger[] c = new BigInteger[_N];
            for (int i = 0; i < _N; i++)
                c[i] = BigInteger.Zero;

            for (int i = 0; i < _ones.Length; i++)
            {
                int j = _N - 1 - _ones[i];
                for (int k = _N - 1; k >= 0; k--)
                {
                    c[k] = c[k].Add(b[j]);
                    j--;

                    if (j < 0)
                        j = _N - 1;
                }
            }

            for (int i = 0; i < _negOnes.Length; i++)
            {
                int j = _N - 1 - _negOnes[i];
                for (int k = _N - 1; k >= 0; k--)
                {
                    c[k] = c[k].Subtract(b[j]);
                    j--;

                    if (j < 0)
                        j = _N - 1;
                }
            }

            return new BigIntPolynomial(c);
        }
Example #19
0
        private int[] ToIntArray(BigIntPolynomial A, int K)
        {
            int N = A.Coeffs.Length;
            int sign = A.Coeffs[A.Degree()].Signum();
            int[] aInt = new int[N * K];

            for (int i = N - 1; i >= 0; i--)
            {
                int[] cArr = SchonhageStrassen.ToIntArray(A.Coeffs[i].Abs());

                if (A.Coeffs[i].Signum() * sign < 0)
                    SubShifted(aInt, cArr, i * K);
                else
                    AddShifted(aInt, cArr, i * K);
            }

            return aInt;
        }
Example #20
0
        private BigIntPolynomial MultRecursive(BigIntPolynomial Factor)
        {
            // Karatsuba multiplication
            BigInteger[] a = Coeffs;
            BigInteger[] b = Factor.Coeffs;

            int n = Factor.Coeffs.Length;
            if (n <= 1)
            {
                BigInteger[] c = (BigInteger[])Coeffs.Clone();
                for (int i = 0; i < Coeffs.Length; i++)
                    c[i] = c[i].Multiply(Factor.Coeffs[0]);

                return new BigIntPolynomial(c);
            }
            else
            {
                int n1 = n / 2;

                BigIntPolynomial a1 = new BigIntPolynomial(a.CopyOf(n1));
                BigIntPolynomial a2 = new BigIntPolynomial(a.CopyOfRange(n1, n));
                BigIntPolynomial b1 = new BigIntPolynomial(b.CopyOf(n1));
                BigIntPolynomial b2 = new BigIntPolynomial(b.CopyOfRange(n1, n));

                BigIntPolynomial A = (BigIntPolynomial)a1.Clone();
                A.Add(a2);
                BigIntPolynomial B = (BigIntPolynomial)b1.Clone();
                B.Add(b2);

                BigIntPolynomial c1 = a1.MultRecursive(b1);
                BigIntPolynomial c2 = a2.MultRecursive(b2);
                BigIntPolynomial c3 = A.MultRecursive(B);
                c3.Subtract(c1);
                c3.Subtract(c2);
                BigIntPolynomial c = new BigIntPolynomial(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] = c.Coeffs[n1 + i].Add(c3.Coeffs[i]);
                for (int i = 0; i < c2.Coeffs.Length; i++)
                    c.Coeffs[2 * n1 + i] = c.Coeffs[2 * n1 + i].Add(c2.Coeffs[i]);

                return c;
            }
        }
        /// <summary>
        /// Multiplies the polynomial by another, taking the indices mod N.
        /// <para>Does not change this polynomial but returns the result as a new polynomial.
        /// Both polynomials must have the same number of coefficients.
        /// This method is designed for large polynomials and uses Schönhage-Strassen multiplication
        /// in combination with <a href="http://en.wikipedia.org/wiki/Kronecker_substitution">Kronecker substitution</a>.
        /// See <a href="http://math.stackexchange.com/questions/58946/karatsuba-vs-schonhage-strassen-for-multiplication-of-polynomials#58955">here</a> for details.</para>
        /// </summary>
        ///
        /// <param name="Factor">The polynomial to multiply by</param>
        ///
        /// <returns>The product polynomial</returns>
        public BigIntPolynomial MultBig(BigIntPolynomial Factor)
        {
            int N = Coeffs.Length;

            // determine #bits needed per coefficient
            int logMinDigits = 32 - IntUtils.NumberOfLeadingZeros(N - 1);
            int maxLengthA   = 0;

            for (int i = 0; i < Coeffs.Length; i++)
            {
                BigInteger coeff = Coeffs[i];
                maxLengthA = Math.Max(maxLengthA, coeff.BitLength);
            }

            int maxLengthB = 0;

            for (int i = 0; i < Factor.Coeffs.Length; i++)
            {
                BigInteger coeff = Factor.Coeffs[i];
                maxLengthB = Math.Max(maxLengthB, coeff.BitLength);
            }

            int k = logMinDigits + maxLengthA + maxLengthB + 1; // in bits

            k = (k + 31) / 32;                                  // in ints

            // encode each polynomial into an int[]
            int aDeg = Degree();
            int bDeg = Factor.Degree();

            if (aDeg < 0 || bDeg < 0)
            {
                return(new BigIntPolynomial(N));   // return zero
            }
            int[] aInt = ToIntArray(this, k);
            int[] bInt = ToIntArray(Factor, k);
            int[] cInt = SchonhageStrassen.Multiply(aInt, bInt);
            // decode poly coefficients from the product
            BigInteger       _2k   = BigInteger.One.ShiftLeft(k * 32);
            BigIntPolynomial cPoly = new BigIntPolynomial(N);

            for (int i = 0; i < 2 * N - 1; i++)
            {
                int[]      coeffInt = cInt.CopyOfRange(i * k, (i + 1) * k);
                BigInteger coeff    = SchonhageStrassen.ToBigInteger(coeffInt);
                if (coeffInt[k - 1] < 0)
                {   // if coeff > 2^(k-1)
                    coeff = coeff.Subtract(_2k);
                    // add 2^k to cInt which is the same as subtracting coeff
                    bool carry = false;
                    int  cIdx  = (i + 1) * k;

                    do
                    {
                        cInt[cIdx]++;
                        carry = cInt[cIdx] == 0;
                        cIdx++;
                    } while (carry);
                }
                cPoly.Coeffs[i % N] = cPoly.Coeffs[i % N].Add(coeff);
            }

            int aSign = Coeffs[aDeg].Signum();
            int bSign = Factor.Coeffs[bDeg].Signum();

            if (aSign * bSign < 0)
            {
                for (int i = 0; i < N; i++)
                {
                    cPoly.Coeffs[i] = cPoly.Coeffs[i].Negate();
                }
            }

            return(cPoly);
        }
Example #22
0
        /// <summary>
        /// Multiplies the polynomial by another, taking the indices mod N.
        /// <para>Does not change this polynomial but returns the result as a new polynomial.
        /// Both polynomials must have the same number of coefficients.
        /// This method is designed for large polynomials and uses Schönhage-Strassen multiplication
        /// in combination with <a href="http://en.wikipedia.org/wiki/Kronecker_substitution">Kronecker substitution</a>.
        /// See <a href="http://math.stackexchange.com/questions/58946/karatsuba-vs-schonhage-strassen-for-multiplication-of-polynomials#58955">here</a> for details.</para>
        /// </summary>
        /// 
        /// <param name="Factor">The polynomial to multiply by</param>
        /// 
        /// <returns>The product polynomial</returns>
        public BigIntPolynomial MultBig(BigIntPolynomial Factor)
        {
            int N = Coeffs.Length;

            // determine #bits needed per coefficient
            int logMinDigits = 32 - IntUtils.NumberOfLeadingZeros(N - 1);
            int maxLengthA = 0;

            for (int i = 0; i < Coeffs.Length; i++)
            {
                BigInteger coeff = Coeffs[i];
                maxLengthA = Math.Max(maxLengthA, coeff.BitLength);
            }

            int maxLengthB = 0;
            for (int i = 0; i < Factor.Coeffs.Length; i++)
            {
                BigInteger coeff = Factor.Coeffs[i];
                maxLengthB = Math.Max(maxLengthB, coeff.BitLength);
            }

            int k = logMinDigits + maxLengthA + maxLengthB + 1;   // in bits
            k = (k + 31) / 32;   // in ints

            // encode each polynomial into an int[]
            int aDeg = Degree();
            int bDeg = Factor.Degree();

            if (aDeg < 0 || bDeg < 0)
                return new BigIntPolynomial(N);   // return zero

            int[] aInt = ToIntArray(this, k);
            int[] bInt = ToIntArray(Factor, k);
            int[] cInt = SchonhageStrassen.Multiply(aInt, bInt);
            // decode poly coefficients from the product
            BigInteger _2k = BigInteger.One.ShiftLeft(k * 32);
            BigIntPolynomial cPoly = new BigIntPolynomial(N);

            for (int i = 0; i < 2 * N - 1; i++)
            {
                int[] coeffInt = cInt.CopyOfRange(i * k, (i + 1) * k);
                BigInteger coeff = SchonhageStrassen.ToBigInteger(coeffInt);
                if (coeffInt[k - 1] < 0)
                {   // if coeff > 2^(k-1)
                    coeff = coeff.Subtract(_2k);
                    // add 2^k to cInt which is the same as subtracting coeff
                    bool carry = false;
                    int cIdx = (i + 1) * k;

                    do
                    {
                        cInt[cIdx]++;
                        carry = cInt[cIdx] == 0;
                        cIdx++;
                    } while (carry);
                }
                cPoly.Coeffs[i % N] = cPoly.Coeffs[i % N].Add(coeff);
            }

            int aSign = Coeffs[aDeg].Signum();
            int bSign = Factor.Coeffs[bDeg].Signum();

            if (aSign * bSign < 0)
            {
                for (int i = 0; i < N; i++)
                    cPoly.Coeffs[i] = cPoly.Coeffs[i].Negate();
            }

            return cPoly;
        }
Example #23
0
        /// <summary>
        /// Multiplies the polynomial by an <c>IntegerPolynomial</c>,
        /// taking the indices mod <c>N</c>.
        /// </summary>
        /// 
        /// <param name="Factor">A polynomial factor</param>
        /// 
        /// <returns>The product of the two polynomials</returns>
        public BigIntPolynomial Multiply(BigIntPolynomial Factor)
        {
            BigIntPolynomial c = _f1.Multiply(Factor);
            c = _f2.Multiply(c);
            c.Add(_f3.Multiply(Factor));

            return c;
        }
Example #24
0
 /// <summary>
 /// Instantiate the class
 /// </summary>
 ///
 /// <param name="Rho">Rho code</param>
 /// <param name="Res">Resultant</param>
 /// <param name="Modulus">Modulus</param>
 public ModularResultant(BigIntPolynomial Rho, BigInteger Res, BigInteger Modulus) :
     base(Rho, Res)
 {
     this.m_modulus = Modulus;
 }
        /// <summary>
        /// Constructs a <c>IntegerPolynomial</c> from a <c>BigIntPolynomial</c>. The two polynomials are independent of each other
        /// </summary>
        /// 
        /// <param name="P">The original polynomial</param>
        public IntegerPolynomial(BigIntPolynomial P)
        {
            Coeffs = new int[P.Coeffs.Length];

            for (int i = 0; i < P.Coeffs.Length; i++)
                Coeffs[i] = P.Coeffs[i].ToInt32();
        }
        // verifies that res=rho*a mod x^n-1 mod p
        private void VerifyResultant(IntegerPolynomial a, Resultant r, int p)
        {
            BigIntPolynomial b = new BigIntPolynomial(a).MultSmall(r.Rho);
            b.Mod(BigInteger.ValueOf(p));

            for (int j = 1; j < b.Coeffs.Length - 1; j++)
            {
                if (!Compare.Equals(BigInteger.Zero, b.Coeffs[j]))
                    throw new Exception("IntegerPolynomialTest VerifyResultant test failed!");
            }
            if (r.Res.Equals(BigInteger.Zero))
            {
                if (!Compare.Equals(BigInteger.Zero, b.Coeffs[0].Subtract(b.Coeffs[b.Coeffs.Length - 1])))
                    throw new Exception("IntegerPolynomialTest VerifyResultant test failed!");
            }
            else
            {
                if (!Compare.Equals(BigInteger.Zero, (b.Coeffs[0].Subtract(b.Coeffs[b.Coeffs.Length - 1]).Subtract(r.Res).Mod(BigInteger.ValueOf(p)))))
                    throw new Exception("IntegerPolynomialTest VerifyResultant test failed!");
            }

            if (!Compare.Equals(BigInteger.Zero, b.Coeffs[0].Subtract(r.Res).Subtract(b.Coeffs[b.Coeffs.Length - 1].Negate()).Mod(BigInteger.ValueOf(p))))
                throw new Exception("IntegerPolynomialTest VerifyResultant test failed!");
        }
 /// <summary>
 /// Multiplies the polynomial with another, taking the indices mod N
 /// </summary>
 /// 
 /// <param name="Factor">The polynomial factor</param>
 /// 
 /// <returns>Multiplied polynomial</returns>
 public BigIntPolynomial Multiply(BigIntPolynomial Factor)
 {
     return new BigIntPolynomial(this).MultSmall(Factor);
 }
Example #28
0
        /// <summary>
        /// Multiplies the polynomial by another, taking the indices mod N.
        /// <para>Does not change this polynomial but returns the result as a new polynomial.
        /// Both polynomials must have the same number of coefficients.
        /// This method is designed for smaller polynomials and uses 
        /// <a href="http://en.wikipedia.org/wiki/Karatsuba_algorithm">Karatsuba multiplication</a>.</para>
        /// </summary>
        /// 
        /// <param name="Factor">he polynomial to multiply by</param>
        /// 
        /// <returns>The product polynomial</returns>
        /// 
        /// <exception cref="CryptoAsymmetricException">Throws if the two polynomials have a different number of coefficients</exception>
        public BigIntPolynomial MultSmall(BigIntPolynomial Factor)
        {
            int N = Coeffs.Length;

            if (Factor.Coeffs.Length != N)
                throw new CryptoAsymmetricException("BigIntPolynomial:Multiply", "Number of coefficients must be the same!", new FormatException());

            BigIntPolynomial c = MultRecursive(Factor);

            if (c.Coeffs.Length > N)
            {
                for (int k = N; k < c.Coeffs.Length; k++)
                    c.Coeffs[k - N] = c.Coeffs[k - N].Add(c.Coeffs[k]);
                c.Coeffs = c.Coeffs.CopyOf(N);
            }

            return c;
        }
Example #29
0
 /// <summary>
 /// Stores the Rho and resultant values
 /// </summary>
 /// 
 /// <param name="Rho">A polynomial such that <c>res = rho*this + t*(x^n-1) for some integer t</c></param>
 /// <param name="Res">A polynomial with <c>x^n-1</c> </param>
 public Resultant(BigIntPolynomial Rho, BigInteger Res)
 {
     this.Rho = Rho;
     this.Res = Res;
 }
Example #30
0
 /// <summary>
 /// Instantiate the class
 /// </summary>
 /// 
 /// <param name="Rho">Rho code</param>
 /// <param name="Res">Resultant</param>
 /// <param name="Modulus">Modulus</param>
 public ModularResultant(BigIntPolynomial Rho, BigInteger Res, BigInteger Modulus)
     : base(Rho, Res)
 {
     this._modulus = Modulus;
 }