Esempio n. 1
0
        private static bool LucasStrongTestHelper(BigInteger thisVal)
        {
            long D = 5, sign = -1, dCount = 0;
            bool done = false;

            while (!done)
            {
                int Jresult = Jacobi(D, thisVal);
                if (Jresult == -1)
                {
                    done = true;    // J(D, this) = 1
                }
                else
                {
                    if (Jresult == 0 && Math.Abs(D) < thisVal) // найден делитель
                    {
                        return(false);
                    }
                    if (dCount == 20)
                    {
                        BigInteger root = Sqrt(thisVal);
                        if (root * root == thisVal)
                        {
                            return(false);
                        }
                    }
                    D    = (Math.Abs(D) + 2) * sign;
                    sign = -sign;
                }
                dCount++;
            }
            long       Q      = (1 - D) >> 2;
            BigInteger p_add1 = thisVal + 1;

            uint[] data = SupportEDS.BigIntegerToUintArray(p_add1);
            int    s    = 0;

            for (int i = 0; i < data.Length - 1; i++)
            {
                uint mask = 0x01;
                for (int j = 0; j < 32; j++)
                {
                    if ((data[i] & mask) != 0)
                    {
                        i = data.Length;
                        break;
                    }
                    mask <<= 1;
                    s++;
                }
            }
            BigInteger t = p_add1 >> s;
            // вычисление константы для Редукции Баррета = b^(2k) / m
            BigInteger constant = new BigInteger();

            uint[] thisVal_data = SupportEDS.BigIntegerToUintArray(thisVal);
            int    nLen         = (thisVal_data.Length - 1) << 1;

            uint[] const_data = new uint[nLen + 2];
            for (int i = 0; i < const_data.Length; i++)
            {
                if (i == nLen)
                {
                    const_data[i] = 0x00000001;
                }
                else
                {
                    const_data[i] = 0x0;
                }
            }
            constant = SupportEDS.BigIntegerFromUintArray(const_data);
            constant = constant / thisVal;
            BigInteger[] lucas   = LucasSequenceHelper(1, Q, t, thisVal, constant, 0);
            bool         isPrime = false;

            if ((lucas[0] == 0) || lucas[1] == 0)
            {
                // u(t) = 0 либо V(t) = 0
                isPrime = true;
            }
            for (int i = 1; i < s; i++)
            {
                if (!isPrime)
                {
                    lucas[1] = BarrettReduction(lucas[1] * lucas[1], thisVal, constant);
                    lucas[1] = (lucas[1] - (lucas[2] << 1)) % thisVal;
                    //lucas[1] = ((lucas[1] * lucas[1]) - (lucas[2] << 1)) % thisVal;
                    if ((lucas[1] == 0))
                    {
                        isPrime = true;
                    }
                }
                lucas[2] = BarrettReduction(lucas[2] * lucas[2], thisVal, constant); //Q^k
            }
            if (isPrime)                                                             // дополнительная проверка на составные числа
            {
                BigInteger g = BigInteger.GreatestCommonDivisor(thisVal, Q);
                if (g == 1)
                {
                    uint[] lucas_data = SupportEDS.BigIntegerToUintArray(lucas[2]);
                    if (lucas[2] < 0)
                    {
                        lucas[2] += thisVal;
                    }
                    BigInteger temp = (Q * Jacobi(Q, thisVal)) % thisVal;
                    if (temp < 0)
                    {
                        temp += thisVal;
                    }
                    if (lucas[2] != temp)
                    {
                        isPrime = false;
                    }
                }
            }
            return(isPrime);
        }
Esempio n. 2
0
        public static BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant)
        {
            uint[] n_data    = SupportEDS.BigIntegerToUintArray(n);
            int    k         = Length(n_data.Length - 1),
                   kPlusOne  = k + 1,
                   kMinusOne = k - 1;
            BigInteger q1    = new BigInteger();

            // q1 = x / b^(k-1)
            uint[] x_data  = SupportEDS.BigIntegerToUintArray(x);
            int    new_lng = x_data.Length - kMinusOne;

            uint[] q1_data;
            if (new_lng > 1)
            {
                q1_data = new uint[new_lng];
            }
            else
            {
                q1_data = new uint[2];
            }
            q1_data[q1_data.Length - 1] = 0;
            for (int i = kMinusOne, j = 0; i < x_data.Length - 1; i++, j++)
            {
                q1_data[j] = x_data[i];
            }
            q1 = SupportEDS.BigIntegerFromUintArray(q1_data);
            BigInteger q2 = q1 * constant;

            // q3 = q2 / b^(k+1)
            uint[] q2_data  = SupportEDS.BigIntegerToUintArray(q2);
            int    new_lng2 = q2_data.Length - kPlusOne;

            uint[] q3_data;
            if (new_lng2 > 1)
            {
                q3_data = new uint[new_lng2];
            }
            else
            {
                q3_data = new uint[2];
            }
            q3_data[q3_data.Length - 1] = 0;
            for (int i = kPlusOne, j = 0; i < q2_data.Length - 1; i++, j++)
            {
                q3_data[j] = q2_data[i];
            }
            // r1 = x mod b^(k+1)
            // i.e. keep the lowest (k+1) words
            BigInteger r1           = new BigInteger();
            int        lengthToCopy = ((x_data.Length - 1) > kPlusOne) ? kPlusOne : (x_data.Length - 1);

            uint[] r1_data = new uint[lengthToCopy + 1];
            for (int i = 0; i < lengthToCopy; i++)
            {
                r1_data[i] = x_data[i];
            }
            r1_data[r1_data.Length - 1] = 0;
            // r2 = (q3 * n) mod b^(k+1)
            // partial multiplication of q3 and n
            BigInteger r2 = new BigInteger();

            uint[] r2_data = new uint[kPlusOne + 1];
            for (int i = 0; i < q3_data.Length - 1; i++)
            {
                if (q3_data[i] == 0)
                {
                    continue;
                }
                ulong mcarry = 0;
                int   t      = i;
                for (int j = 0; j < n_data.Length - 1 && t < kPlusOne; j++, t++)
                {
                    // t = i + j
                    ulong val = ((ulong)q3_data[i] * (ulong)n_data[j]) +
                                (ulong)r2_data[t] + mcarry;
                    r2_data[t] = (uint)(val & 0xFFFFFFFF);
                    mcarry     = (val >> 32);
                }
                if (t < kPlusOne)
                {
                    r2_data[t] = (uint)mcarry;
                }
            }
            r2_data[r2_data.Length - 1] = 0;
            r1  = SupportEDS.BigIntegerFromUintArray(r1_data);
            r2  = SupportEDS.BigIntegerFromUintArray(r2_data);
            r1 -= r2;
            if (r1 < 0)
            {
                r1 = -r1;
            }
            while (r1 >= n)
            {
                r1 -= n;
            }
            return(r1);
        }