void buildSieveTo(unsigned long long n){ if(n<=4289995710U) doSieve(n); else{ doSieve(4289995710U); doBigSieve(n); } }
unsigned int primesUpToSmall(unsigned int n, std::vector<unsigned int>& primes){ if(n>=60184){ primes.reserve((unsigned int)(n/(log(n)-1.1))); doSieve(n); }else if(n>=17){ primes.reserve((unsigned int)(1.25506*n/log(n))); doSieve(n); }else primes.reserve(6); unsigned int t=0; if(n>=2){ primes[0]=2; t=1; } if(n>=3){ primes[1]=3; t=2; } if(n>=5){ primes[2]=5; t=3; } if(n>=7){ primes[3]=7; t=4; } if(n>=11){ primes[4]=11; t=5; } if(n>=13){ primes[5]=13; t=6; } if(n>=17){ unsigned int b=1; unsigned int p=17; while(p<=n){ primes[t]=p; ++t; ++b; while(!sieve[b]) ++b; p=b/5760*30030+conversions[b%5760]; } } return t; }
bool isPrimeSmall(unsigned int n){ if(n==2 || n==3 || n==5 || n==7 || n==11 || n==13) return true; if(!(n&1U) || !(n%3) || !(n%5) || !(n%7) || !(n%11) || !(n%13)) return false; doSieve(n); return sieve[n/30030*5760+indexes[n%30030]]; }
void firstPrimesSmall(unsigned int n, std::vector<unsigned int>& primes){ primes.reserve(n); if(n<=194682290) doSieve((unsigned int)(n*log(n*log(n)))); else doSieve(4289995710U); unsigned int t=0; if(n>=1){ primes[0]=2; t=1; } if(n>=2){ primes[1]=3; t=2; } if(n>=3){ primes[2]=5; t=3; } if(n>=4){ primes[3]=7; t=4; } if(n>=5){ primes[4]=11; t=5; } if(n>=6){ primes[5]=13; t=6; } if(n>=7){ unsigned int b=1; unsigned int p=17; while(t<n){ primes[t]=p; ++t; if(t<n){ ++b; while(!sieve[b]) ++b; p=b/5760*30030+conversions[b%5760]; } } } }
int main(){ // unsigned long max = 10000000UL; unsigned long max = 10000000UL; // unsigned long max = 500UL; // doSieve(max*log(max)*log(log(max)) , &modPrint); doSieve((max * log(max) + max * (log(log(max)) - 0.9385)), &modPrint); printf("max = %lu\n", (max * log(max) + max * (log(log(max)) - 0.9385))); // check(13); return 0; }
unsigned int numPrimesUpToSmall(unsigned int n){ doSieve(n); if(n>=17){ unsigned int t=6; unsigned int b=1; unsigned int maxb=n/1001*192; // this can put maxb up to 2 greater than where it should be if(n%30030){ if(maxb/5760*30030+conversions[maxb%5760]>n) // maxb is at most 1 greater than where it should be --maxb; while(maxb/5760*30030+conversions[maxb%5760]<n) // force maxb up to equal (prime) or 1 greater (composite) than where it should be ++maxb; if(maxb/5760*30030+conversions[maxb%5760]>n) // put maxb where it should be --maxb; }else if(maxb) --maxb; if(n<=4289995710U){ while(b<=maxb){ ++t; ++b; while(!sieve[b]) ++b; } }else{ t=203056267; b=3; maxb-=822856320; while(b<=maxb){ ++t; ++b; while(!bigsieve[b]) ++b; } } return t; }else if(n>=13) return 6; else if(n>=11) return 5; else if(n>=7) return 4; else if(n>=5) return 3; else if(n>=3) return 2; else if(n>=2) return 1; else return 0; }
int latSieve(s32 *candidates, int maxCands, nfs_fb_t *FB, s32 qIndex, double sieveArea, s32 cacheSize) /***************************************************************************/ /* We will not actually test for smoothness - instead, we will just return */ /* the list of candidates and allow the caller to test them. They will be */ /* returned as: (a_i, b_i) = (candidates[2*i], candidates[2*i+1]). */ /* Return value: negative on error. Otherwise, the number of candidates. */ /***************************************************************************/ /* This function should be modified, to accept an area instead of a range */ /* on the c, d values. It should compute the range of values from the area */ /* after we've obtained (short) generators for the lattice. */ /***************************************************************************/ { s32 q, s; /* Special q prime. */ char logQ; s32 a1, b1, a2, b2; /* Short vectors spanning the lattice L_q. */ s32 v1[2], v2[2]; /* temp garbage. */ short *Array, entry, ratInit, normApprox; s32 C, E; /* Defining the total rectangle in the (c,e)-plane to be sieved. */ s32 Clength; s32 E0, E1; /* A particular sub-rectangle being sieved. */ int numPieces, pieceESize; /* Number of sub-rectangles and the size. */ s32 *primeVec; /* Primes prepared for sieving (Master index) */ char *logs, *rlogs, *alogs, *rElogs, *aElogs; /* Logs of those primes. */ s32 *rU, *aU, numRU, numAU; /* Ordinary primes to be vector-sieved with. */ s32 *rExc, *aExc, numRExc, numAExc; /* `Exceptional primes'. */ s32 numVecs, rfbSize, afbSize; s32 p, r, t1, t2, c, e; /* temp stuff. */ s32 rD, aD; /* Crossover from sieve-by-rows to sieve-by-vectors. */ s32 i, j, a, b, g, index; int numCands=0, rfb_log_ff, afb_log_ff; rfb_log_ff = (int)(FB->rfb_lambda * fplog(FB->rfb[FB->rfb_size-1], FB->log_rlb)); afb_log_ff = (int)(FB->afb_lambda * fplog(FB->afb[FB->afb_size-1], FB->log_alb)); #ifdef Q_FROM_RFB if (qIndex >= FB->rfb_size) { fprintf(stderr, "latSieve() Error - invalid qIndex!\n"); return -1; } q = FB->rfb[2*qIndex]; s = FB->rfb[2*qIndex+1]; logQ = FB->rfb_log[qIndex]; rfbSize = qIndex; afbSize = FB->afb_size; #else if (qIndex >= FB->afb_size) { fprintf(stderr, "latSieve() Error - invalid qIndex!\n"); return -1; } q = FB->afb[2*qIndex]; s = FB->afb[2*qIndex+1]; logQ = FB->afb_log[qIndex]; rfbSize = FB->rfb_size; afbSize = qIndex; #endif v1[0]=q; v1[1]=0; v2[0]=s; v2[1]=1; reduceBasis(v1, v2); a1=v1[0]; b1=v1[1]; a2=v2[0]; b2=v2[1]; if (b1 < 0) { a1=-a1; b1=-b1;} if (b2 < 0) { a2=-a2; b2=-b2;} //printf("For (q,s)=(%ld,%ld), L_q has basis: (%ld, %ld), (%ld, %ld)\n",q,s,a1,b1,a2,b2); /************************************************************************/ /* We should compute the shape of the rectangle in the (c,e) plane. */ /* That is, assume a fixed amount of memory A, and find the rect. */ /* defined by -C<=c<=C, 0 < e <= E so that the average resulting 'b' */ /* value, |c*b1 + e*b2|, is minimal (or close to it). */ /* Equivalently, minimize: */ /* sum_R |c*b1 + e*b2|, where the sum is over all -C<=c<=C, 0 < e <= E */ /* subject to the constraint that (2C+1)E = A. */ /************************************************************************/ /* We will approximate the solution to the above constrained optimization */ /* problem later. But I think this should be pretty close (or even correct). */ C = (s32)1*(sqrt(sieveArea*b2/(double)(2.0+2.0*b1))); // if (C<1000) C = 1000; /* Arbitrary, but seems reasonable. */ E = (s32)(sieveArea/C); Clength = 2*C+1; numPieces = (int)((sizeof(short)*sieveArea/cacheSize)); if (numPieces*cacheSize < sieveArea) numPieces++; pieceESize = (E/numPieces); //if (numPieces > 1) // printf("q=(%ld, %ld), C=[%ld, %ld], E=%ld, numPieces=%d\n",q,s,-C,C,E,numPieces); Array = (short *)malloc(pieceESize*(Clength)*sizeof(short)); /*********************************/ /* Prepare the primes. */ /*********************************/ primeVec = (s32 *)malloc((rfbSize+afbSize + MAX_R_EXC + MAX_A_EXC)*4*sizeof(s32)); logs = (char *)malloc((rfbSize+afbSize + MAX_R_EXC + MAX_A_EXC)*sizeof(char)); rExc = &primeVec[4*(rfbSize+afbSize)]; aExc = &primeVec[4*(rfbSize+afbSize + MAX_R_EXC)]; rElogs = &logs[rfbSize+afbSize]; aElogs = &logs[rfbSize+afbSize + MAX_R_EXC]; numVecs = numRExc = numAExc = 0; rD = aD = 0; /* Arbitrary for now, but should be fixed later, when we can treat the small primes differently. */ for (i=rD; i<rfbSize; i++) { p = FB->rfb[2*i]; r = FB->rfb[2*i+1]; t2 = (a2 - mulmod32(r, b2, p) + p)%p; t1 = (mulmod32(r, b1, p) - a1%p + p)%p; if (t1&&t2) { primeVec[4*numVecs]=p; primeVec[4*numVecs+1]=0; primeVec[4*numVecs+2] = mulmod32(t2, inverseModP(t1, p), p); primeVec[4*numVecs+3]=1; reduceBasis(&primeVec[4*numVecs], &primeVec[4*numVecs+2]); if (primeVec[4*numVecs+1]<0) { primeVec[4*numVecs]=-primeVec[4*numVecs]; primeVec[4*numVecs+1]=-primeVec[4*numVecs+1];} if (primeVec[4*numVecs+3]<0) { primeVec[4*numVecs+2]=-primeVec[4*numVecs+2]; primeVec[4*numVecs+3]=-primeVec[4*numVecs+3];} logs[numVecs++] = FB->rfb_log[i]; } else if (t1==0) { rExc[4*numRExc] = 1; rExc[4*numRExc+1] = 0; rExc[4*numRExc+2] = 0; rExc[4*numRExc+3] = p; rElogs[numRExc++] = FB->rfb_log[i]; } else { rExc[4*numRExc] = p; rExc[4*numRExc+1] = 0; rExc[4*numRExc+2] = 0; rExc[4*numRExc+3] = 1; rElogs[numRExc++] = FB->rfb_log[i]; } } rU = primeVec; numRU = numVecs; rlogs = logs; for (i=aD; i<afbSize; i++) { p = FB->afb[2*i]; r = FB->afb[2*i+1]; t2 = (a2 - mulmod32(r, b2, p) + p)%p; t1 = (mulmod32(r, b1, p) - a1%p + p)%p; if (t1&&t2) { primeVec[4*numVecs]=p; primeVec[4*numVecs+1]=0; primeVec[4*numVecs+2] = mulmod32(t2, inverseModP(t1, p), p); primeVec[4*numVecs+3]=1; reduceBasis(&primeVec[4*numVecs], &primeVec[4*numVecs+2]); if (primeVec[4*numVecs+1]<0) { primeVec[4*numVecs]=-primeVec[4*numVecs]; primeVec[4*numVecs+1]=-primeVec[4*numVecs+1];} if (primeVec[4*numVecs+3]<0) { primeVec[4*numVecs+2]=-primeVec[4*numVecs+2]; primeVec[4*numVecs+3]=-primeVec[4*numVecs+3];} logs[numVecs++] = FB->afb_log[i]; } else if (t1==0) { aExc[4*numAExc] = 1; aExc[4*numAExc+1] = 0; aExc[4*numAExc+2] = 0; aExc[4*numAExc+3] = p; aElogs[numAExc++] = FB->afb_log[i]; } else { aExc[4*numAExc] = p; aExc[4*numAExc+1] = 0; aExc[4*numAExc+2] = 0; aExc[4*numAExc+3] = 1; aElogs[numAExc++] = FB->afb_log[i]; } } aU = &primeVec[4*numRU]; numAU = numVecs - numRU; alogs = &logs[numRU]; /* Ok - let's sieve. */ E0 = 1; E1 = pieceESize; for (i=0; i<numPieces; i++) { /* Initialize the sieve array for the rational sieve. */ ratInit = (short)(rfb_log_ff - fplog_mpz(FB->m, FB->log_rlb)); for (j=Clength*(E1-E0+1)-1; j>=0; j--) Array[j]=ratInit; /* We need to sieve by rows with the first rD primes here! */ doSieve(Array, C, E0, E1, rU, numRU, rlogs); doSieveE(Array, -C, C, E0, E1, rExc, numRExc, rElogs); /* Initialize for the algebraic sieve. */ /*******************************************************************/ /* This needs to be implemented: */ /* We should use Lenstra's trick here: Instead of computing the */ /* norm for all candidates which survived the rational sieve, */ /* simply use the same really rough approximation for all of them. */ /* Then, when we are pulling candidates out of the array, we can */ /* compute the real norm and look at it a bit more closely. */ /*******************************************************************/ normApprox = fplog_evalF(a1+a2, b1+b2, FB) - 7; /* -3 for luck :) */ entry = rfb_log_ff + logQ - normApprox; index=0; for (e=E0; e<=E1; e++) { for (c=-C; c<=C; c++) { if (Array[Clength*(e-E0)+c+C] >= 0) { b = c*b1 + e*b2; if (b<0)b=-b; if (Array[Clength*(e-E0)+c+C] >= fplog(b, FB->log_rlb)) Array[Clength*(e-E0)+c+C] = entry; else Array[Clength*(e-E0)+c+C] = VERYSMALL_SHORT; } else Array[Clength*(e-E0)+c+C] = VERYSMALL_SHORT; } } /* We need to sieve by rows with the first aD primes here! */ doSieve(Array, C, E0, E1, aU, numAU, alogs); doSieveE(Array, -C, C, E0, E1, aExc, numAExc, aElogs); /* Find candidates. */ // entry = fplog_evalF(a1+a2, b1+b2, FB); for (j=Clength*(E1-E0+1)-1; j>=0; j--) { if ((Array[j] >= 0)&&(numCands < maxCands)) { e = E0 + j/Clength; c = -C + (j%Clength); a = c*a1 + e*a2; b = c*b1 + e*b2; if (b<0) { a=-a; b=-b;} if ((Array[j] + normApprox - fplog_evalF(a,b, FB))>=0) { g = gcd(a,b); if ((g==1)||(g==-1)) { candidates[2*numCands] = a; candidates[2*numCands+1] = b; numCands++; } } } } /* Prepare to do the next sub-rectangle. */ E0 += pieceESize; E1 += pieceESize; } free(Array); free(primeVec); free(logs); return numCands; }
unsigned char factorSmall(unsigned int n, unsigned int* factors, unsigned char* exponents){ unsigned char exp=0; unsigned char numfacs=0; while(!(n&1U)){ ++exp; n>>=1; } if(exp){ factors[0]=2; exponents[0]=exp; numfacs=1; exp=0; } while(!(n%3)){ ++exp; n/=3; } if(exp){ factors[numfacs]=3; exponents[numfacs]=exp; ++numfacs; exp=0; } while(!(n%5)){ ++exp; n/=5; } if(exp){ factors[numfacs]=5; exponents[numfacs]=exp; ++numfacs; exp=0; } while(!(n%7)){ ++exp; n/=7; } if(exp){ factors[numfacs]=7; exponents[numfacs]=exp; ++numfacs; exp=0; } while(!(n%11)){ ++exp; n/=11; } if(exp){ factors[numfacs]=11; exponents[numfacs]=exp; ++numfacs; exp=0; } while(!(n%13)){ ++exp; n/=13; } if(exp){ factors[numfacs]=13; exponents[numfacs]=exp; ++numfacs; exp=0; } unsigned int b = 1; unsigned int p = 17; if(maxsieve*maxsieve<n){ while(b<maxbool && p*p<=n){ while(!(n%p)){ ++exp; n/=p; } if(exp){ factors[numfacs]=p; exponents[numfacs]=exp; ++numfacs; exp=0; } ++b; while(!sieve[b]) ++b; p = b/5760*30030+conversions[b%5760]; } if(p*p<=n) doSieve(sqrt(n)); } if(p*p<=n){ while(!sieve[b]) ++b; p = b/5760*30030+conversions[b%5760]; } while(p*p<=n){ while(!(n%p)){ ++exp; n/=p; } if(exp){ factors[numfacs]=p; exponents[numfacs]=exp; ++numfacs; exp=0; } ++b; while(!sieve[b]) ++b; p = b/5760*30030+conversions[b%5760]; } if(n>1){ factors[numfacs]=n; exponents[numfacs]=1; ++numfacs; } return numfacs; }