Sieving-inc.cc

Go to the documentation of this file.
00001 
00007 #include "mpqsPolynom.H"
00008 extern CmpqsPolynom Polynom; // object to manage polynomial computations for multipolynomial sieve (MPQS)
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   // this is for much faster access to the data
00032   // (in streaming manner, possibly using SSE instructions!)
00033   const unsigned int MaxDynamicFactors = 2500000;
00034   static int DynFactors[MaxDynamicFactors]; // write once (per entry) - read many access
00035   static int DynFactorReciprocals[MaxDynamicFactors]; // write once (per entry) - read many access
00036   static int SQRT_kNs[MaxDynamicFactors]; // write once (per entry) - read many access
00037   static signed int PolyDs[MaxDynamicFactors]; // read/write many access
00038 
00039   unsigned int DynamicFactorsInUse = 0; // already declared in Sieving.H
00040   double DYNFB_threshold = 0.0; // already declared in Sieving.H
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            //cout << "get MPQS-PolyD for dynamic factor " << DynFac << endl;
00061            PolyDs[i]=mpz_remainder_ui(Polynom.get_D(),DynFac);
00062         }
00063        else
00064         {
00065            //cout << "updating MPQS-PolyD for dynamic factor " << DynFac << endl;
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) // shortcut: only re-insert, if still inside the sieve interval!
00079         {
00080           Sieve_Delta_Heap.push(sieb_delta);
00081           sieb_delta.delta+=sieb_delta.factor;
00082         }
00083      #else
00084        if (sieb_delta.delta<=LogicalSieveSize) // shortcut: only re-insert, if still inside the sieve interval!
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) ) // shortcut: only re-insert, if still inside the sieve interval!
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 } // end of namespace DynamicFactorArrays
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; //exit(19);
00116    }
00117 
00118   // if we use partial sieving, then we cannot be sure, that a
00119   // already known dynamic factor gets redetected: redetected dynamic factors
00120   // *must not* appended again!!
00121   // we could avoid this check for the "complete interval sieving", but I doubt that
00122   // this saves us much time...
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; // don't append this dynamic factor twice...
00129    }
00130   DynFactors[DynamicFactorsInUse] = DynFac;
00131   DynFactorReciprocals[DynamicFactorsInUse] = numtheory::reciprocal(DynFac);
00132   SQRT_kNs[DynamicFactorsInUse]=SQRT_kN_mod_PrimeNumber(DynFac);
00133   PolyDs[DynamicFactorsInUse]=-1; // tripper update at first access
00134   ++DynamicFactorsInUse; // now we have one more in use
00135 
00136   DYNFB_threshold-=(4.0*LogicalSieveSize)/DynFac;
00137   //if ((DynamicFactorsInUse&255)==255) cout << "#DYNFB: " << DynamicFactorsInUse << ", countdown now: " << DYNFB_threshold << endl;
00138 }
00139 
00140 
00141 
00142 void do_sieving_Squares()
00143 {
00144   // Sieve squares of static (and dynamic) factors.
00145   // Important: Only subtract the single logarithm of the factors
00146   //            (because if a square divides, then the factor has divided already!)
00147   // Remark: To be more efficient, at most one hit in the sieve interval
00148   //         is considered.
00149 
00150   //cout << "Start sieving squares" << endl;
00151   if (Sieve_Delta_HeapOfSquares.empty()) return; // there's nothing to sieve...
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) // do we need to skip any factors? (for partial sieving!)
00157     {
00158       cout << "sieving squares: " << sieb_delta.factor << " skipped!" << endl;
00159       Sieve_Delta_HeapOfSquares.pop(); // pop element out of priority queue
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(); // pop element out of priority queue
00169       SieveArray[delta]-=log_DynamicLargePrime(sieb_delta.factor); // mark factor at sieve position
00170       if (Sieve_Delta_HeapOfSquares.empty()) break;
00171       sieb_delta = Sieve_Delta_HeapOfSquares.top();
00172       delta = sieb_delta.delta-SieveOffset;
00173     }
00174   //cout << "Finished sieving squares" << endl;
00175 }
00176 
00177 
00178 // new version, patch contributed by Alexis Michon
00179 void do_sieving_DynamicFactors()
00180 {
00181   if (Sieve_Delta_Heap.empty()) return; // there's nothing to sieve...
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) // do we need to skip any factors? (for partial sieving!)
00189     {
00190       cout << "sieving dynamic factors: " << sieb_delta.factor << " skipped!" << endl;
00191       Sieve_Delta_Heap.pop(); // pop element out of priority queue
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) // still in the current (physical) interval?
00199   {
00200         Sieve_Delta_Heap.pop(); // pop element out of priority queue
00201         SieveArray[delta]-=log_DynamicLargePrime(sieb_delta.factor); // mark factor at sieve position
00202   
00203         // to speedup refactorization of relations, a dynamic factor hit is memorized here
00204         Hits[HitCount].Faktor=sieb_delta.factor;
00205 
00206 #ifdef USE_FAKEHEAP
00207         if (Sieve_Delta_Heap.empty()) 
00208         {
00209                 if (SieveArray[delta]<0) // found a (possible) relation?
00210                 if (SieveControl::Hit_after_DirtyCorrection(delta+SieveOffset,SieveArray[delta]))
00211                 {
00212                         SieveArray[delta]=1; // stall further hits at this position...
00213                         StaticRelations::insert(new CRelation(delta+SieveOffset,HitCount+1)); // and insert as a hit
00214                 }
00215                 return;
00216         }
00217 #else
00218         sieb_delta.delta += sieb_delta.factor; // next hit-position
00219         if (sieb_delta.delta<=LogicalSieveSize) // shortcut: push only, if it will be inside the sieve interval
00220         {
00221                 Sieve_Delta_Heap.push(sieb_delta); // pushing to priority queue again
00222         }
00223         else
00224         if (Sieve_Delta_Heap.empty()) 
00225         {
00226                 if (SieveArray[delta]<0) // found a (possible) relation?
00227                  if (SieveControl::Hit_after_DirtyCorrection(delta+SieveOffset,SieveArray[delta]))
00228                  {
00229                         SieveArray[delta]=1; // stall further hits at this position...
00230                         StaticRelations::insert(new CRelation(delta+SieveOffset,HitCount+1)); // and insert as a hit
00231                  }
00232                 return;
00233         }
00234 #endif
00235   
00236         sieb_delta = Sieve_Delta_Heap.top(); // get next entry out of the priority queue
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) // found a (possible) relation?
00247          if (SieveControl::Hit_after_DirtyCorrection(delta+SieveOffset,SieveArray[delta]))
00248          {
00249                 SieveArray[delta]=1; // stall further hits at this position...
00250                 StaticRelations::insert(new CRelation(delta+SieveOffset, HitCount+1)); // and insert as a hit
00251          }
00252         delta=delta2;
00253         HitCount=0; // reset HitCount for next hit
00254   }
00255   return; // done with this interval
00256 }
00257 
00258 
00259 
00260 #if 0
00261 #include <map>
00262 void Werteverteilung_im_Sieb_ausgeben(void)
00263 {
00264   // if you want to view more stats, you can use this function
00265   // to get the distribution of hits in the sieve
00266   // (don't activate this for "production use", as this is very slow!)
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 /* =true */)
00287 {
00288   // While changing polynomials, the old Deltavalues get void.
00289   // They must be recomputed.
00290 
00291   //cout << "recomputing deltas" << endl;
00292 
00293   // at first, remove any (possible remaining) dynamic factors from the queue:
00294 #ifdef USE_FAKEHEAP
00295 //  cout << "clearing Fakeheap with " << Sieve_Delta_Heap.size() << " elements..." << endl;
00296   Sieve_Delta_Heap.clear();
00297 #else
00298   while (!Sieve_Delta_Heap.empty()) Sieve_Delta_Heap.pop(); // for priority_queue (in case that no clear-method is defined)
00299 #endif
00300 
00301   // do the same with squares:
00302   //Sieve_Delta_HeapOfSquares.clear();
00303   while (!Sieve_Delta_HeapOfSquares.empty()) Sieve_Delta_HeapOfSquares.pop(); // for priority_queue (in case that no clear-method is defined)
00304  
00305   
00306   // first, compute the Deltas in/of the static factorbase
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   // for computing Deltas, we need to query the mpqs coefficient "A2" and
00313   // compute "A2 mod p", if we want to sieve with p. This is slow. 
00314   // For gods sake we can do it much faster:
00315   mpqsDmodPUpdater.update();
00316    // .. and now the new A2's are available via "CDeltaComputations::get_A2_mod_FBPrime(int Nr)"
00317    // instead of the more slowly version "Polynom.get_A2_mod(const unsigned int m)"
00318 
00319 
00320   // factorbase: compute first sieve hit; ignore primenumber 2, because computation of root for this value is too complicated...
00321   // ignore PrimeNumbers[0]==-1 because of sign
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) // do the paired part (magic 46340 is sqrt(2^31))
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]; // = PrimeNumbers[i]*PrimeNumbers[i+1];
00358       inv_A2_modp=fastinvmod(get_A2_mod_FBPrimePair(i),N); // fast version
00359       //inv_A2_modp=fastinvmod(Polynom.get_A2_mod(N),N); // slow version
00360       PolyB=mpz_remainder_ui(Polynom.get_B(),N);
00361       //cout << "paired: i=" << i << " N=" << N << endl;
00362 
00363       for (signed int j=2; --j>=0; ++i) // this is no typo, it's really ++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           : /* empty output list, we're writing to memory */
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           : /* empty output list, we're writing to memory */
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          // we may want to check, whether above computations are valid:
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   // it guaranteed here that i%2=0
00477 
00478   // factorbase: compute first sieve hit (unpaired part)
00479   for ( ; i<StaticFactorbase::Size(); ++i) // do the unpaired part
00480     {
00481       //inv_A2_modp=fastinvmod(Polynom.get_A2_mod(PrimeNumbers[i]),PrimeNumbers[i]); // slow version
00482       inv_A2_modp=fastinvmod_23bit(get_A2_mod_FBPrime(i),PrimeNumbers[i]); // fast version
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       // we may want to check, whether above computations are valid:
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       // compute Deltas for these numbers (which are powers of prime numbers of the factorbase)
00531       // (and sieve them together with the static factors)
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 /* Test!!!! 2004-03-09 */
00548   for (int i=FB_maxQuadrate+1; i<StaticFactorbase::Size() && PrimeNumbers[i]<25000; ++i)
00549     {
00550       if (MPQS_Multiplier%PrimeNumbers[i]!=0)
00551         {
00552           // For all/some "large" squares of the factorbase we determine the Deltas,
00553           // but these squares are sieved in conjunction with the dynamic factors.
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           // Delta1
00560           signed int d = wuq>=PolyB ? wuq-PolyB : wuq-PolyB+P; // overflow?
00561           d=mulmod(d,inv_A2_modp,P);
00562           d+=LogicalSieveSize; d%=P; d-=LogicalSieveSize;
00563           if (d<LogicalSieveSize) // value in interval?
00564             {
00565               TSieve_Delta sieb_delta;
00566               sieb_delta.factor=PrimeNumbers[i];
00567               sieb_delta.delta=d;
00568               Sieve_Delta_HeapOfSquares.push(sieb_delta); // and store
00569               //cout << "Square of " << sieb_delta.factor << " pushed!" << endl;
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                } //else { cout << "square of " << sieb_delta.factor << " pushed and okay (delta1)" << endl; };
00576 #endif
00577             }
00578 
00579           // Delta2
00580           unsigned int h = wuq+PolyB; d=P-mulmod(h,inv_A2_modp,P); d+=LogicalSieveSize; d%=P; d-=LogicalSieveSize;
00581           if (d<LogicalSieveSize) // value in interval?
00582             {
00583               TSieve_Delta sieb_delta;
00584               sieb_delta.factor=PrimeNumbers[i];
00585               sieb_delta.delta=d;
00586               Sieve_Delta_HeapOfSquares.push(sieb_delta); // and store
00587               //cout << "Square of " << sieb_delta.factor << " pushed!" << endl;
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                } //else { cout << "square of " << sieb_delta.factor << " pushed and okay (delta2)" << endl; };
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           // For all "large" squares of the factorbase we determine the Deltas,
00609           // but these squares are sieved in conjunction with the dynamic factors.
00610           mpz_set_ui(P,PrimeNumbers[i]); mpz_mul(P,P,P); // get square of the prime number
00611           mpz_invert(inv_A2,Polynom.get_A2(),P);
00612 
00613           // now compute square roots modulo P (these values are not memorized; this would take too much space)
00614           // compute square roots of kN modulo Primzahl^2
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           // we may want to check, whether above computations are valid:
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           // and now the Deltas:
00641 
00642           // Delta1
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) // does the value lie in the interval?
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); // and store
00651               //cout << "Square of " << sieb_delta.factor << " pushed!" << endl;
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                } //else { cout << "square of " << sieb_delta.factor << " pushed and okay (delta1)" << endl; };
00658 #endif
00659             }
00660           
00661           // Delta2
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) // value inside interval?
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); // and store
00670               //cout << "Square of " << sieb_delta.factor << " pushed!" << endl;
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                } //else { cout << "square of " << sieb_delta.factor << " pushed and okay (delta2)" << endl; };
00677 #endif
00678             }
00679           
00680         }
00681     }
00682 #endif
00683 
00684   
00685 
00686 #ifdef SIEVING_MORE_LARGE_SQUARES
00687   // and push more squares outside of the static factorbase:
00688   {
00689     unsigned int Primzahl = biggest_Prime_in_Factorbase;
00690     const unsigned int UpperLimit = 1000000; // or maybe 4*biggest_Prime_in_Factorbase;
00691     cout << "pushing more prime squares up to " << UpperLimit << endl; 
00692     while (Primzahl<UpperLimit)
00693      {
00694        do // compute next prime number of the static factorbase
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)); // next prime number
00700           mpz_set_ui(P,Primzahl);
00701         }
00702        while (mpz_legendre(kN,P)<0); // prime number valid for factorbase?
00703 
00704        mpz_mul(P,P,P); // compute square
00705        mpz_invert(inv_A2,Polynom.get_A2(),P);
00706 
00707        // now compute square roots modulo P (these values are not memorized; this would take too much space)
00708        // compute square roots of kN modulo Primzahl^2
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        // we may want to check, whether above computations are valid:
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        // and now compute the Deltas:
00735 
00736        // Delta1
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) // value inside interval?
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); // and store
00745 
00746           // IMPORTANT: The prime number will be placed into Sieve_Delta_HeapOfSquares *and*
00747           // additionally into Sieve_Delta_Heap (if it is a square of a unknown/unresolved dynamic factor).
00748           // Please remember: Known dynamic factors will be sieved anyway, so sieving two times again
00749           // for squares should be avoided.
00750           // Doing this, we can assure, that
00751           //  - the value (factor instead of factor^2) fits into integer range,
00752           //  - the value is hitting twice (as square) inside the sieve.
00753           // The (possible) effect, that a square is counted with 3 hits remains still possible (whenever
00754           // a new dynamic factor is detected during sieving and deactivated FAKEHEAP), but this case
00755           // is unlikely and harmless. (In the worst case a non-relation will falsely be considered as
00756           // a relation and rejected afterwards.)
00757           if (!is_dynamic_factor(Primzahl)) Sieve_Delta_Heap.push(sieb_delta); // and store
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        // Delta2
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) // value inside interval?
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); // and push into priority queue
00779           // see remark for Delta1
00780           if (!is_dynamic_factor(Primzahl)) Sieve_Delta_Heap.push(sieb_delta); // push into priority queue
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   // and now do the same computations for dynamic factorbase:
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  // cout << "Finished computation of Deltas." << endl;
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]; // contains starting indices
00823   static unsigned int StopPSI[2]; // contains stopping indices
00824   static int* HelperTables[2][2] = { {NULL,NULL}, {NULL,NULL} };
00825   static int* SieveImages[1024] = { 0 };
00826 
00827   {
00828     // this blocks triggers recalibration of sieving thresholds
00829     // from time to time.
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         //cout << "Sieving Interval: " << SieveOffset << endl;
00880         if (SieveImages[SieveControl::PhysicalSieveIntervalIndex<=StopPSI[i]])
00881           initialize_Sieve(SieveImages[SieveControl::PhysicalSieveIntervalIndex]);
00882         else
00883           initialize_Sieve();
00884         CSieveStaticFactors::do_sieving_StaticFactors(); // with primes out of the static factorbase
00885         do_scanning_Sieve();
00886         SieveOffset+=PhysicalSieveSize;
00887         SieveControl::PhysicalSieveIntervalIndex++;
00888       }
00889    }
00890   statistical_data::StatusReport(); // issue information to screen (don't remove this, it triggers some other stats, too!)
00891 
00892   // decide when to switch to complete interval sieving mode:
00893   if (DynamicFactorArrays::DYNFB_threshold<0.0) do_sieving=do_sieving_full_intervals;
00894   //if ( DynamicFactorRelations.size() > 8*static_cast<unsigned int>(StaticFactorbase::Size()) ) do_sieving=do_sieving_full_intervals;
00895 }
00896 
00897 void do_sieving_full_intervals()
00898 {
00899   SieveOffset=-LogicalSieveSize;
00900   SieveControl::PhysicalSieveIntervalIndex=0;
00901 
00902 #if 1
00903   {
00904     // this blocks triggers recalibration of sieving thresholds
00905     // from time to time.
00906     static unsigned int counter = 1;
00907     if (--counter==0)
00908      { 
00909        counter=0x20000;
00910        statistical_data::StatusReport(true); // issue information to screen (don't remove this, it triggers some other stats, too!)
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   //CSieveStaticFactors::init_LocalDeltas(); // or use this deprecated function, if memory access is slower (due to cache pollution) than computing thousands of mulmods!
00923   while (SieveOffset<LogicalSieveSize)
00924    {
00925      initialize_Sieve();
00926      CSieveStaticFactors::do_sieving_StaticFactors(); // with primes out of the static factorbase
00927      do_sieving_Squares(); // (bigger) squares of primes of the static factorbase
00928      do_sieving_DynamicFactors(); // sieve with active single large primes (=dynamic factors)
00929      do_scanning_Sieve();
00930      SieveOffset+=PhysicalSieveSize;
00931      SieveControl::PhysicalSieveIntervalIndex++;
00932    }
00933   statistical_data::StatusReport(); // issue information to screen (don't remove this, it triggers some other stats, too!)
00934 }
00935 
00936 
00937 void select_sieve_method()
00938 {
00939   cout << "QSieve sieve method selector called." << endl;
00940 
00941   // try calculate a good threshold for switching from partial sieving to complete sieving:
00942   // - the logical sieve interval is [-LogicalSieveSize ... LogicalSieveSize] -> *2
00943   // - two hits per prime number -> *2
00944   // - the larger the logical sieve interval, the less costs for switching polynomials -> 2^21 as reference interval size
00945   // - we want that the dynamic Factorbase has roughly the same quality as the static factorbase
00946   DynamicFactorArrays::DYNFB_threshold=4.0*2097152.0*StaticFactorbaseSettings::Size()/StaticFactorbaseSettings::BiggestPrime();
00947 
00948   if (mpz_sizeinbase(n,10)<60) // for small numbers we use full intervals!
00949    {
00950      do_sieving=do_sieving_full_intervals;
00951    }
00952   else // for large numbers we start with sieving partial intervals
00953    {
00954      do_sieving=do_sieving_partial_intervals;
00955      if (mpz_sizeinbase(n,10)<100) DynamicFactorArrays::DYNFB_threshold*=5.0; // high threshold avoids sieving complete intervals
00956      if (mpz_sizeinbase(n,10)>105) DynamicFactorArrays::DYNFB_threshold/=5.0; // low threshold (use partial intervals only to collect dynamic factors for starting the chain reaction)
00957    }
00958   do_sieving();
00959 }

Generated on Wed Nov 7 23:29:26 2007 for Qsieve by  doxygen 1.5.4