Пример #1
0
        private void TestAddShifted()
        {
            int[] a = new int[] { 1522485231, 1933026569 };
            int[] b = new int[] { 233616584 };
            SchonhageStrassen.AddShifted(a, b, 1);
            if (!Compare.AreEqual(a, new int[] { 1522485231, -2128324143 }))
            {
                throw new Exception("SchönhageStrassen:AddShifted test has failed!");
            }

            a = new int[] { 796591014, -1050856894, 1260609160 };
            b = new int[] { 2093350350, -1822145887 };
            SchonhageStrassen.AddShifted(a, b, 1);
            if (!Compare.AreEqual(a, new int[] { 796591014, 1042493456, -561536726 }))
            {
                throw new Exception("SchönhageStrassen:AddShifted test has failed!");
            }

            a = new int[] { -1135845471, 1374513806, 391471507 };
            b = new int[] { 980775637, 1136222341 };
            SchonhageStrassen.AddShifted(a, b, 1);
            if (!Compare.AreEqual(a, new int[] { -1135845471, -1939677853, 1527693848 }))
            {
                throw new Exception("SchönhageStrassen:AddShifted test has failed!");
            }
        }
Пример #2
0
 private void TestMultModFn()
 {
     if (!Compare.AreEqual(new int[] { 1713569892, -280255914 }, SchonhageStrassen.MultModFn(new int[] { -142491638, 0 }, new int[] { -142491638, 0 })))
     {
         throw new Exception("SchönhageStrassen:MultModFn test has failed!");
     }
 }
Пример #3
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!");
            }
        }
Пример #4
0
 private void TestAppendBits()
 {
     int[] a = new int[] { 3615777, 0 };
     SchonhageStrassen.AppendBits(a, 22, new int[] { -77, 61797 }, 1, 13);
     if (!Compare.AreEqual(new int[] { 1500982305, 4 }, a))
     {
         throw new Exception("SchönhageStrassen:AppendBits test has failed!");
     }
 }
Пример #5
0
 private void TestSubModPow2()
 {
     int[] a = new int[] { 3844, 0, 0 };
     int[] b = new int[] { 627199739, 1091992276, 2332 };
     SchonhageStrassen.SubModPow2(a, b, 12);
     if (!Compare.AreEqual(new int[] { 9, 0, 0 }, a))
     {
         throw new Exception("SchönhageStrassen:SubModPow2 test has failed!");
     }
 }
Пример #6
0
        private void TestMult(int[] a, int[] b)
        {
            int[] cSimple   = SchonhageStrassen.MultSimple(a, b);
            int[] cKara     = SchonhageStrassen.MultKaratsuba(a, b);
            int   maxLength = Math.Max(cSimple.Length, cKara.Length);

            if (!Compare.AreEqual(cSimple.CopyOf(maxLength), cKara.CopyOf(maxLength)))
            {
                throw new Exception("SchönhageStrassen:Multiply test has failed!");
            }
        }
Пример #7
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!");
            }
        }
Пример #8
0
        private void TestModFn()
        {
            int[] a = new int[] { 50593286, 151520511 };
            SchonhageStrassen.ModFn(a);
            if (!Compare.AreEqual(new int[] { -100927224, 0 }, a))
            {
                throw new Exception("SchönhageStrassen:TestModFn test has failed!");
            }

            a = new int[] { 1157041776, -1895306073, -1094584616, -218513495 };
            SchonhageStrassen.ModFn(a);
            if (!Compare.AreEqual(new int[] { -2043340903, -1676792579, 0, 0 }, a))
            {
                throw new Exception("SchönhageStrassen:TestModFn test has failed!");
            }
        }
Пример #9
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);
        }
Пример #10
0
        //verifies idft(dft(a)) = a
        private void TestInversion()
        {
            Random rng = new Random();

            int m           = 7 + rng.Next(10);
            int n           = m / 2 + 1;
            int numElements = m % 2 == 0 ? 1 << n : 1 << (n + 1);

            numElements /= 2;

            int[][] a = ArrayUtils.CreateJagged <int[][]>(numElements, 1 << (n + 1 - 5));
            for (int i = 0; i < a.Length; i++)
            {
                for (int j = 0; j < a[i].Length; j++)
                {
                    a[i][j] = rng.Next();
                }
            }
            SchonhageStrassen.ModFn(a);

            int[][] aOrig = new int[a.Length][];
            for (int i = 0; i < a.Length; i++)
            {
                aOrig[i] = (int[])a[i].Clone();
            }
            SchonhageStrassen.Dft(a, m, n);
            SchonhageStrassen.Idft(a, m, n);
            SchonhageStrassen.ModFn(a);
            for (int j = 0; j < aOrig.Length; j++)
            {
                if (!Compare.AreEqual(aOrig[j], a[j]))
                {
                    throw new Exception("SchönhageStrassen:Inversion test has failed!");
                }
            }
        }
Пример #11
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);
        }
