public bool NextSegment(out long start, out long len, out SieveInitInfo req) { len = bs; req = this.req; start = currIdx; currIdx += bs; return(true); }
public static void FindQuadraticResidues(SieveInitInfo sievereq) { long L = primeSupply[sievereq.B]; BigInteger[] V = new BigInteger[L]; for (int i = 0; i < L; i++) { V[i] = sievereq.PolyFunction.F(i + sievereq.AStart); } List <List <long> > tmpPrimeStarts = new List <List <long> >(); List <long> tmpPrimeIntervals = new List <long>(); for (int pI = 0; pI < sievereq.B; pI++) { int p = primeSupply[pI]; List <long> tmp = new List <long>(2); for (int a = 0; a < p; a++) { if (V[a] % p == 0) { //we found a quadratic residue (there are two for each prime that isn't 2) tmp.Add(a); } } if (tmp.Count > 0) { //if the ith value is divisible by the prime k, then every k results after that will also be divisible tmpPrimeIntervals.Add(p); tmpPrimeStarts.Add(tmp); } } sievereq.PrimeIntervals = tmpPrimeIntervals.ToArray(); sievereq.PrimeStarts = tmpPrimeStarts.ToArray(); //remove primes with no quadratic residues sievereq.B = sievereq.PrimeIntervals.Length; }
static void MyQuadraticsTest() { BigInteger N = BigInteger.Parse(Console.ReadLine()); int B = slkjhjdf.SmallPrimes.Length - 1; SieveInitInfo req = new SieveInitInfo(B, new AS2MNPolyFunc(N)); //the max amount of data we need to find the quadratic residues is the Bth prime (the highest one) QuadraticSieve.FindQuadraticResidues(req); // QuadraticSieve.Sieve(req, res, 0, 109090); Console.WriteLine("Sieving for smooths..."); SolveRequest sreq = QuadraticSieve.MultiThreadSieve(B + 10, B, new SinglePolynomialGen(req, 200000), 2, 500); Console.WriteLine("Done sieving. Performing solve..."); SolveResult sres = QuadraticSieve.Gaussian(sreq); // sreq.V.ForEach(x => Console.WriteLine(x * x - N)); BigInteger factor; if (QuadraticSieve.GetFactor(N, sreq, sres, out factor)) { Console.WriteLine("{0} = {1} * {2}", N, factor, N / factor); } }
public SinglePolynomialGen(SieveInitInfo req, long len) { this.req = req; bs = len; }
//memory saving method - is slower, but better for multithreading public static void Sieve(SieveInitInfo sievereq, SieveResult sieveres, long startIdx, long L) { //want to optimize this further (predefine size of SmoothRelations to approximated B value) sieveres.SmoothRelations = new List <BinaryVector>(); sieveres.V = new List <long>(); sieveres.B = sievereq.B; sieveres.VOut = new List <BigInteger>(); long[] nextIdxA = new long[sievereq.B]; long[] nextIdxB = new long[sievereq.B]; for (int i = 0; i < sievereq.B; i++) { long interval = sievereq.PrimeIntervals[i]; long primeStart = sievereq.PrimeStarts[i][0]; long unoffset = startIdx - primeStart; long rounded = (long)Math.Ceiling((unoffset) * 1D / interval) * interval; long remappedStart = rounded + primeStart; nextIdxA[i] = remappedStart; if (sievereq.PrimeStarts[i].Count == 1) { nextIdxB[i] = -1; } else { interval = sievereq.PrimeIntervals[i]; primeStart = sievereq.PrimeStarts[i][1]; unoffset = startIdx - primeStart; rounded = (long)Math.Ceiling((unoffset) * 1D / interval) * interval; remappedStart = rounded + primeStart; nextIdxB[i] = remappedStart; } } BinaryVector currVect = new BinaryVector(sievereq.B); BigInteger currVal; for (long i = startIdx; i < L + startIdx; i++) { currVal = sievereq.PolyFunction.F(i + sievereq.AStart); for (int j = 0; j < sievereq.B; j++) { if (nextIdxA[j] == i) { while (currVal % sievereq.PrimeIntervals[j] == 0) { currVal /= sievereq.PrimeIntervals[j]; currVect[j] = currVect[j] + 1; } nextIdxA[j] += sievereq.PrimeIntervals[j]; } if (nextIdxB[j] == i) { while (currVal % sievereq.PrimeIntervals[j] == 0) { currVal /= sievereq.PrimeIntervals[j]; currVect[j] = currVect[j] + 1; } nextIdxB[j] += sievereq.PrimeIntervals[j]; } } if (currVal == 1) { sieveres.SmoothRelations.Add(currVect); currVect = new BinaryVector(sievereq.B); sieveres.V.Add(i + sievereq.AStart); sieveres.VOut.Add(sievereq.PolyFunction.F(i + sievereq.AStart)); sieveres.SmoothsFound++; } else { BinaryVector.FastFill(0, currVect); } } }