CRelation-inc.cc

Go to the documentation of this file.
00001 
00007 inline CRelation::ProvideDynamicRelationsStream::ProvideDynamicRelationsStream(Pistream &pistream_)
00008  : pistream(pistream_), reuse(true)
00009 {
00010   if (!pistream)
00011    {
00012      //cout << "acquired an istream!" << endl;
00013      pistream=DynamicRelations::IstreamPool::acquire_istream();
00014      reuse=false;
00015    } //else cout << "reusing an istream!" << endl;
00016 }
00017 
00018 inline CRelation::ProvideDynamicRelationsStream::~ProvideDynamicRelationsStream()
00019 {
00020   if (!reuse)
00021    {
00022      DynamicRelations::IstreamPool::release_istream(pistream);
00023      pistream=NULL;
00024    }
00025 }
00026 
00027 
00028 
00029 
00030 // this is used to store the sieved dynamic factors.
00031 // Remark: To collect the dynamic factors efficiently in the sieving phase, I decided to make this array global.
00032 //         (The constructor of "CRelation" is called with the number of found dynamic factors for each relation.)
00033 CHits Hits[CHits::MaxHits]; // collected dynamic factors
00034 
00035 // important: The exponent need not to (and shouldn't) be set during the sieving phase. It will be evaluated
00036 // inside the constructor (and only there!) while the relation is split into its factors.
00037 // Also keep in mind not to place any composite numbers as factors into this struct.
00038 
00039 
00040 #ifndef IS_SERVER
00041 
00042 CRelation::CRelation(const signed int SievePos, short int HitCount /* =0 */)
00043 : CProvideHelperVariables(), relevant_factor(no_factor), Relation_sparse(new CTinyFBsizetypeVector), Relation_dense(NULL),
00044   pDynamicRelations_from_file(NULL), pMulticombineData(NULL)
00045   /* constructor: insert a new relation.
00046      initialize "Deltas" with the value of Delta,
00047      (re)split the relation into its factors; thereby pick up only the factors, whose exponents are odd
00048      (if the exponent is even, then the factor can be replaced by factor^2 and thereby be handled as a square!)
00049    */
00050 {
00051   // cout << "initialize relation" << endl;
00052   mpz_init(Delta);
00053   Polynom.get_values(SievePos,Delta,y);
00054   // in y: reduced square (which is now to be factorized...) 
00055   mpz_invert(Delta,Delta,n); /* we use the modular inverse of Delta,
00056                                 this saves us an extra variable;
00057                                 doing so, the quadratic congruence
00058                                 is normalized to Delta^2=1 (mod n)
00059                               */
00060   
00061   if (mpz_sgn(y)<0) // negative numbers (handle sign)
00062     {
00063       Relation_sparse->append(0);
00064        // -1 must be considered to handle the sign;
00065        // we have to insert a "0", because StaticFactorbase::PrimeNumbers[0]=-1.
00066       mpz_neg(y,y); // switch sign (to make positive)
00067     }
00068   
00069   // special handling for the first factor of the static factorbase.
00070   // In MPQS we have problems to sieve for prime number 2...
00071 
00072   if (StaticFactorbase::PrimeNumbers[1]==2)
00073    {
00074      // special treatment for 2, since it it very easy:
00075      const unsigned int z = mpz_scan1(y,0);
00076      if (z)
00077       {
00078         mpz_tdiv_q_2exp(y,y,z);
00079         mpz_mul_2exp(Delta,Delta,z>>1);
00080         if (z&1) Relation_sparse->append(1); // mark odd exponent of the prime number
00081       }
00082    }
00083   else
00084    {
00085      // this is the common case (which works also for 2)  
00086      unsigned int z=0;
00087      while (mpz_div_ui(x,y,StaticFactorbase::PrimeNumbers[1])==0) { mpz_set(y,x); z++; }
00088 
00089      if (z&1) Relation_sparse->append(1); // mark odd exponent of the prime number
00090      if (z>1) // need to multiply "valid square roots" into Delta?
00091       {
00092         if (z<4) mpz_mul_ui(Delta,Delta,StaticFactorbase::PrimeNumbers[1]);
00093         else
00094          {
00095            mpz_set_ui(x,StaticFactorbase::PrimeNumbers[1]); mpz_powm_ui(x,x,z/2,n);
00096            mpz_mul(Delta,Delta,x);
00097          }
00098       }
00099    }
00100 
00101   {
00102     // find factors in static factorbase
00103     // (beginning with the 3. prime of FB (s.o) )
00104     vector<unsigned int> FB_Primteiler;
00105     CDeltaComputations::GetStaticFactorHits(FB_Primteiler,SievePos);
00106 
00107     // multiply factors to collect them, and then divide them in one go
00108     mpz_set_ui(x,1);
00109     for (unsigned int i=0; i<FB_Primteiler.size(); i++) mpz_mul_ui(x,x,StaticFactorbase::PrimeNumbers[FB_Primteiler[i]]);
00110     mpz_divexact(y,y,x);
00111 
00112     // factor reduction using the principle of inclusion/exclusion
00113     // die Faktor-Potenzen nach dem Prinzip Inklusion/Exklusion abdividieren
00114     vector<unsigned int> WithOddExponent, TempTeiler;
00115     while (mpz_cmp_ui(x,1)>0) // is there a factor from our FB?
00116      {
00117        mpz_gcd(x,x,y); // prime numbers of FB, that divide a even number of times
00118        mpz_divexact(y,y,x); // divide by them
00119        mpz_mul(Delta,Delta,x); // multiply them to our square root Delta
00120        for (unsigned int i=0; i<FB_Primteiler.size(); ++i)
00121         if (mpz_divisible_ui_p(x,StaticFactorbase::PrimeNumbers[FB_Primteiler[i]]))
00122           TempTeiler.push_back(FB_Primteiler[i]); // will divide again...
00123         else
00124           WithOddExponent.push_back(FB_Primteiler[i]); // this was the last time that it divided.
00125        FB_Primteiler.swap(TempTeiler); TempTeiler.clear();
00126 
00127        mpz_gcd(x,x,y); mpz_divexact(y,y,x); // odd number of times
00128        for (unsigned int i=0; i<FB_Primteiler.size(); ++i)
00129         if (mpz_divisible_ui_p(x,StaticFactorbase::PrimeNumbers[FB_Primteiler[i]]))
00130           TempTeiler.push_back(FB_Primteiler[i]); // will divide again
00131        FB_Primteiler.swap(TempTeiler); TempTeiler.clear();
00132      }
00133     mpz_mod(Delta,Delta,n);
00134     std::sort(WithOddExponent.begin(),WithOddExponent.end());
00135     for (unsigned int i=0; i<WithOddExponent.size(); ++i)
00136      {
00137        Relation_sparse->append(WithOddExponent[i]);
00138      }
00139   }
00140 
00141 
00142   // reduce factors from dynamic factorbase (and maybe pushed squares...)
00143   // multiply the factors together and divide them in one go.
00144   if (HitCount)
00145    {
00146      mpz_set_ui(x,Hits[0].Faktor); Hits[0].Exponent = 1;
00147      for (int i=1; i<HitCount; i++) { Hits[i].Exponent = 1; mpz_mul_ui(x,x,Hits[i].Faktor); }
00148 #if defined(DEBUG)
00149      if (!mpz_divisible_p(y,x)) { MARK; cerr << "Wrong divisor in Hits!" << endl; exit(1); }
00150 #endif
00151      mpz_divexact(y,y,x);
00152      mpz_gcd(x,x,y);
00153      if (mpz_cmp_ui(x,1)!=0) // are there higher exponents?
00154       {
00155         // find exponents of factors in dynamic factorbase (and maybe pushed squares...)
00156         for (int i=0; i<HitCount; ++i)
00157          {
00158            while (mpz_divisible_ui_p(y,Hits[i].Faktor))
00159             {
00160               mpz_divexact_ui(y,y,Hits[i].Faktor);
00161               Hits[i].Exponent++; // increment exponent of factor
00162             }
00163 #ifdef DEBUG
00164            if (Hits[i].Exponent==2)
00165             {
00166               MARK;
00167               cout << "Square in Hits[]: " << Hits[i].Faktor;
00168               if (is_dynamic_factor(Hits[i].Faktor))
00169                cout << " (dynamic factor)" << endl;
00170               else
00171                cout << " (pushed square)" << endl;
00172             }
00173 #endif
00174            if (Hits[i].Exponent>1)
00175             {
00176               mpz_set_ui(x, Hits[i].Faktor);
00177               mpz_powm_ui(x,x,Hits[i].Exponent/2, n);
00178               mpz_mul(Delta,Delta,x); mpz_mod(Delta,Delta,n);
00179               Hits[i].Exponent%=2;
00180             }
00181          }
00182       }
00183    }
00184 
00185   // Restfactor outside of the static factorbase...
00186   const bool existiert_grosser_Restfaktor = (mpz_cmp_ui(y,StaticFactorbaseSettings::BiggestPrime())>0);
00187 
00188   if (existiert_grosser_Restfaktor && collecting_phase_finished)
00189     { relevant_factor=special_factor; return; } // premature cancellation
00190 
00191   if (!existiert_grosser_Restfaktor)
00192     {
00193       if (mpz_cmp_ui(y,1)!=0) 
00194         {
00195           MARK;
00196           cerr << "relation is inconsistent / BUG in program:" << endl;
00197           cerr << y << " should be 1!" << endl;
00198           exit(1);
00199         }
00200       relevant_factor=largest_factor_in_Relation();
00201       // relevant factor can be eliminated later (by utilizing this relation)
00202     }
00203 
00204 #if 0 || defined(SIEVING_MORE_LARGE_SQUARES)
00205   // dynamic factor sanity check
00206   for (int i=0; i<HitCount; ++i) if(Hits[i].Exponent!=0)
00207     {
00208       if (!is_dynamic_factor(Hits[i].Faktor))
00209         {
00210           cerr << "Inconsistency in dynamic factorbase! " << Hits[i].Faktor << " not found as known dynamic factor!" << endl;
00211           // This is actually an error OR the radix of a pushed square has
00212           // divided with an odd number of times, and the radix isn't a SLP
00213           // yet (so we cannot resolve the resulting relation to a static,
00214           // dynamic or special relation).  This shouldn't happen too often,
00215           // but it can happen.  Since this is unlikely, we can exit with an
00216           // error to watch this special case instead of just skipping the
00217           // relation.
00218           exit(1); // not necessary, because it should also be safe just to skip this relation
00219           relevant_factor=dynamic_factor; return; // skip the relation
00220         }
00221     }
00222 #else
00223 #ifdef DEBUG
00224  #warning "dynamic factor sanity check disabled! (just want to mention it)"
00225 #endif
00226 #endif
00227 
00228   if (existiert_grosser_Restfaktor)
00229     {
00230       const bool is_possible_dynamic = (mpz_cmp_ui(y, SingleLargePrime_Threshold)<=0);
00231       if ( !is_possible_dynamic && CmpqsFactor::DLP_rejected(y) )
00232         {
00233           // We should first filter out invalid big numbers, especially the
00234           // primes! It doesn't harm (except for performance) if some composite
00235           // numbers are filtered out as primes.
00236           // Important is that "DLP_reject(y)" is not too expensive!
00237           relevant_factor=special_factor; // ignored factor (because we do not insert any relation)
00238           return;
00239         }
00240         
00241       if (is_possible_dynamic && probab_prime(mpz_get_ui(y)) )
00242         {
00243           // this is a new dynamic factor
00244           relevant_factor=dynamic_factor;
00245           TDynamicFactorRelation relation;
00246           relation.factor=mpz_get_ui(y);
00247 
00248           // the found factor could be a rediscovered SingleLargePrime
00249           // We should detect this and take appropriate action!
00250           if (is_dynamic_factor(relation.factor))
00251            {
00252              Hits[HitCount].Faktor=relation.factor; Hits[HitCount].Exponent=1; ++HitCount;
00253              relevant_factor=largest_factor_in_Relation();
00254              goto done_with_grosser_Restfaktor;
00255            }
00256           relation.append_for_sieving();
00257 
00258 #ifndef IS_CLIENT
00259           relation.fpos = save(DynamicRelations::DynamicRelations_to_file,relation.factor, HitCount);
00260 #ifdef SAFEMODE
00261           // validate the newly generated dynamic factor relation.
00262           // also the new dynamic factor needs to be feed to the validation routine!
00263           {
00264            const streampos rpos=DynamicRelations::DynamicRelations_from_file.tellg();
00265            DynamicRelations::DynamicRelations_from_file.seekg(relation.fpos);
00266            CRelation::SanityCheck(DynamicRelations::DynamicRelations_from_file); // exit if relation is invalid (->this would be an internal error!)
00267            DynamicRelations::DynamicRelations_from_file.seekg(rpos);
00268           }
00269 #endif
00270 #else /* IS_CLIENT */
00271           // send it to the output file
00272           relation.fpos=save(communication_stream,relation.factor, HitCount);
00273 #endif
00274           DynamicFactorRelations.insert(relation);
00275           statistical_data::directly_sieved_DynamicFactors++;
00276 #ifndef IS_CLIENT
00277           SpecialRelations::split_by_primefactor(relation.factor);
00278 #endif
00279           ++statistical_data::relations_sieved_so_far; // one more relation found
00280           return;
00281         }
00282         
00283       // it's a special factor, which isn't a prime
00284       {
00285         relevant_factor=special_factor;
00286         TSpecialFactorRelation relation;
00287         if (!relation.factor.DLP_get(y))
00288           {
00289             //cerr << "Hint: Special Factor " << y << " invalid." << endl;
00290             return; // Don't take over this hit, since it is invalid.
00291           }
00292 #ifndef IS_CLIENT
00293         if (!SpecialRelations::insert(relation.factor,this,HitCount))
00294           {
00295             relevant_factor=largest_factor_in_Relation();
00296             // if factor hasn't been marked, then this means, that it
00297             // has been neutralised. -> we have found a normal relation.
00298 
00299             // ööö/FIXME: nachfolgendes sollte vielleicht besser in SpecialRelations::insert() getan werden?
00300             //            -> in English: I'm not sure whether the following block should eventually be move into SpecialRelations::insert()
00301             // kombiniere Faktoren der dynamic Factorbase
00302 
00303             static CRelation::SMulticombineData MD; // static is faster as long as this is no critical resource!
00304             set_MulticombineData(&MD);
00305             multi_combine_init();
00306             for (int i=0; i<HitCount; ++i) if(Hits[i].Exponent!=0)
00307              {
00308                //cout << "combining dynamic factor " << Hits[i].Faktor << endl;
00309                TDynamicFactorRelation FaRelSearch;
00310                FaRelSearch.factor=Hits[i].Faktor;
00311                const TDynamicFactorRelations::const_iterator p = DynamicFactorRelations.find(FaRelSearch);
00312                mpz_mul_ui(Delta,Delta,(*p).factor); mpz_mod(Delta,Delta,n);
00313                multi_combine_main(DynamicRelations::DynamicRelations_from_file,(*p).fpos);
00314                //cout << "combined: " << *pos << endl;
00315              }
00316             multi_combine_exit();
00317             invalidate_MulticombineData();
00318             ++statistical_data::relations_sieved_so_far; // one more relation found
00319             return;
00320           }
00321 #else
00322         // send to output file
00323         relation.fpos=save(communication_stream, relation.factor, HitCount);
00324 #endif
00325         statistical_data::directly_sieved_SpecialFactors++;
00326 
00327 //ööö 2004-12:
00328         // activate this small block only for performance tuning & profiling: 
00329         //cout << (*this) << endl;
00330         //if (statistical_data::directly_sieved_SpecialFactors>49) exit(0);
00331 
00332         ++statistical_data::relations_sieved_so_far; // one more relation found
00333         return;
00334       }
00335     } // end of "if (existiert_grosser_Restfaktor)"
00336  done_with_grosser_Restfaktor:
00337 
00338 #ifndef IS_CLIENT
00339   // combining factors of the dynamic factorbase
00340   static CRelation::SMulticombineData MD; // static is faster as long as this is no critical resource!
00341   set_MulticombineData(&MD);
00342   multi_combine_init();
00343   for (int i=0; i<HitCount; ++i) if(Hits[i].Exponent!=0)
00344    {
00345      //cout << "combining dynamic factor " << Hits[i].Faktor << endl;
00346      TDynamicFactorRelation FaRelSearch;
00347      FaRelSearch.factor=Hits[i].Faktor;
00348      const TDynamicFactorRelations::const_iterator p = DynamicFactorRelations.find(FaRelSearch);
00349      mpz_mul_ui(Delta,Delta,(*p).factor); mpz_mod(Delta,Delta,n);
00350      multi_combine_main(DynamicRelations::DynamicRelations_from_file,(*p).fpos);
00351      //cout << "combined: " << *pos << endl;
00352    }
00353   multi_combine_exit();
00354   invalidate_MulticombineData();
00355 #else
00356   // output to file
00357   save(communication_stream,1, HitCount);
00358 #endif
00359 
00360   ++statistical_data::relations_sieved_so_far; // one more relation found
00361   statistical_data::DynamicFactorRating.increment_Hits_at_position(HitCount);
00362   /* for statistical evaluation on how the dynamic factorbase
00363      is responsible for the finding of relations:
00364       [0]-> no dynamic factor is involved,
00365       [1]-> one dynamic factor is involved
00366       [2]-> two dynamic factors are involved
00367       [3]-> three dynamic factors are involved
00368       [n]-> n dynamic factors are involved
00369       [mysize-1]-> at least mysize-1 dynamic factors are involved
00370    */
00371 
00372   //cout << "relation: " << *this << endl;
00373   //cout << "relevant factor: " << relevant_factor << endl;
00374   //cout << "Finished initialization of this relation! (leaving constructor)" << endl;
00375 }
00376 
00377 #endif /* IS_SERVER not defined */
00378 
00379 
00380 
00381 CmpqsFactor CRelation::combine(istream &in)
00382 {
00383   //cout << "combining relation from file" << endl;
00384   CStreamDecoder enc_in(in);
00385   CmpqsFactor ret;
00386   string s;
00387   int index;
00388  
00389   // save file flags
00390   const ios::fmtflags oldFlags = in.flags(); // memorize old flags of the stream
00391   in.unsetf(ios::hex); in.setf(ios::dec); // enable decimal output (notice: because of "correction factors" there could be a recursive call!)
00392   in.unsetf(ios::showbase); // without any leading prefix
00393  
00394   in >> s; // starting symbol "G"
00395   if (s != "G")
00396     {
00397       MARK;
00398       cerr << "error: wrong position while reading relation" << endl;
00399       exit(1);
00400     }
00401   in >> ret; // read factor (dynamic-factor or special-factor of relation or 1)
00402   in >> s; // delta
00403   mpz_set_str(x, s.c_str(), mpzbase_f); // x is classwide auxiliary variable
00404   mpz_mul(Delta, Delta, x);
00405   mpz_mod(Delta, Delta, n);
00406 
00407   // now we start to work in hexadecimal notation:
00408   in.unsetf(ios::dec); in.setf(ios::hex); // hexadecimal output
00409   in.unsetf(ios::showbase); // without "0x"-marker
00410   
00411   /*
00412     compute symmetric difference of the factors in the relation
00413     Multiply the common part (=intersection) into square root Delta
00414   */
00415   mpz_set_ui(x,1); // for speedup: collect factors in x as long as x<n
00416   signed int distance; // hint: we work with differences instead of the values itself
00417 
00418   if (Relation_dense) // Relation is dense
00419     { // compute symmetric difference using dense-representation
00420       distance=enc_in.GetValue(); index=distance;
00421       while (distance >= 0)
00422         {
00423           if (Relation_dense->test(index))
00424             if (index>0)
00425               {
00426                 mpz_mul_ui(x,x,StaticFactorbase::PrimeNumbers[index]);
00427                 if (mpz_cmp(x,n)>=0)
00428                   {
00429                     mpz_mod(x,x,n); mpz_mul(Delta,Delta,x);
00430                     mpz_mod(Delta,Delta,n); mpz_set_ui(x,1);
00431                   }
00432               } //else mpz_neg(Delta,Delta);
00433           Relation_dense->invert(index);
00434           distance=enc_in.GetValue(); index+=distance;
00435         }
00436     }
00437   else
00438     { // compute symmetric difference using sparse-representation
00439       int p1 = 0;
00440       CTinyFBsizetypeVector neueMenge(StaticFactorbase::Size());
00441       //neueMenge.reset(); // "clear" without deallocating memory
00442       const CTinyFBsizetypeVector& R = *Relation_sparse;
00443       
00444       distance=enc_in.GetValue(); index=distance; 
00445       while (distance>=0 && p1<R.size())
00446         {
00447           while (index<R[p1])
00448             {
00449               neueMenge.append(index); distance=enc_in.GetValue(); index+=distance;
00450               if (distance<0) goto done;
00451             }
00452           while (R[p1]<index)
00453             {
00454               neueMenge.append(R[p1]); ++p1;
00455               if (p1==R.size()) goto done;
00456             }
00457           while (index==R[p1])
00458             {
00459               if (index>0)
00460                 {
00461                   mpz_mul_ui(x,x,StaticFactorbase::PrimeNumbers[index]);
00462                   if (mpz_cmp(x,n)>=0)
00463                     {
00464                       mpz_mod(x,x,n); mpz_mul(Delta,Delta,x);
00465                       mpz_mod(Delta,Delta,n); mpz_set_ui(x,1);
00466                     }
00467                 } //else mpz_neg(Delta,Delta);
00468               distance=enc_in.GetValue(); index+=distance; ++p1;
00469               if (distance<0) goto done;
00470               if (p1==R.size()) goto done;      
00471             }
00472         }
00473     done:
00474       while (distance>=0) { neueMenge.append(index); distance=enc_in.GetValue(); index+=distance; }
00475       while (p1!=R.size()) { neueMenge.append(R[p1]); ++p1; }
00476       Relation_sparse->copy_from(neueMenge); // take over new set
00477       //optisize(); // optimize memory usage (sparse<->dense, etc.)
00478     }
00479   
00480   // x contains (possibly) a remaining value, which has to be multiplied into Delta:
00481   mpz_mul(Delta,Delta,x); mpz_mod(Delta,Delta,n);
00482  
00483   if (distance == -2) // "correction factors" follow
00484     {
00485       /* Korrekturfaktoren sind dynamische Faktoren, die zum Zeitpunkt der Generierung
00486          der gelesenen Relation nicht aufgelöst wurden. Sie müssen daher jetzt verknüpft werden. */
00487       /* correction factors are dynamic factors, that weren't resolved at the time of generating
00488          this relation. They must be considered and combined now! */
00489       TDynamicFactorRelation FaRelSearch;
00490       stack<int> DeferredFactors; // breadth first search (Breitensuche) to avoid perpetually seeking on file.
00491       while ( (FaRelSearch.factor=enc_in.GetValue())>0 ) DeferredFactors.push(FaRelSearch.factor);
00492       
00493       ProvideDynamicRelationsStream to_me(pDynamicRelations_from_file); // constructor acquires and destructor releases pDynamicRelations_from_file...
00494       while (!DeferredFactors.empty())
00495         {
00496           FaRelSearch.factor=DeferredFactors.top(); DeferredFactors.pop();
00497           //cout << "Korrekturfaktor: " << FaRelSearch.factor << " für " << setprecision(20) << ret << endl;
00498 
00499           fillin_streampos(FaRelSearch);
00500            // fillin_streampos will throw an exception, if FaRelSearch.factor is not a member.
00501            // we could catch the exception and do "ret=0; break;" to skip this factor and continue with new data...
00502 
00503           mpz_mul_ui(Delta,Delta,FaRelSearch.factor); mpz_mod(Delta,Delta,n);
00504           (*pDynamicRelations_from_file).seekg(FaRelSearch.fpos);
00505           if ((*pDynamicRelations_from_file).peek()==EOF) seek_emergency_handler(*pDynamicRelations_from_file,FaRelSearch.fpos);
00506           if (combine(*pDynamicRelations_from_file).IsTypeOf(CmpqsFactor::empty)) { ret=0; break; } // combine on background storage device; return ret=0 on failure
00507           //cout << "finished combining " << FaRelSearch.factor << endl;
00508         }
00509     }
00510   
00511   in.flags(oldFlags); // restore memorized stream flags
00512  
00513   relevant_factor=largest_factor_in_Relation();
00514   //cout << "finished combining relation from file." << endl;
00515   return ret;
00516 }
00517 
00518 CmpqsFactor CRelation::multi_combine_main(istream &in)
00519 {
00520   //cout << "multi-combine relation from file..." << endl;
00521   CStreamDecoder enc_in(in);
00522   adjust_multi_combine(); // keep aware of number of calls (do not remove; this is essential!)
00523 
00524   TExponentArrayElement *ExponentArray = pMulticombineData->ExponentArray;
00525 
00526   CmpqsFactor ret;
00527   string s;
00528   int index;
00529  
00530   // save file flags
00531   const ios::fmtflags oldFlags = in.flags(); // memorize old flags of the stream
00532   in.unsetf(ios::hex); in.setf(ios::dec); // enable decimal output (notice: because of "correction factors" there could be a recursive call!)
00533   in.unsetf(ios::showbase); // without any leading prefix
00534  
00535   in >> s; // starting symbol "G"
00536   if (s != "G")
00537     {
00538       MARK;
00539       cerr << "error: wrong position while reading relation" << endl;
00540       exit(1);
00541     }
00542   in >> ret; // read factor (dynamic-factor or special-factor of relation or 1)
00543   in >> s; // delta
00544   mpz_set_str(x, s.c_str(), mpzbase_f); // x is classwide auxiliary variable
00545   mpz_mul(Delta, Delta, x);
00546   mpz_mod(Delta, Delta, n);
00547 
00548   // now we start to work in hexadecimal notation:
00549   in.unsetf(ios::dec); in.setf(ios::hex); // hexadecimal output
00550   in.unsetf(ios::showbase); // without "0x"-marker
00551   
00552   /*
00553     compute symmetric difference of the factors in the relation
00554     Multiply the common part (=intersection) into square root Delta
00555   */
00556   signed int distance; // hint: we work with differences instead of the values itself
00557 
00558   if (Relation_dense) // Relation is dense
00559     { // compute symmetric difference using dense-representation
00560       distance=enc_in.GetValue(); index=distance;
00561       while (distance >= 0)
00562         {
00563           if (Relation_dense->test_and_invert(index)) ++ExponentArray[index];
00564           distance=enc_in.GetValue(); index+=distance;
00565         }
00566     }
00567   else
00568     { // compute symmetric difference using sparse-representation
00569       int p1 = 0;
00570       CTinyFBsizetypeVector neueMenge(StaticFactorbase::Size());
00571       //neueMenge.reset(); // "leeren" ohne Speicherfreigabe
00572       const CTinyFBsizetypeVector& R = *Relation_sparse;
00573       
00574       distance=enc_in.GetValue(); index=distance; 
00575       while (distance>=0 && p1<R.size())
00576         {
00577           while (index<R[p1])
00578             {
00579               neueMenge.append(index); distance=enc_in.GetValue(); index+=distance;
00580               if (distance<0) goto done;
00581             }
00582           while (R[p1]<index)
00583             {
00584               neueMenge.append(R[p1]); ++p1;
00585               if (p1==R.size()) goto done;
00586             }
00587           while (index==R[p1])
00588             {
00589               ++ExponentArray[index];
00590               distance=enc_in.GetValue(); index+=distance; ++p1;
00591               if (distance<0) goto done;
00592               if (p1==R.size()) goto done;      
00593             }
00594         }
00595     done:
00596       while (distance>=0) { neueMenge.append(index); distance=enc_in.GetValue(); index+=distance; }
00597       while (p1!=R.size()) { neueMenge.append(R[p1]); ++p1; }
00598       Relation_sparse->copy_from(neueMenge); // take over new set
00599     }
00600 
00601   if (distance == -2) // "correction factors" follow
00602     {
00603       /* Korrekturfaktoren sind dynamische Faktoren, die zum Zeitpunkt der Generierung
00604          der gelesenen Relation nicht aufgelöst wurden. Sie müssen daher jetzt verknüpft werden. */
00605       /* correction factors are dynamic factors, that weren't resolved at the time of generating
00606          this relation. They must be considered and combined now! */
00607 
00608       TDynamicFactorRelation FaRelSearch;
00609       stack<int> DeferredFactors; // breadth first search (Breitensuche) to avoid perpetually seeking on file.
00610       while ( (FaRelSearch.factor=enc_in.GetValue())>0 ) DeferredFactors.push(FaRelSearch.factor);
00611 
00612       ProvideDynamicRelationsStream to_me(pDynamicRelations_from_file); // constructor acquires and destructor releases pDynamicRelations_from_file...
00613       while (!DeferredFactors.empty())
00614         {
00615           FaRelSearch.factor=DeferredFactors.top(); DeferredFactors.pop();
00616           //cout << "Korrekturfaktor: " << FaRelSearch.factor << " für " << setprecision(20) << ret << endl;
00617 
00618           fillin_streampos(FaRelSearch);
00619            // fillin_streampos will throw an exception, if FaRelSearch.factor is not a member.
00620            // we could catch the exception and do "ret=0; break;" to skip this factor and continue with new data...
00621 
00622           mpz_mul_ui(Delta,Delta,FaRelSearch.factor); mpz_mod(Delta,Delta,n);
00623           (*pDynamicRelations_from_file).seekg(FaRelSearch.fpos);
00624           if ((*pDynamicRelations_from_file).peek()==EOF) seek_emergency_handler(*pDynamicRelations_from_file,FaRelSearch.fpos);
00625           if (multi_combine_main(*pDynamicRelations_from_file).IsTypeOf(CmpqsFactor::empty)) { ret=0; break; } // combine on background storage device; return ret=0 on failure
00626           //cout << "finished combining " << FaRelSearch.factor << endl;
00627         }
00628     }
00629   
00630   in.flags(oldFlags); // restore memorized stream flags
00631  
00632   relevant_factor=largest_factor_in_Relation();
00633   //cout << "finished multi-combine from file." << endl;
00634   return ret;
00635 }
00636 
00637 streampos CRelation::save(ostream &out, const CmpqsFactor factor, const short int HitCount /* = 0 */) const
00638 {
00639   CStreamEncoder enc_out(out);
00640 #ifndef IS_CLIENT
00641   streampos pos;
00642   // out.seekp(0,ios::end);  // should be already at the end of the file
00643   pos = out.tellp(); // get file position
00644 #endif
00645   char *str;
00646 
00647   str = new char [mpz_sizeinbase(Delta,mpzbase_f)+2]; mpz_get_str(str,mpzbase_f, Delta);
00648   out << "G " << setprecision(20) << factor << " " << str << " ";
00649   delete [] str;
00650 
00651   // now we start to work in hexadecimal notation:
00652   const ios::fmtflags oldFlags = out.flags(); // memorize old stream flags
00653   out << hex; // hexadecimal output
00654   out.unsetf(ios::showbase); // without "0x"-marker
00655   
00656   /* remark:
00657      Instead of storing the values theirself, we store the distances between them (which is more space-efficient!) */
00658   if (Relation_dense)
00659     { 
00660       int prev = 0;
00661       for (int i=Relation_dense->first(); i>=0; i=Relation_dense->next(i))
00662         {
00663           enc_out.PutValue(i-prev);
00664           prev=i;
00665         } 
00666     }
00667   else
00668     {
00669       int prev = 0;
00670       for (int i=0; i<Relation_sparse->size(); ++i)
00671         {
00672           int h = (*Relation_sparse)[i];
00673           enc_out.PutValue(h-prev);
00674           prev=h;
00675         }
00676     }
00677 
00678   int Count_SLP_in_relation = 0;
00679   for (int i=0; i<HitCount; ++i) if (Hits[i].GetExponent()>0) ++Count_SLP_in_relation;
00680   if (Count_SLP_in_relation>0)
00681     {
00682       enc_out.PutValue(-2);
00683       //cout << "Korrekturfaktoren für Relation mit Faktor " << setprecision(20) << factor << endl;
00684       for (int i=0; i<HitCount; ++i)
00685         { 
00686           //cout << Hits[i].Faktor << "^" << Hits[i].Exponent << endl; 
00687           if (Hits[i].GetExponent()>0) enc_out.PutValue(Hits[i].Faktor);
00688         }
00689     }
00690   enc_out.PutValue(-1); out << endl;
00691   out.flags(oldFlags); // restore old state of format-flags
00692 #ifdef IS_CLIENT
00693   return 0;
00694 #else
00695   return pos;
00696 #endif
00697 }
00698 
00699 
00700 
00701 #ifndef IS_CLIENT
00702 bool CRelation::ComputeQuadraticCongruence() const
00703 {
00704   /* The determined relation satisfies the congruency (A²=1) mod n.
00705      Because of A²-1²=(A+1)*(A-1)=0 mod n, we can construct a factor by computing ggT(A+1,n);
00706      we have a good chance that this factor is not a trivial one... */
00707 
00708   mpz_t x,y;
00709   mpz_init(x); mpz_init(y);
00710 
00711   StatusReport(true);
00712 #ifdef VERBOSE_NOTICE
00713   cout << endl << "Found a suitable relation..." << endl;
00714 #endif
00715 
00716   if (!empty())
00717    {
00718      MARK;
00719      cerr << "Error! Relation contains unresolved members!" << endl;
00720    }
00721 
00722   mpz_powm_ui(x,Delta,2,n);
00723 
00724 #ifdef VERBOSE_INFO
00725   cout << "[" << Delta << "]² = 1 (mod N)" << endl;
00726   cout << "-> " << x << " = 1 (mod N)" << endl;
00727 #endif
00728   
00729   if (mpz_cmp_ui(x,1)!=0) 
00730     {
00731       cerr << "Error! Squares are NOT congruent!" << endl;
00732       cerr << "?? [" << Delta << "]² = 1 (mod N)" << endl;
00733       cerr << "?? -> " << x << " = 1 (mod N)" << endl;
00734       exit(1);
00735     }
00736   
00737   mpz_add_ui(x,Delta,1);
00738   mpz_gcd(x,x,n); mpz_divexact(y,n,x); // notice: n and *not* kN is the number to factorize!
00739   
00740   if ((mpz_cmp_ui(x,1)==0) || (mpz_cmp_ui(y,1)==0))
00741     {
00742 #ifdef VERBOSE_NOTICE
00743       cout << "factorization was trivial..." << endl << endl;
00744 #endif
00745     }
00746   else
00747     {
00748       if (mpz_cmp(x,y)>0) mpz_swap(x,y); // we want x<y
00749 
00750       cout << endl << "factor found!" << endl;
00751       cout << x << " * ";
00752       cout << y << endl;
00753       cout << "= ";
00754       cout << n << endl;
00755       
00756       if (mpz_probab_prime_p(x,probab_prime_checks))
00757         {
00758           mpz_divexact(n,n,x);
00759           cout << x << " is a factor." << endl;
00760           std::ostringstream comment;
00761           comment << " [dmpqs]";
00762           Factorization_to_file << MAL(x,1,comment) << flush;
00763         }
00764       else
00765         if (Potenztest(x)) mpz_divexact(n,n,x); // remove powers...
00766 
00767       if (mpz_probab_prime_p(y,probab_prime_checks))
00768         {
00769           mpz_divexact(n,n,y);
00770           cout << y << " is a factor." << endl;
00771           std::ostringstream comment;
00772           comment << " [dmpqs]";
00773           Factorization_to_file << MAL(y,1,comment) << flush;
00774         }
00775       else
00776         if (Potenztest(y)) mpz_divexact(n,n,y); // remove powers...
00777       
00778 
00779       if (mpz_cmp_ui(n,1)==0) // factorization complete?
00780         { 
00781           cout << "factorization successfully completed." << endl;
00782           Factorization_to_file << endl;
00783           mpz_clear(x); mpz_clear(y);
00784           return true; 
00785         }
00786     }
00787 #ifdef VERBOSE_NOTICE
00788   cout << "continue factorization..." << endl << endl;
00789 #endif
00790   mpz_clear(x); mpz_clear(y);
00791   return false;
00792 }
00793 #endif

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