00001
00007 #include "mpqsPolynom.H"
00008 extern CmpqsPolynom Polynom;
00009
00010
00011 #ifdef USE_FIBHEAP
00012 #include "fibheap.H"
00013 FibHeap <TSieve_Delta> Sieve_Delta_Heap, Sieve_Delta_HeapOfSquares;
00014 #include <queue>
00015 #elif defined(USE_FAKEHEAP)
00016 #include "fakeheap.H"
00017 FakeHeap <TSieve_Delta> Sieve_Delta_Heap;
00018 #include <queue>
00019 std::priority_queue<TSieve_Delta> Sieve_Delta_HeapOfSquares;
00020 #else
00021 #include <queue>
00022 std::priority_queue<TSieve_Delta> Sieve_Delta_Heap, Sieve_Delta_HeapOfSquares;
00023 #endif
00024
00025
00026 extern bool is_dynamic_factor(const int number);
00027
00029 namespace DynamicFactorArrays
00030 {
00031
00032
00033 const unsigned int MaxDynamicFactors = 2500000;
00034 static int DynFactors[MaxDynamicFactors];
00035 static int DynFactorReciprocals[MaxDynamicFactors];
00036 static int SQRT_kNs[MaxDynamicFactors];
00037 static signed int PolyDs[MaxDynamicFactors];
00038
00039 unsigned int DynamicFactorsInUse = 0;
00040 double DYNFB_threshold = 0.0;
00041
00042 void compute_Deltas_for_DynamicFactors(const int offset)
00043 {
00044 #if defined(VERBOSE)
00045 cout << "FYI: we have " << DynamicFactorsInUse << " dynamic factors in use for sieving." << endl;
00046 #endif
00047 for (unsigned int i=0; i<DynamicFactorsInUse; ++i)
00048 {
00049 register const int DynFac=DynFactors[i];
00050 const int &DynFacReciprocal = DynFactorReciprocals[i];
00051
00052 TSieve_Delta sieb_delta;
00053 int d1,d2;
00054
00055 sieb_delta.factor=DynFac;
00056 const unsigned int PolyB = mpz_remainder_ui(Polynom.get_B(),DynFac);
00057
00058 if (PolyDs[i]<0 || !CDeltaComputations::D_difference_to_last)
00059 {
00060
00061 PolyDs[i]=mpz_remainder_ui(Polynom.get_D(),DynFac);
00062 }
00063 else
00064 {
00065
00066 PolyDs[i]+=CDeltaComputations::D_difference_to_last;
00067 }
00068 while (PolyDs[i]>=DynFac) PolyDs[i]-=DynFac;
00069 unsigned int inv_A2 = numtheory::squaremod(PolyDs[i],DynFac)<<1;
00070 if (inv_A2>=static_cast<unsigned int>(DynFac)) inv_A2-=DynFac;
00071 inv_A2 = fastinvmod(inv_A2,DynFac);
00072
00073 d1=SQRT_kNs[i]-PolyB; if (d1<0) d1+=DynFac;
00074 d1=mulmod(d1,inv_A2,DynFac);
00075 sieb_delta.delta=normalized_signed_mod(d1-offset,DynFac,DynFacReciprocal);
00076 sieb_delta.delta+=offset;
00077 #ifdef USE_FAKEHEAP
00078 while (sieb_delta.delta<=LogicalSieveSize)
00079 {
00080 Sieve_Delta_Heap.push(sieb_delta);
00081 sieb_delta.delta+=sieb_delta.factor;
00082 }
00083 #else
00084 if (sieb_delta.delta<=LogicalSieveSize)
00085 Sieve_Delta_Heap.push(sieb_delta);
00086 #endif
00087
00088 d2=DynFac-SQRT_kNs[i]-PolyB; if (d2<0) d2+=DynFac;
00089 d2=mulmod(d2,inv_A2,DynFac);
00090 sieb_delta.delta=normalized_signed_mod(d2-offset,DynFac,DynFacReciprocal);
00091 sieb_delta.delta+=offset;
00092 if ( (sieb_delta.delta<=LogicalSieveSize) && (d1!=d2) )
00093 {
00094 Sieve_Delta_Heap.push(sieb_delta);
00095 #ifdef USE_FAKEHEAP
00096 sieb_delta.delta+=sieb_delta.factor;
00097 while (sieb_delta.delta<=LogicalSieveSize)
00098 {
00099 Sieve_Delta_Heap.push(sieb_delta);
00100 sieb_delta.delta+=sieb_delta.factor;
00101 }
00102 #endif
00103 }
00104 }
00105 }
00106
00107 }
00108
00109 void TDynamicFactorRelation::append_DynamicFactor_for_sieving(const int DynFac)
00110 {
00111 using namespace DynamicFactorArrays;
00112 if (DynamicFactorsInUse>=MaxDynamicFactors)
00113 {
00114 MARK; cerr << "you may want to increase MaxDynamicFactors and recompile..." << endl;
00115 return;
00116 }
00117
00118
00119
00120
00121
00122
00123 if (is_dynamic_factor(DynFac))
00124 {
00125 #ifdef VERBOSE_INFO
00126 cout << "append dynamic factor: " << DynFac << " is already appended!" << endl;
00127 #endif
00128 return;
00129 }
00130 DynFactors[DynamicFactorsInUse] = DynFac;
00131 DynFactorReciprocals[DynamicFactorsInUse] = numtheory::reciprocal(DynFac);
00132 SQRT_kNs[DynamicFactorsInUse]=SQRT_kN_mod_PrimeNumber(DynFac);
00133 PolyDs[DynamicFactorsInUse]=-1;
00134 ++DynamicFactorsInUse;
00135
00136 DYNFB_threshold-=(4.0*LogicalSieveSize)/DynFac;
00137
00138 }
00139
00140
00141
00142 void do_sieving_Squares()
00143 {
00144
00145
00146
00147
00148
00149
00150
00151 if (Sieve_Delta_HeapOfSquares.empty()) return;
00152 TSieve_Delta sieb_delta = Sieve_Delta_HeapOfSquares.top();
00153 register int delta = sieb_delta.delta-SieveOffset;
00154
00155 #if 0
00156 while (delta<0)
00157 {
00158 cout << "sieving squares: " << sieb_delta.factor << " skipped!" << endl;
00159 Sieve_Delta_HeapOfSquares.pop();
00160 if (Sieve_Delta_HeapOfSquares.empty()) return;
00161 sieb_delta = Sieve_Delta_HeapOfSquares.top();
00162 delta = sieb_delta.delta-SieveOffset;
00163 }
00164 #endif
00165
00166 while (delta<PhysicalSieveSize)
00167 {
00168 Sieve_Delta_HeapOfSquares.pop();
00169 SieveArray[delta]-=log_DynamicLargePrime(sieb_delta.factor);
00170 if (Sieve_Delta_HeapOfSquares.empty()) break;
00171 sieb_delta = Sieve_Delta_HeapOfSquares.top();
00172 delta = sieb_delta.delta-SieveOffset;
00173 }
00174
00175 }
00176
00177
00178
00179 void do_sieving_DynamicFactors()
00180 {
00181 if (Sieve_Delta_Heap.empty()) return;
00182
00183 short int HitCount=0;
00184 TSieve_Delta sieb_delta = Sieve_Delta_Heap.top();
00185 register int delta = sieb_delta.delta-SieveOffset;
00186
00187 #if 0
00188 while (delta<0)
00189 {
00190 cout << "sieving dynamic factors: " << sieb_delta.factor << " skipped!" << endl;
00191 Sieve_Delta_Heap.pop();
00192 if (Sieve_Delta_Heap.empty()) return;
00193 sieb_delta = Sieve_Delta_Heap.top();
00194 delta = sieb_delta.delta-SieveOffset;
00195 }
00196 #endif
00197
00198 while (delta < PhysicalSieveSize)
00199 {
00200 Sieve_Delta_Heap.pop();
00201 SieveArray[delta]-=log_DynamicLargePrime(sieb_delta.factor);
00202
00203
00204 Hits[HitCount].Faktor=sieb_delta.factor;
00205
00206 #ifdef USE_FAKEHEAP
00207 if (Sieve_Delta_Heap.empty())
00208 {
00209 if (SieveArray[delta]<0)
00210 if (SieveControl::Hit_after_DirtyCorrection(delta+SieveOffset,SieveArray[delta]))
00211 {
00212 SieveArray[delta]=1;
00213 StaticRelations::insert(new CRelation(delta+SieveOffset,HitCount+1));
00214 }
00215 return;
00216 }
00217 #else
00218 sieb_delta.delta += sieb_delta.factor;
00219 if (sieb_delta.delta<=LogicalSieveSize)
00220 {
00221 Sieve_Delta_Heap.push(sieb_delta);
00222 }
00223 else
00224 if (Sieve_Delta_Heap.empty())
00225 {
00226 if (SieveArray[delta]<0)
00227 if (SieveControl::Hit_after_DirtyCorrection(delta+SieveOffset,SieveArray[delta]))
00228 {
00229 SieveArray[delta]=1;
00230 StaticRelations::insert(new CRelation(delta+SieveOffset,HitCount+1));
00231 }
00232 return;
00233 }
00234 #endif
00235
00236 sieb_delta = Sieve_Delta_Heap.top();
00237 register int delta2; delta2 = sieb_delta.delta-SieveOffset;
00238 if (delta==delta2)
00239 {
00240 ++HitCount;
00241 #ifdef DEBUG
00242 if (HitCount>=CHits::MaxHits) { cerr << "increase MaxHits!"; exit(1); }
00243 #endif
00244 continue;
00245 }
00246 if (SieveArray[delta]<0)
00247 if (SieveControl::Hit_after_DirtyCorrection(delta+SieveOffset,SieveArray[delta]))
00248 {
00249 SieveArray[delta]=1;
00250 StaticRelations::insert(new CRelation(delta+SieveOffset, HitCount+1));
00251 }
00252 delta=delta2;
00253 HitCount=0;
00254 }
00255 return;
00256 }
00257
00258
00259
00260 #if 0
00261 #include <map>
00262 void Werteverteilung_im_Sieb_ausgeben(void)
00263 {
00264
00265
00266
00267 typedef map<TSieveElement,unsigned int> TStats;
00268 static TStats S;
00269 for (int i=0; i<PhysicalSieveSize; ++i) S[SieveArray[i]]++;
00270
00271 static int z = 1000;
00272 if (--z==0)
00273 {
00274 z=1000;
00275
00276 for (TStats::const_iterator pos=S.begin(); pos!=S.end(); ++pos)
00277 cout << static_cast<signed long int>(pos->first) << " : " << pos->second << endl;
00278
00279 cout << "press <Enter> to continue" << endl;
00280 string s; cin >> s;
00281 }
00282 }
00283 #endif
00284
00285
00286 void CDeltaComputations::recompute_all_Deltas(const bool DoReallyAll )
00287 {
00288
00289
00290
00291
00292
00293
00294 #ifdef USE_FAKEHEAP
00295
00296 Sieve_Delta_Heap.clear();
00297 #else
00298 while (!Sieve_Delta_Heap.empty()) Sieve_Delta_Heap.pop();
00299 #endif
00300
00301
00302
00303 while (!Sieve_Delta_HeapOfSquares.empty()) Sieve_Delta_HeapOfSquares.pop();
00304
00305
00306
00307 unsigned int inv_A2_modp, PolyB;
00308 mpz_t inv_A2, P, wuq, x, y;
00309
00310 mpz_init(inv_A2); mpz_init(P); mpz_init(wuq); mpz_init(x); mpz_init(y);
00311
00312
00313
00314
00315 mpqsDmodPUpdater.update();
00316
00317
00318
00319
00320
00321
00322 if (PrimeNumbers[1]!=2)
00323 {
00324 inv_A2_modp=fastinvmod_23bit(Polynom.get_A2_mod(PrimeNumbers[1]),PrimeNumbers[1]);
00325 PolyB=mpz_remainder_ui(Polynom.get_B(),PrimeNumbers[1]);
00326 register signed int d = PolyB%PrimeNumbers[1];
00327 register signed int h = inv_A2_modp%PrimeNumbers[1];
00328 d=mulmod(d,h,PrimeNumbers[1]);
00329 h=mulmod(SQRT_kN_of_PrimeNumbers[1],h,PrimeNumbers[1]);
00330 d=-d; d+=h; if (d<0) d+=PrimeNumbers[1];
00331 Delta_of_PrimeNumbers[1][0]=d;
00332 d-=h; if (d<0) d+=PrimeNumbers[1];
00333 d-=h; if (d<0) d+=PrimeNumbers[1];
00334 Delta_of_PrimeNumbers[1][1]=d;
00335 }
00336
00337 long int i=2;
00338 while(i<StaticFactorbase::Size() && PrimeNumbers[i+1]<46340)
00339 {
00340 #if 0 || defined(DEBUG)
00341 if (D_mod_FBPrime[i]!=PrimeNumbers[i]*PrimeNumbers[i+1])
00342 {
00343 MARK; cerr << "implementation error."
00344 << "The D_mod_FBPrime[] structure is a bit tricky..." << endl
00345 << "review the source code." << endl;
00346 exit(2);
00347 }
00348 if (get_A2_mod_FBPrimePair(i)!=Polynom.get_A2_mod(D_mod_FBPrime[i]))
00349 {
00350 MARK;
00351 cout << "StaticFactorbase::Size(): " << StaticFactorbase::Size() << endl;
00352 cout << "PrimeNumbers[i], PrimeNumbers[i+1]: " << PrimeNumbers[i] << ", " << PrimeNumbers[i+1] << endl;
00353 cout << i << ": " << get_A2_mod_FBPrimePair(i) << " ?? " << Polynom.get_A2_mod(D_mod_FBPrime[i]) << endl;
00354 exit(2);
00355 }
00356 #endif
00357 const int N=D_mod_FBPrime[i];
00358 inv_A2_modp=fastinvmod(get_A2_mod_FBPrimePair(i),N);
00359
00360 PolyB=mpz_remainder_ui(Polynom.get_B(),N);
00361
00362
00363 for (signed int j=2; --j>=0; ++i)
00364 {
00365 #if 1 && defined(ASM_X86_64)
00366 asm volatile(\
00367 "mov %[inv_A2_modp],%%edx \n\t" \
00368 "mov %[inv_A2_modp],%%eax \n\t" \
00369 "shr $16,%%edx \n\t" \
00370 "divw %%si \n\t" \
00371 "movzxw %%dx,%%ebx \n\t" \
00372 "mov %[PolyB],%%edx \n\t" \
00373 "movzxw %%dx,%%eax \n\t" \
00374 "shr $16,%%edx \n\t" \
00375 "divw %%si \n\t" \
00376 "movw %%dx,%%ax \n\t" \
00377 "mulw %%bx \n\t" \
00378 "divw %%si \n\t" \
00379 "mov %%ebx,%%eax \n\t" \
00380 "movzx %%dx,%%ebx \n\t" \
00381 "mulw (%[SQRTkN],%[i],4) \n\t" \
00382 "divw %%si \n\t" \
00383 "# %%edx and %%ebx are now swapped! \n\t" \
00384 "xorl %%eax,%%eax \n\t" \
00385 "negl %%ebx \n\t" \
00386 "addl %%edx,%%ebx \n\t" \
00387 "cmovsl %%esi,%%eax \n\t" \
00388 "addl %%eax,%%ebx \n\t" \
00389 "xorl %%eax,%%eax \n\t" \
00390 "movl %%ebx,(%[Deltas],%[i],8) \n\t" \
00391 "subl %%edx,%%ebx \n\t" \
00392 "cmovsl %%esi,%%eax \n\t" \
00393 "addl %%eax,%%ebx \n\t" \
00394 "xorl %%eax,%%eax \n\t" \
00395 "subl %%edx,%%ebx \n\t" \
00396 "cmovsl %%esi,%%eax \n\t" \
00397 "addl %%eax,%%ebx \n\t" \
00398 "movl %%ebx,4(%[Deltas],%[i],8) \n"
00399 :
00400 : "S" (PrimeNumbers[i]), [inv_A2_modp] "g" (inv_A2_modp),
00401 [PolyB] "g" (PolyB), [SQRTkN] "r" (&SQRT_kN_of_PrimeNumbers[0]),
00402 [Deltas] "r" (&Delta_of_PrimeNumbers[0][0]), [i] "r" (i)
00403 : "cc", "memory", "eax","ebx","edx");
00404 #elif 1 && defined(ASM_CMOV)
00405 asm volatile(\
00406 "mov %[inv_A2_modp],%%edx \n\t" \
00407 "mov %[inv_A2_modp],%%eax \n\t" \
00408 "shr $16,%%edx \n\t" \
00409 "divw %%si \n\t" \
00410 "movzxw %%dx,%%ebx \n\t" \
00411 "mov %[PolyB],%%edx \n\t" \
00412 "movzxw %%dx,%%eax \n\t" \
00413 "shr $16,%%edx \n\t" \
00414 "divw %%si \n\t" \
00415 "movw %%dx,%%ax \n\t" \
00416 "mulw %%bx \n\t" \
00417 "divw %%si \n\t" \
00418 "mov %%ebx,%%eax \n\t" \
00419 "movzx %%dx,%%ebx \n\t" \
00420 "mulw %[SQRTkN](,%[i],4) \n\t" \
00421 "divw %%si \n\t" \
00422 "# %%edx and %%ebx are now swapped! \n\t" \
00423 "xorl %%eax,%%eax \n\t" \
00424 "negl %%ebx \n\t" \
00425 "addl %%edx,%%ebx \n\t" \
00426 "cmovsl %%esi,%%eax \n\t" \
00427 "addl %%eax,%%ebx \n\t" \
00428 "xorl %%eax,%%eax \n\t" \
00429 "movl %%ebx,%[Deltas](,%[i],8) \n\t" \
00430 "subl %%edx,%%ebx \n\t" \
00431 "cmovsl %%esi,%%eax \n\t" \
00432 "addl %%eax,%%ebx \n\t" \
00433 "xorl %%eax,%%eax \n\t" \
00434 "subl %%edx,%%ebx \n\t" \
00435 "cmovsl %%esi,%%eax \n\t" \
00436 "addl %%eax,%%ebx \n\t" \
00437 "movl %%ebx,4+%[Deltas](,%[i],8) \n"
00438 :
00439 : "S" (PrimeNumbers[i]), [inv_A2_modp] "g" (inv_A2_modp),
00440 [PolyB] "g" (PolyB), [SQRTkN] "o" (SQRT_kN_of_PrimeNumbers[0]),
00441 [Deltas] "o" (Delta_of_PrimeNumbers[0][0]), [i] "r" (i)
00442 : "cc", "memory", "eax","ebx","edx");
00443 #else
00444 register signed int d = PolyB%PrimeNumbers[i];
00445 register signed int h = inv_A2_modp%PrimeNumbers[i];
00446 d=mulmod(d,h,PrimeNumbers[i]);
00447 h=mulmod(SQRT_kN_of_PrimeNumbers[i],h,PrimeNumbers[i]);
00448 d=-d; d+=h; if (d<0) d+=PrimeNumbers[i];
00449 Delta_of_PrimeNumbers[i][0]=d;
00450 d-=h; if (d<0) d+=PrimeNumbers[i];
00451 d-=h; if (d<0) d+=PrimeNumbers[i];
00452 Delta_of_PrimeNumbers[i][1]=d;
00453 #endif
00454
00455 #if 0 || defined(DEBUG)
00456
00457 Polynom.get_values(Delta_of_PrimeNumbers[i][0],x,y);
00458 if (mpz_mod_ui(y,y,PrimeNumbers[i])!=0)
00459 {
00460 cerr << "Delta0 " << Delta_of_PrimeNumbers[i][0] << " doesn't divide for "
00461 << PrimeNumbers[i] << "! (remainder: " << y << ")" << endl;
00462 Delta_of_PrimeNumbers[i][0]-=mpz_get_ui(y);
00463 if (Delta_of_PrimeNumbers[i][0]<0) Delta_of_PrimeNumbers[i][0]+=PrimeNumbers[i];
00464 }
00465 Polynom.get_values(Delta_of_PrimeNumbers[i][1],x,y);
00466 if (mpz_mod_ui(y,y,PrimeNumbers[i])!=0)
00467 {
00468 cerr << "Delta1 " << Delta_of_PrimeNumbers[i][1] << " doesn't divide for "
00469 << PrimeNumbers[i] << "! (remainder: " << y << ")" << endl;
00470 Delta_of_PrimeNumbers[i][1]-=mpz_get_ui(y);
00471 if (Delta_of_PrimeNumbers[i][1]<0) Delta_of_PrimeNumbers[i][1]+=PrimeNumbers[i];
00472 }
00473 #endif
00474 }
00475 }
00476
00477
00478
00479 for ( ; i<StaticFactorbase::Size(); ++i)
00480 {
00481
00482 inv_A2_modp=fastinvmod_23bit(get_A2_mod_FBPrime(i),PrimeNumbers[i]);
00483
00484 #ifdef DEBUG
00485 if ( (inv_A2_modp != fastinvmod(get_A2_mod_FBPrime(i),PrimeNumbers[i]))
00486 || (inv_A2_modp != fastinvmod(Polynom.get_A2_mod(PrimeNumbers[i]),PrimeNumbers[i])) )
00487 {
00488 MARK; cerr << "Inconsistency detected! please review source code!" << endl;
00489 cerr << "i=" << i << endl;
00490 cerr << "inv_A2_modp=" << inv_A2_modp << endl;
00491 cerr << "but using method 1 we get: " << fastinvmod(Polynom.get_A2_mod(PrimeNumbers[i]),PrimeNumbers[i]) << endl;
00492 cerr << "and using method 2 we get: " << fastinvmod(get_A2_mod_FBPrime(i),PrimeNumbers[i]) << endl;
00493 exit(2);
00494 }
00495 #endif
00496
00497 PolyB=mpz_remainder_ui(Polynom.get_B(),PrimeNumbers[i]);
00498
00499 register int d;
00500 d=SQRT_kN_of_PrimeNumbers[i]-PolyB; if (d<0) d+=PrimeNumbers[i];
00501 Delta_of_PrimeNumbers[i][0]=mulmod(d,inv_A2_modp,PrimeNumbers[i]);
00502
00503 d=PrimeNumbers[i]-SQRT_kN_of_PrimeNumbers[i]-PolyB; if (d<0) d+=PrimeNumbers[i];
00504 Delta_of_PrimeNumbers[i][1]=mulmod(d,inv_A2_modp,PrimeNumbers[i]);
00505
00506 #if 0 || defined(DEBUG)
00507
00508 Polynom.get_values(Delta_of_PrimeNumbers[i][0],x,y);
00509 if (mpz_mod_ui(y,y,PrimeNumbers[i])!=0)
00510 {
00511 cerr << "Delta0 " << Delta_of_PrimeNumbers[i][0] << " doesn't divide for "
00512 << PrimeNumbers[i] << "! (remainder: " << y << ")" << endl;
00513 Delta_of_PrimeNumbers[i][0]-=mpz_get_ui(y);
00514 if (Delta_of_PrimeNumbers[i][0]<0) Delta_of_PrimeNumbers[i][0]+=PrimeNumbers[i];
00515 }
00516 Polynom.get_values(Delta_of_PrimeNumbers[i][1],x,y);
00517 if (mpz_mod_ui(y,y,PrimeNumbers[i])!=0)
00518 {
00519 cerr << "Delta1 " << Delta_of_PrimeNumbers[i][1] << " doesn't divide for "
00520 << PrimeNumbers[i] << "! (remainder: " << y << ")" << endl;
00521 Delta_of_PrimeNumbers[i][1]-=mpz_get_ui(y);
00522 if (Delta_of_PrimeNumbers[i][1]<0) Delta_of_PrimeNumbers[i][1]+=PrimeNumbers[i];
00523 }
00524 #endif
00525 }
00526
00527
00528 for (int i=0; i<NumberOf_more_PrimePowers; ++i)
00529 {
00530
00531
00532
00533 inv_A2_modp=fastinvmod(Polynom.get_A2_mod(PrimePowers[i]),PrimePowers[i]);
00534 PolyB=mpz_remainder_ui(Polynom.get_B(),PrimePowers[i]);
00535
00536 register int d;
00537 d=SQRT_kN_of_PrimePowers[i]-PolyB; if (d<0) d+=PrimePowers[i];
00538 Delta_of_PrimePowers[i][0]=mulmod(d,inv_A2_modp,PrimePowers[i]);
00539
00540 d=PrimePowers[i]-SQRT_kN_of_PrimePowers[i]-PolyB; if (d<0) d+=PrimePowers[i];
00541 Delta_of_PrimePowers[i][1]=mulmod(d,inv_A2_modp,PrimePowers[i]);
00542 }
00543
00544 if (!DoReallyAll) goto done;
00545
00546
00547 #if 1
00548 for (int i=FB_maxQuadrate+1; i<StaticFactorbase::Size() && PrimeNumbers[i]<25000; ++i)
00549 {
00550 if (MPQS_Multiplier%PrimeNumbers[i]!=0)
00551 {
00552
00553
00554 const unsigned int P = PrimeNumbers[i]*PrimeNumbers[i];
00555 const unsigned int wuq = SQRT_kN_of_PrimeSquares[i];
00556 inv_A2_modp=fastinvmod(Polynom.get_A2_mod(P),P);
00557 PolyB=mpz_remainder_ui(Polynom.get_B(),P);
00558
00559
00560 signed int d = wuq>=PolyB ? wuq-PolyB : wuq-PolyB+P;
00561 d=mulmod(d,inv_A2_modp,P);
00562 d+=LogicalSieveSize; d%=P; d-=LogicalSieveSize;
00563 if (d<LogicalSieveSize)
00564 {
00565 TSieve_Delta sieb_delta;
00566 sieb_delta.factor=PrimeNumbers[i];
00567 sieb_delta.delta=d;
00568 Sieve_Delta_HeapOfSquares.push(sieb_delta);
00569
00570 #if defined(DEBUG)
00571 Polynom.get_values(sieb_delta.delta,x,y);
00572 if (!mpz_divisible_ui_p(y,P))
00573 {
00574 MARK; cerr << "wrong delta position for square!" << endl; exit(1);
00575 }
00576 #endif
00577 }
00578
00579
00580 unsigned int h = wuq+PolyB; d=P-mulmod(h,inv_A2_modp,P); d+=LogicalSieveSize; d%=P; d-=LogicalSieveSize;
00581 if (d<LogicalSieveSize)
00582 {
00583 TSieve_Delta sieb_delta;
00584 sieb_delta.factor=PrimeNumbers[i];
00585 sieb_delta.delta=d;
00586 Sieve_Delta_HeapOfSquares.push(sieb_delta);
00587
00588 #if defined(DEBUG)
00589 Polynom.get_values(sieb_delta.delta,x,y);
00590 if (!mpz_divisible_ui_p(y,P))
00591 {
00592 MARK; cerr << "wrong delta position for square!" << endl; exit(1);
00593 }
00594 #endif
00595 }
00596
00597 }
00598 }
00599 #endif
00600
00601
00602
00603 #ifdef SIEVING_LARGE_SQUARES
00604 for (int i=StaticFactorbase::Size()-1; i>FB_maxQuadrate && PrimeNumbers[i]>25000; --i)
00605 {
00606 if (MPQS_Multiplier%PrimeNumbers[i]!=0)
00607 {
00608
00609
00610 mpz_set_ui(P,PrimeNumbers[i]); mpz_mul(P,P,P);
00611 mpz_invert(inv_A2,Polynom.get_A2(),P);
00612
00613
00614
00615 const int Wu = SQRT_kN_of_PrimeNumbers[i];
00616 mpz_set_ui(y,2*Wu);
00617 if (mpz_invert(y,y,P)==0)
00618 {
00619 cerr << "PQ-root for " << PrimeNumbers[i] << ": inverse doesn't exist!" << endl;
00620 exit(1);
00621 }
00622
00623 mpz_mod(x,kN,P); mpz_set_ui(wuq,Wu); mpz_mul_ui(wuq,wuq,Wu); mpz_sub(x,x,wuq);
00624 mpz_mul(x,x,y); mpz_add_ui(x,x,Wu); mpz_mod(wuq,x,P);
00625
00626 #ifdef DEBUG
00627
00628 mpz_mul(x,wuq,wuq); mpz_sub(x,kN,x); mpz_mod(x,x,P);
00629 if (mpz_cmp_ui(x,0)!=0)
00630 {
00631 cerr << "PQ-root incorrect!" << endl;
00632 cerr << "Primzahl=" << PrimeNumbers[i] << endl;
00633 cerr << "kN= " << kN << endl;
00634 cerr << "SQRT(kN) mod p=" << SQRT_kN_of_PrimeNumbers[i] << endl;
00635 cerr << "SQRT(kN) mod p^2=" << wuq << endl;
00636 cerr << "but we got (wrong value): " << x << endl;
00637 exit(1);
00638 }
00639 #endif
00640
00641
00642
00643 mpz_sub(x,wuq,Polynom.get_B()); mpz_mul(x,x,inv_A2); mpz_add_ui(x,x,LogicalSieveSize); mpz_mod(x,x,P);
00644 mpz_sub_ui(x,x,LogicalSieveSize);
00645 if (mpz_cmp_ui(x,LogicalSieveSize)<=0)
00646 {
00647 TSieve_Delta sieb_delta;
00648 sieb_delta.factor=PrimeNumbers[i];
00649 sieb_delta.delta=mpz_get_si(x);
00650 Sieve_Delta_HeapOfSquares.push(sieb_delta);
00651
00652 #ifdef DEBUG
00653 Polynom.get_values(sieb_delta.delta,x,y);
00654 if (!mpz_divisible_p(y,P))
00655 {
00656 MARK; cerr << "wrong delta position for square!" << endl; exit(1);
00657 }
00658 #endif
00659 }
00660
00661
00662 mpz_add(x,wuq,Polynom.get_B()); mpz_neg(x,x); mpz_mul(x,x,inv_A2); mpz_add_ui(x,x,LogicalSieveSize); mpz_mod(x,x,P);
00663 mpz_sub_ui(x,x,LogicalSieveSize);
00664 if (mpz_cmp_ui(x,LogicalSieveSize)<=0)
00665 {
00666 TSieve_Delta sieb_delta;
00667 sieb_delta.factor=PrimeNumbers[i];
00668 sieb_delta.delta=mpz_get_si(x);
00669 Sieve_Delta_HeapOfSquares.push(sieb_delta);
00670
00671 #ifdef DEBUG
00672 Polynom.get_values(sieb_delta.delta,x,y);
00673 if (!mpz_divisible_p(y,P))
00674 {
00675 MARK; cerr << "wrong delta position for square!" << endl; exit(1);
00676 }
00677 #endif
00678 }
00679
00680 }
00681 }
00682 #endif
00683
00684
00685
00686 #ifdef SIEVING_MORE_LARGE_SQUARES
00687
00688 {
00689 unsigned int Primzahl = biggest_Prime_in_Factorbase;
00690 const unsigned int UpperLimit = 1000000;
00691 cout << "pushing more prime squares up to " << UpperLimit << endl;
00692 while (Primzahl<UpperLimit)
00693 {
00694 do
00695 {
00696 do Primzahl+=2;
00697 while( Primzahl%3==0 || Primzahl%5==0 || Primzahl%7==0
00698 || Primzahl%11==0 || Primzahl%13==0 || Primzahl%17==0
00699 || !probab_prime(Primzahl));
00700 mpz_set_ui(P,Primzahl);
00701 }
00702 while (mpz_legendre(kN,P)<0);
00703
00704 mpz_mul(P,P,P);
00705 mpz_invert(inv_A2,Polynom.get_A2(),P);
00706
00707
00708
00709 const int Wu = SQRT_kN_mod_PrimeNumber(Primzahl);
00710 mpz_set_ui(y,2*Wu);
00711 if (mpz_invert(y,y,P)==0)
00712 {
00713 cerr << "PQ-root for " << Primzahl << ": inverse doesn't exist!" << endl;
00714 exit(1);
00715 }
00716
00717 mpz_mod(x,kN,P); mpz_set_ui(wuq,Wu); mpz_mul_ui(wuq,wuq,Wu); mpz_sub(x,x,wuq);
00718 mpz_mul(x,x,y); mpz_add_ui(x,x,Wu); mpz_mod(wuq,x,P);
00719
00720 #ifdef DEBUG
00721
00722 mpz_mul(x,wuq,wuq); mpz_sub(x,kN,x); mpz_mod(x,x,P);
00723 if (mpz_cmp_ui(x,0)!=0)
00724 {
00725 cerr << "PQ-root incorrect!" << endl;
00726 cerr << "Primzahl=" << Primzahl << endl;
00727 cerr << "kN= " << kN << endl;
00728 cerr << "SQRT(kN) mod p=" << Wu << endl;
00729 cerr << "SQRT(kN) mod p^2=" << wuq << endl;
00730 cerr << "but we got (wrong value): " << x << endl;
00731 exit(1);
00732 }
00733 #endif
00734
00735
00736
00737 mpz_sub(x,wuq,Polynom.get_B()); mpz_mul(x,x,inv_A2); mpz_add_ui(x,x,LogicalSieveSize); mpz_mod(x,x,P);
00738 mpz_sub_ui(x,x,LogicalSieveSize);
00739 if (mpz_cmp_ui(x,LogicalSieveSize)<=0)
00740 {
00741 TSieve_Delta sieb_delta;
00742 sieb_delta.factor=Primzahl;
00743 sieb_delta.delta=mpz_get_si(x);
00744 Sieve_Delta_HeapOfSquares.push(sieb_delta);
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 if (!is_dynamic_factor(Primzahl)) Sieve_Delta_Heap.push(sieb_delta);
00758 #ifdef VERBOSE
00759 cout << "Pushed square of " << sieb_delta.factor << " (Delta1)!" << endl;
00760 #endif
00761 #ifdef DEBUG
00762 Polynom.get_values(sieb_delta.delta,x,y);
00763 if (!mpz_divisible_p(y,P))
00764 {
00765 MARK; cerr << "wrong delta position for square!" << endl; exit(1);
00766 } else { cout << "large square of " << Primzahl << " pushed and okay (delta1)" << endl; };
00767 #endif
00768 }
00769
00770
00771 mpz_add(x,wuq,Polynom.get_B()); mpz_neg(x,x); mpz_mul(x,x,inv_A2); mpz_add_ui(x,x,LogicalSieveSize); mpz_mod(x,x,P);
00772 mpz_sub_ui(x,x,LogicalSieveSize);
00773 if (mpz_cmp_ui(x,LogicalSieveSize)<=0)
00774 {
00775 TSieve_Delta sieb_delta;
00776 sieb_delta.factor=Primzahl;
00777 sieb_delta.delta=mpz_get_si(x);
00778 Sieve_Delta_HeapOfSquares.push(sieb_delta);
00779
00780 if (!is_dynamic_factor(Primzahl)) Sieve_Delta_Heap.push(sieb_delta);
00781 #ifdef VERBOSE
00782 cout << "Pushed square of " << sieb_delta.factor << " (Delta2)!" << endl;
00783 #endif
00784 #ifdef DEBUG
00785 Polynom.get_values(sieb_delta.delta,x,y);
00786 if (!mpz_divisible_p(y,P))
00787 {
00788 MARK; cerr << "wrong delta position for square!" << endl; exit(1);
00789 } else { cout << "large square of " << Primzahl << " pushed and okay (delta2)" << endl; };
00790 #endif
00791 }
00792
00793 }
00794 }
00795 #endif
00796
00797
00798 #if defined(VERBOSE) || defined(DEBUG)
00799 if (!Sieve_Delta_HeapOfSquares.empty())
00800 cout << Sieve_Delta_HeapOfSquares.size() << " squares have been pushed." << endl;
00801 #endif
00802
00803
00804 DynamicFactorArrays::compute_Deltas_for_DynamicFactors(-LogicalSieveSize);
00805
00806 done:
00807 mpz_clear(inv_A2); mpz_clear(P); mpz_clear(wuq); mpz_clear(x); mpz_clear(y);
00808
00809 }
00810
00811 namespace statistical_data
00812 {
00813 extern bool StatusReport(const bool force_now = false);
00814 }
00815
00816 void select_sieve_method();
00817 void (*do_sieving)() = select_sieve_method;
00818
00819 void do_sieving_partial_intervals()
00820 {
00821 const int ScanningRange = (5*LogicalSieveSize)/(16*PhysicalSieveSize);
00822 static signed int StartPSI[2];
00823 static unsigned int StopPSI[2];
00824 static int* HelperTables[2][2] = { {NULL,NULL}, {NULL,NULL} };
00825 static int* SieveImages[1024] = { 0 };
00826
00827 {
00828
00829
00830 static unsigned int counter = 1;
00831 if (--counter==0)
00832 {
00833 counter=0x20000;
00834 SieveControl::RecalibrateThresholds();
00835 cout << "Sieving partial intervals." << endl;
00836 for (int i=0; i<2; ++i)
00837 {
00838 StartPSI[i]=StopPSI[i]=SieveControl::BestPSI[i];
00839 StartPSI[i]-=ScanningRange; StopPSI[i]+=ScanningRange;
00840 if (StartPSI[i]<0) StartPSI[i]=0;
00841 if (StopPSI[i]>=2*static_cast<unsigned int>(LogicalSieveSize)/PhysicalSieveSize)
00842 {
00843 cout << "CUTTING RANGE!" << endl;
00844 StopPSI[i]=2*LogicalSieveSize/PhysicalSieveSize-1;
00845 }
00846 CSieveStaticFactors::create_Tables_for_init_LocalDeltas(HelperTables[i][0],HelperTables[i][1],-LogicalSieveSize+PhysicalSieveSize*StartPSI[i]);
00847 cout << "Physical intervals " << StartPSI[i] << " to " << StopPSI[i] << " marked for sieving." << endl;
00848 #if 0
00849 cout << "creating Threshold Sieve Image for Interval " << SieveControl::BestPSI[i] << endl;
00850 SieveControl::create_sieve_image(SieveImages[SieveControl::BestPSI[i]],-LogicalSieveSize+PhysicalSieveSize*SieveControl::BestPSI[i]);
00851 if (static_cast<unsigned int>(StartPSI[i]+1)<=SieveControl::BestPSI[i])
00852 {
00853 cout << "creating Threshold Sieve Image for Interval " << SieveControl::BestPSI[i]-1 << endl;
00854 SieveControl::create_sieve_image(SieveImages[SieveControl::BestPSI[i]-1],-LogicalSieveSize+PhysicalSieveSize*(SieveControl::BestPSI[i]-1));
00855 }
00856 if (SieveControl::BestPSI[i]+1<=StopPSI[i])
00857 {
00858 cout << "creating Threshold Sieve Image for Interval " << SieveControl::BestPSI[i]+1 << endl;
00859 SieveControl::create_sieve_image(SieveImages[SieveControl::BestPSI[i]+1],-LogicalSieveSize+PhysicalSieveSize*(SieveControl::BestPSI[i]+1));
00860 }
00861 #elif 1
00862 cout << "creating Threshold Sieve Image for Interval " << SieveControl::BestPSI[i] << endl;
00863 SieveControl::create_sieve_image(SieveImages[SieveControl::BestPSI[i]],-LogicalSieveSize+PhysicalSieveSize*SieveControl::BestPSI[i]);
00864 #endif
00865
00866 }
00867 }
00868 }
00869
00870 CDeltaComputations::recompute_all_Deltas(false);
00871
00872 for (int i=0; i<2; ++i)
00873 {
00874 SieveOffset=-LogicalSieveSize+PhysicalSieveSize*StartPSI[i];
00875 SieveControl::PhysicalSieveIntervalIndex=StartPSI[i];
00876 CSieveStaticFactors::init_LocalDeltas(HelperTables[i][0],HelperTables[i][1]);
00877 while (SieveControl::PhysicalSieveIntervalIndex<=StopPSI[i])
00878 {
00879
00880 if (SieveImages[SieveControl::PhysicalSieveIntervalIndex<=StopPSI[i]])
00881 initialize_Sieve(SieveImages[SieveControl::PhysicalSieveIntervalIndex]);
00882 else
00883 initialize_Sieve();
00884 CSieveStaticFactors::do_sieving_StaticFactors();
00885 do_scanning_Sieve();
00886 SieveOffset+=PhysicalSieveSize;
00887 SieveControl::PhysicalSieveIntervalIndex++;
00888 }
00889 }
00890 statistical_data::StatusReport();
00891
00892
00893 if (DynamicFactorArrays::DYNFB_threshold<0.0) do_sieving=do_sieving_full_intervals;
00894
00895 }
00896
00897 void do_sieving_full_intervals()
00898 {
00899 SieveOffset=-LogicalSieveSize;
00900 SieveControl::PhysicalSieveIntervalIndex=0;
00901
00902 #if 1
00903 {
00904
00905
00906 static unsigned int counter = 1;
00907 if (--counter==0)
00908 {
00909 counter=0x20000;
00910 statistical_data::StatusReport(true);
00911 SieveControl::RecalibrateThresholds();
00912 cout << "Sieving complete intervals." << endl;
00913 }
00914 }
00915 #endif
00916
00917 CDeltaComputations::recompute_all_Deltas();
00918 #ifdef USE_FAKEHEAP
00919 Sieve_Delta_Heap.sort();
00920 #endif
00921 CSieveStaticFactors::init_LocalDeltas(CSieveStaticFactors::DefaultHelperTable[0],CSieveStaticFactors::DefaultHelperTable[1]);
00922
00923 while (SieveOffset<LogicalSieveSize)
00924 {
00925 initialize_Sieve();
00926 CSieveStaticFactors::do_sieving_StaticFactors();
00927 do_sieving_Squares();
00928 do_sieving_DynamicFactors();
00929 do_scanning_Sieve();
00930 SieveOffset+=PhysicalSieveSize;
00931 SieveControl::PhysicalSieveIntervalIndex++;
00932 }
00933 statistical_data::StatusReport();
00934 }
00935
00936
00937 void select_sieve_method()
00938 {
00939 cout << "QSieve sieve method selector called." << endl;
00940
00941
00942
00943
00944
00945
00946 DynamicFactorArrays::DYNFB_threshold=4.0*2097152.0*StaticFactorbaseSettings::Size()/StaticFactorbaseSettings::BiggestPrime();
00947
00948 if (mpz_sizeinbase(n,10)<60)
00949 {
00950 do_sieving=do_sieving_full_intervals;
00951 }
00952 else
00953 {
00954 do_sieving=do_sieving_partial_intervals;
00955 if (mpz_sizeinbase(n,10)<100) DynamicFactorArrays::DYNFB_threshold*=5.0;
00956 if (mpz_sizeinbase(n,10)>105) DynamicFactorArrays::DYNFB_threshold/=5.0;
00957 }
00958 do_sieving();
00959 }