Пример #1
0
        private static int CompareBaseBits(int bitsPerDigit, long n)
        {   //middle digit <= n * (base - 1) ^ 2 + [2^(128 - bitsPerDigit)] <= P - 1
            ulong[] value      = new ulong[1];
            ulong[] square     = new ulong[value.Length * 2];
            ulong[] multiplier = new ulong[square.Length];
            ulong[] result     = new ulong[square.Length * 2];
            ulong[] adder      = new ulong[result.Length];
            value[0]      = (1UL << bitsPerDigit) - 1;
            multiplier[0] = (ulong)n;
            AsmX64Operations.Square(value, square, value.Length);
            AsmX64Operations.Multiply(square, multiplier, result, square.Length);
            if (128 - bitsPerDigit < 64)
            {
                adder[0] = 1UL << (128 - bitsPerDigit);
            }
            else
            {
                adder[1] = 1UL << (64 - bitsPerDigit);
            }
            AsmX64Operations.Add(result, adder, result, 0, result.Length);

            if (result[2] > 0 || result[3] > 0 || (result[0] >= FourierPoint.PrimeModulo.Low && result[1] == ulong.MaxValue))
            {
                return(1);
            }
            if (result[0] == FourierPoint.PrimeModulo.Low - 1 && result[1] == ulong.MaxValue)
            {
                return(0);
            }
            return(-1);
        }
Пример #2
0
        public static bool UnitTest()
        {
            Random random = new Random(101);
            int    n      = 2048 / 64;

            ulong[] a   = new ulong[n];
            ulong[] b   = new ulong[n];
            ulong[] m   = new ulong[n];
            ulong[] am1 = new ulong[n];
            ulong[] am3 = new ulong[n];
            ulong[] c1  = new ulong[n * 2];
            ulong[] c2  = new ulong[n * 2];
            ulong[] c3  = new ulong[n * 2];
            ulong[] s0  = new ulong[n * 2];
            ulong[] s1  = new ulong[n * 2];
            ulong[] s2  = new ulong[n * 2];

            BigInteger a0, b0, m0;

            TimeSpan
                elapsedMontgomeryExpMod = TimeSpan.Zero,
                elapsedExpMod           = TimeSpan.Zero,
                elapsedBigIntegerExpMod = TimeSpan.Zero;
            bool ok = true;

            for (int iteration = 1; --iteration >= 0;)
            {
                getRandom(a, random);
                getRandom(b, random);
                getRandom(m, random); m[0] &= ulong.MaxValue - 1;
                a0 = new BigInteger(a.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray());
                b0 = new BigInteger(b.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray());
                m0 = new BigInteger(m.SelectMany(l => BitConverter.GetBytes(l)).Concat(Enumerable.Repeat((byte)0, 1)).ToArray());

                a.CopyTo(am1, 0);
                ExpMod(am1, b, m, n, 5);

                BigInteger am2 = BigInteger.Zero;
                elapsedBigIntegerExpMod += MeasureTime(() =>
                {
                    am2 = BigInteger.ModPow(a0, b0, m0);
                });
                var bytes1 = am1.SelectMany(l => BitConverter.GetBytes(l)).ToArray();
                var bytes2 = am2.ToByteArray();
                ok &= Enumerable.Range(0, Math.Min(bytes1.Length, bytes2.Length)).All(idx => bytes1[idx] == bytes2[idx]);
            }

            for (int iteration = 1; --iteration >= 0;)
            {
                getRandom(a, random);
                getRandom(b, random);
                getRandom(m, random); m[0] |= 1;
                a.CopyTo(am1, 0);
                a.CopyTo(am3, 0);

                elapsedMontgomeryExpMod += MeasureTime(() =>
                {
                    MontgomeryExpMod(am1, b, m, n, 6);
                });
                elapsedExpMod += MeasureTime(() =>
                {
                    ExpMod(am3, b, m, n, 5);
                });

                ok &= Enumerable.Range(0, n).All(idx => am3[idx] == am1[idx]);
            }

            TimeSpan
                elapsedMulDirect = TimeSpan.Zero,
                elapsedKaratsuba = TimeSpan.Zero;

            ulong[] temporaryKaratsubaBuffer = new ulong[GetKaratsubaMultiplicationBufferSize(n)];
            for (int iteration = 128; --iteration >= 0;)
            {
                getRandom(a, random);
                getRandom(b, random);
                AsmX64Operations.Multiply(a, a, s0, n);

                elapsedMulDirect += MeasureTime(() =>
                {
                    AsmX64Operations.Multiply(a, b, c1, n);
                    AsmX64Operations.Square(a, s1, n);
                });
                elapsedKaratsuba += MeasureTime(() =>
                {
                    AsmX64Operations.Karatsuba(a, b, c2, n, temporaryKaratsubaBuffer);
                    AsmX64Operations.KaratsubaSquare(a, s2, n, temporaryKaratsubaBuffer);
                });

                ok &= Enumerable.Range(0, n * 2).All(idx => c1[idx] == c2[idx]);
                ok &= Enumerable.Range(0, n * 2).All(idx => s0[idx] == s1[idx]);
                ok &= Enumerable.Range(0, n * 2).All(idx => s1[idx] == s2[idx]);
            }
            if (!ok)
            {
                //MessageBox.Show("not ok - error");
                return(false);
            }
            //MessageBox.Show(
            //    "elapsedMontgomeryExpMod: " + elapsedMontgomeryExpMod.ToString() + "\r\n" +
            //    "elapsedExpMod: " + elapsedExpMod.ToString() + "\r\n" +
            //    "elapsedBigIntegerExpMod: " + elapsedBigIntegerExpMod.ToString() + "\r\n" +
            //    "normal: " + elapsedMulDirect.ToString() + "  karatsuba: " + elapsedKaratsuba.ToString());
            return(true);
        }