Пример #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="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 NTRUException("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 = _f1.Multiply(Factor);

            c = _f2.Multiply(c);
            c.Add(_f3.Multiply(Factor));

            return(c);
        }
Пример #3
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);
            }
        }
Пример #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);
        }
Пример #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]);
        }
        /// <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 NTRUException("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));
        }
Пример #7
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]);
            }
        }
Пример #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._modulus;
            BigInteger      mod2 = ModRes2._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));
        }
Пример #9
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="NTRUException">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 NTRUException("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);
        }
Пример #10
0
        /// <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);
        }
Пример #11
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);
        }
Пример #12
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="NTRUException">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 NTRUException("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;
        }
Пример #13
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;
        }
Пример #14
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;
 }
Пример #15
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 != _N)
                throw new NTRUException("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);
        }
Пример #16
0
 /// <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);
 }
Пример #17
0
        /// <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();
        }
Пример #18
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="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 NTRUException("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;
        }
Пример #19
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;
 }
Пример #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;
            }
        }
Пример #21
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;
        }
Пример #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);
        }
Пример #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;
        }
Пример #24
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;
 }
Пример #25
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;
        }
Пример #26
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;
 }