Пример #12
0
        private void TestMult()
        {
            TestMult(BigInteger.ValueOf(0), BigInteger.ValueOf(0));
            TestMult(BigInteger.ValueOf(100), BigInteger.ValueOf(100));
            TestMult(BigInteger.ValueOf(-394786896548787L), BigInteger.ValueOf(604984572698687L));
            TestMult(BigInteger.ValueOf(415338904376L), BigInteger.ValueOf(527401434558L));
            TestMult(new BigInteger("9145524700683826415"), new BigInteger("1786442289234590209543"));

            BigInteger pow19_1 = BigInteger.ValueOf(1).ShiftLeft((1 << 19) - 1); // 2^(2^19-1)
            BigInteger pow20_2 = BigInteger.ValueOf(1).ShiftLeft((1 << 20) - 2); // 2^(2^20-2)
            BigInteger pow19   = BigInteger.ValueOf(1).ShiftLeft(1 << 19);       // 2^2^19
            BigInteger pow20   = BigInteger.ValueOf(1).ShiftLeft(1 << 20);       // 2^2^20

            if (!Compare.Equals(pow19_1.ShiftLeft(1024).Subtract(pow19_1), SchonhageStrassen.Multiply(pow19_1, BigInteger.ValueOf(1).ShiftLeft(1024).Subtract(BigInteger.One))))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            if (!Compare.Equals(pow20_2, SchonhageStrassen.Multiply(pow19_1, pow19_1)))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            if (!Compare.Equals(pow20_2.Subtract(pow19_1), SchonhageStrassen.Multiply(pow19_1, pow19_1.Subtract(BigInteger.One))))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            if (!Compare.Equals(pow20_2.Add(pow19_1), SchonhageStrassen.Multiply(pow19_1, pow19_1.Add(BigInteger.One))))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            if (!Compare.Equals(pow20, SchonhageStrassen.Multiply(pow19, pow19)))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            if (!Compare.Equals(pow20.Subtract(pow19), SchonhageStrassen.Multiply(pow19, pow19.Subtract(BigInteger.One))))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            if (!Compare.Equals(pow20.Add(pow19), SchonhageStrassen.Multiply(pow19, pow19.Add(BigInteger.One))))
            {
                throw new Exception("SchönhageStrassen:TestMult test has failed!");
            }
            OnProgress(new TestEventArgs("Passed Known Value Multiplication test"));

            Random rng = new Random();

            TestMult(BigInteger.ValueOf(rng.Next(1000000000) + 524288), BigInteger.ValueOf(rng.Next(1000000000) + 524288));
            TestMult(BigInteger.ValueOf((rng.Next() >> 1) + 1000), BigInteger.ValueOf((rng.Next() >> 1) + 1000));
            TestMult(BigInteger.ValueOf(rng.Next(1000000000) + 524288), BigInteger.ValueOf(rng.Next(1000000000) + 524288));
            TestMult(BigInteger.ValueOf((rng.Next() >> 1) + 1000), BigInteger.ValueOf((rng.Next() >> 1) + 1000));
            OnProgress(new TestEventArgs("Passed Random Multiplication test"));

            int aLength = 80000 + rng.Next(20000);
            int bLength = 80000 + rng.Next(20000);

            for (int i = 0; i < 2; i++)
            {
                byte[] aArr = new byte[aLength];
                rng.NextBytes(aArr);
                byte[] bArr = new byte[bLength];
                rng.NextBytes(bArr);
                BigInteger a = new BigInteger(aArr);
                BigInteger b = new BigInteger(bArr);
                TestMult(a, b);
                // double the length and test again so an even and an odd m is tested
                aLength *= 2;
                bLength *= 2;
            }
            OnProgress(new TestEventArgs("Passed Large Number Multiplication test"));
        }
Пример #13
0
 private void TestMult(BigInteger a, BigInteger b)
 {
     Compare.Equals(a.Multiply(b), SchonhageStrassen.Multiply(a, b));
 }
Пример #14
0
        private void TestCyclicShift()
        {
            int[] arr = new int[] { 16712450, -2139160576 };

            // test cyclicShiftLeft
            if (!Compare.AreEqual(new int[] { 33424901, 16646144 }, SchonhageStrassen.CyclicShiftLeftBits(arr, 1)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { -16579968, 2130706432 }, SchonhageStrassen.CyclicShiftLeftBits(arr, 8)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { 50495615, 255 }, SchonhageStrassen.CyclicShiftLeftBits(arr, 16)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { 41975552, 65283 }, SchonhageStrassen.CyclicShiftLeftBits(arr, 24)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { -2139160576, 16712450 }, SchonhageStrassen.CyclicShiftLeftBits(arr, 32)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(arr, SchonhageStrassen.CyclicShiftLeftBits(arr, 64)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }

            int[] arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr, 17);
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr2, 12);
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr2, 1);
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr2, 1);
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr2, 24);
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr2, 9);

            if (!Compare.AreEqual(arr, arr2))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            // test cyclicShiftRight
            if (!Compare.AreEqual(new int[] { 8356225, 1077903360 }, SchonhageStrassen.CyclicShiftRight(arr, 1)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { 65283, 41975552 }, SchonhageStrassen.CyclicShiftRight(arr, 8)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { 255, 50495615 }, SchonhageStrassen.CyclicShiftRight(arr, 16)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { 2130706432, -16579968 }, SchonhageStrassen.CyclicShiftRight(arr, 24)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { -2139160576, 16712450 }, SchonhageStrassen.CyclicShiftRight(arr, 32)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(new int[] { 41975552, 65283 }, SchonhageStrassen.CyclicShiftRight(arr, 40)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
            if (!Compare.AreEqual(arr, SchonhageStrassen.CyclicShiftRight(arr, 64)))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }

            arr2 = SchonhageStrassen.CyclicShiftRight(arr, 17);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 12);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 1);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 1);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 24);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 9);
            if (!Compare.AreEqual(arr, arr2))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }

            // shift left, then right by the same amount
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr, 22);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 22);
            if (!Compare.AreEqual(arr, arr2))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }

            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr, 9);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 14);
            arr2 = SchonhageStrassen.CyclicShiftRight(arr2, 9);
            arr2 = SchonhageStrassen.CyclicShiftLeftBits(arr2, 14);
            if (!Compare.AreEqual(arr, arr2))
            {
                throw new Exception("SchönhageStrassen:TestCyclicShift test has failed!");
            }
        }