示例#1
0
        public static BigInteger Run(BigInteger N, int B, int M)
        {
            // Find basis for sieving
            var primes = nt.Primes(B).Where(p => nt.IsQuadResidue(p, N)).ToList();
            var sqN = N.Sqrt();
            Func<int, BigInteger> Q = x => (x + sqN) * (x + sqN) - N;

            // use quadsieve on V
            BigInteger[] V = Enumerable.Range(0, M).Select(x => Q(x)).ToArray();
            int[,] coeff; // coeff[i,j] : Q(i) = Prod p_j ^e_ij
            Sieve(N, primes, ref V, out coeff);

            int K = primes.Count;
            int L = V.Count(w => w.IsOne);
            int[] indices = new int[L]; // indices[i] = x_i, Q(x_i) : B-smooth
            int[,] vectors = new int[K, L];
            for(int i=0, cnt=0; i<V.Length && cnt < L; i++)
            {
                if (!V[i].IsOne) continue;

                for(int j=0; j<K; j++)
                {
                    indices[cnt] = i;
                    vectors[j, cnt] = coeff[i, j] % 2; // transposed
                }
                cnt++;
            }

            var exponent = GaussianElimination(vectors);
            BigInteger ans1, ans2;
            ans1 = ans2 = BigInteger.One;
            for (int i = 0; i < exponent.Length; i++)
            {
                if (exponent[i] == 0) continue;
                ans1 *= (indices[i] + sqN);
                ans2 *= Q(indices[i]);
            }
            ans2 = ans2.Sqrt();
            var a = BigInteger.GreatestCommonDivisor(ans1 - ans2, N);
            if (a.IsOne)
                a = BigInteger.GreatestCommonDivisor(ans1 + ans2, N);
            return a;
        }
        /// <summary>  v    cQ1
        ///  Initializes a SievingRequest based on given parameters, and finds the quadratic residues for primes specified
        /// </summary>
        /// <param name="N">The number to factor</param>
        /// <param name="B">The limit for smooth numbers</param>
        /// <param name="f">The polynomial to sieve</param>
        /// <param name="sievereq">The SieveRequest that will be initialized</param>
        public static void InitSievingRequest(BigInteger N, int B, PolynomialFunction f, SieveRequest sievereq)
        {
            sievereq.AStart = (int)N.Sqrt() + 1;
            sievereq.StartIdx = 0;
            sievereq.polyFunction = f;
            sievereq.L = primeSupply[B];

            SievingData sievedat = new SievingData();

            EvaluatePoly(sievereq, sievedat);

            List<List<int>> tmpPrimeStarts = new List<List<int>>();
            List<int> tmpPrimeIntervals = new List<int>();

            for (int pI = 0; pI < B; pI++)
            {
                int p = primeSupply[pI];
                List<int> tmp = new List<int>();
                for (int a = 0; a < p; a++)
                {
                    if (sievedat.V[a] % p == 0)
                    {
                        tmp.Add(a);
                    }
                }
                if (tmp.Count > 0)
                {
                    tmpPrimeIntervals.Add(p);
                    tmpPrimeStarts.Add(tmp);
                }
            }

            sievereq.PrimeIntervals = tmpPrimeIntervals.ToArray();
            sievereq.PrimeStarts = tmpPrimeStarts.ToArray();
            sievereq.B = sievereq.PrimeIntervals.Length;
        }
示例#3
0
 private static void Sieve(BigInteger N, List<int> primes, ref BigInteger[] V, out int[,] coeff)
 {
     var sqN = N.Sqrt();
     int M = V.Length;
     int K = primes.Count;
     // exponent vectors
     coeff = new int[M, K];
     for (int k = 0; k < K; k++)
     {
         int p = primes[k];
         int a;
         if (p == 2)
         {
             a = (sqN.IsEven ^ N.IsEven) ? 1 : 0;
             for (int i = a; i < M; i += 2)
             {
                 if (!V[i].IsEven) throw new ArithmeticException();
                 V[i] /= 2;
                 coeff[i, k]++;
             }
             continue;
         }
         int sr = nt.ModSqrt(N, p);
         a = (p+sr - sqN.Mod(p)) % p;
         int b = (2*p - sr - sqN.Mod(p)) % p;
         for (int i = a; i < M; i += p)
         {
             if (V[i] % p != 0) throw new ArithmeticException();
             V[i] /= p;
             coeff[i, k]++;
         }
         for (int i = b; i < M; i += p)
         {
             if (V[i] % p != 0) throw new ArithmeticException();
             V[i] /= p;
             coeff[i, k]++;
         }
     }
 }
示例#4
0
文件: BagMath.cs 项目: jamiees2/Pie
        /// <summary>
        /// Checks whether a number is a prime number or not.
        /// </summary>
        /// <param name="n">The number to test.</param>
        /// <param name="checkCache">Whether to check cache for primality.</param>
        /// <returns>Whether the number is prime.</returns>
        public static bool IsPrime(BigInteger n, bool checkCache = true)
        {
            if (n <= 1) return false;
            if (checkCache && n <= BagMath.LargestSmallPrime) return Array.BinarySearch<int>(BagMath.SmallPrimes, (int)n) >= 0;
            if (n < 4) return true;
            if (n % 2 == 0) return false;
            if (n < 9) return true;
            if (n % 3 == 0) return false;

            BigInteger r = n.Sqrt(),
                       f = 5;

            while (f <= r)
            {
                if (n % f == 0) return false;
                if (n % (f + 2) == 0) return false;
                f += 6;
            }

            return true;
        }
        public static void Test_Sqrt_Neg1throwsException()
        {
            var neg1 = new BigInteger(-1);

            var sqrt = neg1.Sqrt();
        }