Example #1
0
        private void TestAddModFn()
        {
            Random rng = new Random();
            int    n   = 5 + rng.Next(10);
            int    len = 1 << (n + 1 - 5);

            int[] aArr = new int[len];
            for (int i = 0; i < aArr.Length; i++)
            {
                aArr[i] = rng.Next();
            }

            BigInteger a = SchonhageStrassen.ToBigInteger(aArr);

            int[] bArr = new int[len];
            for (int i = 0; i < bArr.Length; i++)
            {
                bArr[i] = rng.Next();
            }

            BigInteger b = SchonhageStrassen.ToBigInteger(bArr);

            SchonhageStrassen.AddModFn(aArr, bArr);
            SchonhageStrassen.ModFn(aArr);
            BigInteger Fn = BigInteger.ValueOf(2).Pow(1 << n).Add(BigInteger.One);
            BigInteger c  = a.Add(b).Mod(Fn);

            if (!Compare.Equals(c, SchonhageStrassen.ToBigInteger(aArr)))
            {
                throw new Exception("SchönhageStrassen:AddModFn test has failed!");
            }
        }
Example #2
0
        private void TestToBigInteger()
        {
            Random rng = new Random();

            byte[] a = new byte[1 + rng.Next(100)];
            rng.NextBytes(a);
            int[]      b = SchonhageStrassen.ToIntArray(new BigInteger(1, a));
            BigInteger c = SchonhageStrassen.ToBigInteger(b);

            if (!Compare.Equals(new BigInteger(1, a), c))
            {
                throw new Exception("SchönhageStrassen:ToBigInteger test has 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 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);
        }