CRelation.cc

Go to the documentation of this file.
00001 
00007 #include <string>
00008 #include <iostream>
00009 #include <stdexcept>
00010 #include <cmath>
00011 #include <gmp.h>
00012 #include "utils.H"
00013 
00014 #include "qsieve.H"
00015 
00016 using namespace std;
00017 
00018 extern mpz_t n;
00019 
00020 
00021 ostream& operator<< (ostream& ostr, const CRelation& GL)
00022 {
00023   if (GL.Relation_dense) ostr << "dense"; else ostr << "sparse";
00024   ostr << "1=";
00025   
00026   char *str;
00027   str = new char [mpz_sizeinbase(GL.Delta,10)+2]; mpz_get_str(str, 10, GL.Delta);
00028   ostr << str << "^2";
00029   delete [] str; 
00030   
00031   if (GL.Relation_dense)
00032     { 
00033       for (int i=GL.Relation_dense->first(); i>=0; i=GL.Relation_dense->next(i))
00034         ostr << "*p" << i;
00035     }
00036   else
00037     {
00038       const CTinyFBsizetypeVector& R = *GL.Relation_sparse;
00039       for (int pos=0; pos<R.size(); ++pos)
00040         ostr << "*p" << R[pos];
00041     }
00042   
00043   return ostr;
00044 }
00045 
00046 
00047 void CRelation::convert_Relation_to_dense()
00048 {
00049   //cout << "Converting relation from sparse to dense representation." << endl;
00050   if (Relation_dense)
00051     { cerr << "Relation is already dense!" << endl; return; }
00052   Relation_dense = new myBitString;
00053   for (int pos=Relation_sparse->size()-1; pos>=0; --pos)
00054     Relation_dense->set((*Relation_sparse)[pos]);
00055   //Relation_sparse->erase(Relation_sparse->begin(),Relation_sparse->end());
00056   delete Relation_sparse; Relation_sparse=NULL; // delete sparse representation
00057 }
00058 
00059 void CRelation::convert_Relation_to_sparse()
00060 {
00061   //cout << "Converting relation from dense to sparse representation." << endl;
00062   if (Relation_sparse)
00063     { cerr << "Relation is already sparse!" << endl; return; }
00064   Relation_sparse = new CTinyFBsizetypeVector(Relation_dense->count(1));
00065   for (int i=Relation_dense->first(); i>=0; i=Relation_dense->next(i))
00066     Relation_sparse->fast_append(i);
00067   //Relation_dense->clear();
00068   delete Relation_dense; Relation_dense=NULL; // delete dense representation
00069 }
00070 
00071 
00072 void CRelation::combine(const CRelation& GL2)
00073   // GL2 as reference, because this more efficient
00074   // compute symmetric difference
00075 {
00076   //cout << "combining relations..." << endl;
00077   //cout << "Gl.1: "; SanityCheck();
00078   //cout << "Gl.2: "; GL2.SanityCheck();
00079   
00080   /*
00081     Compute symmetric difference of the two relation sets.
00082     Multiply common part (intersection) into square root Delta.
00083   */
00084   mpz_set_ui(x,1); // collect factors in x until x>n (to speedup computation)
00085 
00086   if ( GL2.Relation_dense ) // GL2.Relation is dense
00087     {
00088       if (!Relation_dense) // if relation isn't dense already,
00089         convert_Relation_to_dense(); // make it dense...
00090       
00091       // PrimeNumbers[0] == -1; we can ignore the sign!
00092       //  -> loop until i>0 instead of i>=0
00093       //  -> we can treat all numbers as unsigned, thereby optimizing things...
00094       for (int i=GL2.Relation_dense->last(); i>0; i=GL2.Relation_dense->prev(i))
00095         if (Relation_dense->test(i))
00096          {
00097            mpz_mul_ui(x,x,PrimeNumbers[i]);
00098            if (mpz_cmp(x,n)>=0)
00099             {
00100               mpz_mod(x,x,n); mpz_mul(Delta,Delta,x);
00101               mpz_mod(Delta,Delta,n); mpz_set_ui(x,1);
00102             }
00103          }
00104       
00105       (*Relation_dense)._xor(*GL2.Relation_dense); // symmetric difference
00106     }
00107   else /* GL2.Relation is sparse */
00108     if (Relation_dense) /* and Relation is dense */
00109       { 
00110         // compute symmetric difference in dense representation
00111         // (whereas the other vector remains sparse)
00112         for (int pos=0; pos<GL2.Relation_sparse->size(); ++pos)
00113           {
00114             if (Relation_dense->test((*GL2.Relation_sparse)[pos]))
00115               if ((*GL2.Relation_sparse)[pos]>0)
00116                 {
00117                   mpz_mul_ui(x,x,PrimeNumbers[(*GL2.Relation_sparse)[pos]]);
00118                   if (mpz_cmp(x,n)>=0)
00119                     {
00120                       mpz_mod(x,x,n); mpz_mul(Delta,Delta,x);
00121                       mpz_mod(Delta,Delta,n); mpz_set_ui(x,1);
00122                     }
00123                 } //else mpz_neg(Delta,Delta);
00124             Relation_dense->invert((*GL2.Relation_sparse)[pos]);
00125           }
00126       }
00127     else
00128       {
00129         // compute symmetric difference in sparse representation
00130         int p1 = 0;
00131         int p2 = 0;
00132         const CTinyFBsizetypeVector& R = *Relation_sparse;
00133         const CTinyFBsizetypeVector& R2 = *GL2.Relation_sparse;
00134         CTinyFBsizetypeVector neueMenge(R.size()+R2.size());
00135         //neueMenge.reset();
00136         while (p2<R2.size() && p1<R.size())
00137           {
00138             while (R2[p2]<R[p1])
00139               {
00140                 neueMenge.fast_append(R2[p2]); ++p2;
00141                 if (p2==R2.size()) goto done;
00142               }
00143             while (R[p1]<R2[p2])
00144               {
00145                 neueMenge.fast_append(R[p1]); ++p1;
00146                 if (p1==R.size()) goto done;
00147               }
00148             while (R2[p2]==R[p1])
00149               {
00150                 if (R[p1]>0)
00151                   {
00152                     mpz_mul_ui(x,x,PrimeNumbers[R[p1]]);
00153                     if (mpz_cmp(x,n)>=0)
00154                       {
00155                         mpz_mod(x,x,n); mpz_mul(Delta,Delta,x);
00156                         mpz_mod(Delta,Delta,n); mpz_set_ui(x,1);
00157                       }
00158                   } //else mpz_neg(Delta,Delta);
00159                 ++p1; ++p2;
00160                 if (p2==R2.size()) goto done;
00161                 if (p1==R.size()) goto done;      
00162               }
00163           }
00164       done:
00165         while (p2!=R2.size()) { neueMenge.fast_append(R2[p2]); ++p2; }
00166         while (p1!=R.size()) { neueMenge.fast_append(R[p1]); ++p1; }
00167         Relation_sparse->copy_from(neueMenge); // take over new set
00168         //optisize(); // optimize memory usage (sparse<->dense, etc.)
00169       }
00170   
00171   // x contains (possibly) a remaining value, which has to be multiplied into Delta:
00172   mpz_mul(Delta,Delta,x); mpz_mod(Delta,Delta,n);
00173   
00174   // don't forget: the new delta has to contain the delta of the other
00175   // relation as well!
00176   mpz_mul(Delta,Delta,GL2.Delta); mpz_mod(Delta,Delta,n);
00177   
00178   relevant_factor=largest_factor_in_Relation();
00179   //cout << "combine finished." << endl;
00180 }
00181 
00182 
00183 // The following set of methods greatly improve multiple combination of relations.
00184 //  idea: the update/combine of the exponents of the factors can
00185 //   deferred up to the time, where the result is needed.
00186 //   (In most situations there is really no need to this simultaneously.)
00187 
00188 void CRelation::multi_combine_init()
00189 {
00190   // initialize vector of exponents.
00191   // hint: If you can assure, that the last call of multi_combine_...
00192   //       was in fact a multi_combine_exit(), then you
00193   //       may skip calling multi_combine_init().
00194   if (pMulticombineData==NULL)
00195    {
00196      MARK; cerr << "Error: pMulticombineData invalid!" << endl;
00197      exit(1);
00198    }
00199   if (!pMulticombineData->multi_combine_Counter) return;
00200   pMulticombineData->multi_combine_Counter=0;
00201   for (int i=0; i<StaticFactorbaseSettings::Size(); i++) pMulticombineData->ExponentArray[i]=0;
00202 }
00203 
00204 void CRelation::multi_combine_exit()
00205 {
00206   if (!pMulticombineData->multi_combine_Counter) return; // nothing to do...
00207 #ifdef VERBOSE
00208   cout << "Multicombine_exit after " << pMulticombineData->multi_combine_Counter
00209        << " calls." << endl;
00210 #endif
00211 
00212   if (pMulticombineData->multi_combine_Counter>std::numeric_limits<TExponentArrayElement>::max())
00213    {
00214      MARK;
00215      cerr << "Elements of CRelation::ExponentArray may have exceeded limits," << endl
00216           << "you have to increase the type of CRelation::TExponentArrayElement" << endl
00217           << "and recompile the program to assure correct computation." << endl
00218           << "(Data computed so far are still correct and can be reused afterwards.)" << endl;
00219      exit(8);
00220    }
00221 
00222   optisize(); // optimize Size of vector (sparse<->dense, etc.)
00223 
00224   // multiply factors weighted by their exponents into Delta:
00225   mpz_set_ui(y,1); // collect product in y
00226   pMulticombineData->ExponentArray[0]=0; // leave "prime number" "-1" out of consideration
00227 
00228   /* 
00229      implemented idea:
00230      sort vector of exponents descending by exponents,
00231      evaluate the product analogously to the Horner scheme.
00232      -> sorting method: bucketsort. ("Flag[i]" defines, whether an exponent is associated to i.)
00233      All bases belonging to an exponent e will be multiplied together in "Basis[e]".
00234   */
00235 
00236 #define MY_BASIS_WORKAROUND
00237 #if !defined(__GNUC__) || !defined(MY_BASIS_WORKAROUND)
00238   // I got strange errors in server mode when using this:
00239   // glibc 2.5 raises an assertion fault...
00240   // probably a racing condition between threads.
00241   mpz_t* const Basis = new mpz_t[StaticFactorbaseSettings::Size()];
00242   bool* const Flag = new bool[StaticFactorbaseSettings::Size()];
00243 #else
00244   #warning "enabling workaround for possible Basis assertion failure"
00245   // this code is less standard conformant since it uses variable-length arrays,
00246   // but it seems to circumvent the above problem and may be slightly faster...
00247   __extension__ mpz_t Basis[StaticFactorbaseSettings::Size()];
00248   __extension__ bool Flag[StaticFactorbaseSettings::Size()];
00249 #endif  
00250   for (int i=0; i<StaticFactorbaseSettings::Size(); ++i) Flag[i]=false; // initialize
00251 
00252   for (int i=1; i<StaticFactorbaseSettings::Size(); ++i)
00253    if (pMulticombineData->ExponentArray[i])
00254     {
00255       const unsigned long int e=pMulticombineData->ExponentArray[i];
00256       pMulticombineData->ExponentArray[i]=0; // reset exponent
00257 
00258       if (e>=StaticFactorbaseSettings::Size())
00259        {
00260          cout << "Unexpected exponent " << e << "! Use normal exponentiation..." << endl;
00261          mpz_set_ui(y,PrimeNumbers[i]); mpz_powm_ui(y,y,e,n);
00262          mpz_mul(Delta,Delta,y);
00263          continue;
00264        }
00265 
00266       if (Flag[e])
00267        {
00268          // expand Basis
00269          mpz_mul_ui(Basis[e],Basis[e],PrimeNumbers[i]);
00270          if (mpz_cmp(Basis[e],n)>=0)
00271           { 
00272             // reduce mod n
00273             mpz_mod(Basis[e],Basis[e],n);
00274           }
00275        }
00276       else 
00277        { 
00278          // initialize Basis
00279          Flag[e]=true;
00280          mpz_init_set_ui(Basis[e],PrimeNumbers[i]);
00281        }
00282     }
00283 
00284  /*
00285   Evaluate product analogously to Horner scheme,
00286   example: a^7 * b^4 * c^3 * d 
00287            = a^(7-4) * (a*b)^(4-3) * (a*b*c)^(3-1) * (a*b*c*d)
00288  */     
00289 
00290   unsigned int e2 = StaticFactorbaseSettings::Size()-1;
00291   Flag[0]=true; // be cautious for next loop...
00292   while (!Flag[e2]) --e2; // get highest set exponent
00293 
00294   mpz_set_ui(y,1);
00295   if (e2>1)
00296    for (unsigned int e=e2-1; e>0; --e)
00297     if (Flag[e])
00298      {
00299        mpz_mul(Basis[e],Basis[e],Basis[e2]);
00300        if (mpz_cmp(Basis[e],n)>=0)
00301         {
00302           // reduce mod n
00303           mpz_mod(Basis[e],Basis[e],n);
00304         }
00305        if (e2-e>1) mpz_powm_ui(Basis[e2],Basis[e2],e2-e,n);
00306        mpz_mul(y,y,Basis[e2]);
00307        if (mpz_cmp(y,n)>=0)
00308         {
00309           // reduce mod n
00310           mpz_mod(y,y,n);
00311         }
00312        mpz_clear(Basis[e2]); // do not forget: free this mpz-number
00313        e2=e;
00314      }
00315 
00316   if (e2>1) mpz_powm_ui(Basis[e2],Basis[e2],e2,n);
00317   if (e2>0)
00318    {
00319       mpz_mul(y,y,Basis[e2]); mpz_mod(y,y,n);
00320       mpz_clear(Basis[e2]); // do not forget: free this mpz number
00321    }
00322 
00323 #if !defined(__GNUC__) || !defined(MY_BASIS_WORKAROUND)
00324   delete [] Basis; delete [] Flag;
00325 #endif
00326   
00327   mpz_mul(Delta,Delta,y); mpz_mod(Delta,Delta,n);
00328   pMulticombineData->multi_combine_Counter=0;
00329 #ifdef VERBOSE
00330   cout << "Multi_combine_exit finished." << endl;
00331 #endif
00332 }
00333 
00334 void CRelation::multi_combine_main(const CRelation& GL2)
00335   // get GL2 via reference (to be more efficient)
00336   // compute symmetric difference
00337 {
00338   //cout << "multi-combine relations..." << endl;
00339   adjust_multi_combine(); // keep aware of number of calls
00340 
00341   /*
00342     Compute symmetric difference of the two relation sets.
00343     Memorize common part (intersection) by adding it to ExponentArray.
00344   */
00345 
00346   if ( GL2.Relation_dense ) /* GL2.Relation is dense */
00347     {
00348       if (!Relation_dense) // relation is not dense
00349         convert_Relation_to_dense(); // make it dense!
00350 
00351       /* Zunächst werden die Bits der beiden Relationen
00352          (temporär!) komponentenweise durch "and" verknüpft.
00353          Dadurch werden die Primzahlen ermittelt, die verknüpft Quadrate
00354          ergeben. Diese können dann im Exponentenfeld berücksichtigt werden.
00355          In gewisser Weise wird die Bitstrings komponentenweise wie
00356          mit einem "Halbaddierer" verknüpft.
00357           Additionsergebnis (durch xor) überschreibt anschließend den
00358           Bitstring, während der Übertrag im Exponentenfeld addiert wird.
00359        */
00360       Relation_dense->test_and_add_carry(*GL2.Relation_dense,pMulticombineData->ExponentArray);
00361       (*Relation_dense)._xor(*GL2.Relation_dense); // compute symmetric difference
00362     }
00363   else // GL2.Relation is sparse
00364     if (Relation_dense) // and Relation is dense
00365       { // compute symmetric difference in dense representation,
00366         // whereas the other vector is sparse
00367         const CTinyFBsizetypeVector& R2 = *GL2.Relation_sparse;
00368         for (int pos=0; pos<R2.size(); ++pos)
00369           {
00370             if (Relation_dense->test_and_invert(R2[pos])) ++pMulticombineData->ExponentArray[R2[pos]];
00371           }
00372       }
00373     else
00374       { // compute symmetric difference in sparse representation
00375         int p1 = 0;
00376         int p2 = 0;
00377         const CTinyFBsizetypeVector& R  = *Relation_sparse;
00378         const CTinyFBsizetypeVector& R2 = *GL2.Relation_sparse;
00379         CTinyFBsizetypeVector neueMenge(R.size()+R2.size());
00380         //neueMenge.reset();
00381         while (p2<R2.size() && p1<R.size())
00382           {
00383             while (R2[p2]<R[p1])
00384               {
00385                 neueMenge.fast_append(R2[p2]); ++p2;
00386                 if (p2==R2.size()) goto done;
00387               }
00388             while (R[p1]<R2[p2])
00389               {
00390                 neueMenge.fast_append(R[p1]); ++p1;
00391                 if (p1==R.size()) goto done;
00392               }
00393             while (R2[p2]==R[p1])
00394               {
00395                 ++pMulticombineData->ExponentArray[R[p1]];
00396                 ++p1; ++p2;
00397                 if (p2==R2.size()) goto done;
00398                 if (p1==R.size()) goto done;      
00399               }
00400           }
00401       done:
00402         while (p2!=R2.size()) { neueMenge.fast_append(R2[p2]); ++p2; }
00403         while (p1!=R.size()) { neueMenge.fast_append(R[p1]); ++p1; }
00404         Relation_sparse->copy_from(neueMenge); // take over new set
00405       }
00406 
00407   // don't forget: the new delta has to contain the delta of the other
00408   // relation as well!
00409   mpz_mul(Delta,Delta,GL2.Delta); mpz_mod(Delta,Delta,n);
00410   
00411   //-------------------------------------------------------------------
00412   // IMPORTANT: After the last call of multi_combine_main it is necessary
00413   // to call a closing multi_combine_exit!
00414   // Otherwise the values in "Exponentenfeld" would be left out!
00415   //-------------------------------------------------------------------
00416 
00417   relevant_factor=largest_factor_in_Relation();
00418   //cout << "finished combine." << endl;
00419 }
00420 
00421 
00422 // default action, when an invalid seek occurs in one of the combine methods
00423 void CRelation::seek_emergency_default_handler(istream &, const streampos)
00424 {
00425   throw ios_base::failure("invalid seek position on istream");
00426 }
00427 
00428 // a function pointer, that gets called whenever combine tries to seek to an invalid position
00429 void (*CRelation::seek_emergency_handler)(istream &, const streampos) = CRelation::seek_emergency_default_handler;
00430 
00431 CmpqsFactor CRelation::combine(istream &in, const streampos pos)
00432 {
00433   const streampos merkfpos=in.tellg(); // memorize fileposition
00434   in.seekg(pos); if (in.peek()==EOF) seek_emergency_handler(in,pos);
00435   CmpqsFactor f=combine(in);
00436   in.seekg(merkfpos); // restore memorized fileposition
00437   return f;
00438 }
00439 
00440 CmpqsFactor CRelation::multi_combine_main(istream &in, const streampos pos)
00441 {
00442   const streampos merkfpos=in.tellg(); // memorize fileposition
00443   in.seekg(pos); if (in.peek()==EOF) seek_emergency_handler(in,pos);
00444   CmpqsFactor f=multi_combine_main(in);
00445   in.seekg(merkfpos); // restore memorized fileposition
00446   return f;
00447 }
00448 
00449 
00450 int CStreamDecoder::GetValue()
00451 {
00452   if (ahead_value>0) { int w=ahead_value; ahead_value=0; return w; }
00453 
00454   char c;
00455   in >> c;
00456   if ( c>='A' && c<='Z' ) return c-('A'-1); // A=1,...,Z=26
00457   if ( c>='g' && c<='z' )
00458    {
00459      int h = (c-'g');
00460      ahead_value=(h%5)+1; // next "ahead read" value
00461      return (h/5)+1; 
00462    }
00463   if (c=='0') return 0; // as we have no leading zeros, '0' means 0.
00464   if (c=='$') return -1;
00465   if (c=='%') return -2;
00466 
00467   if (c==' ')
00468    {
00469      MARK;
00470      cerr << "GetValue: Read a space? How to handle this?" << endl;
00471      in.setstate(std::ios::failbit);
00472      throw std::runtime_error("GetValue: read invalid character");
00473    }
00474 
00475   // otherwise the memorized number:
00476   int w;
00477   in.unget();
00478   in >> w;
00479   return w;
00480 }
00481 
00482 void CStreamEncoder::PutValue(const int w)
00483 {
00484   if (w<=5 && w>=1 && prev_value>0) // then output coded value
00485     {
00486       out << char( (prev_value-1)*5 + w-1 + 'g' );
00487       prev_value=0;
00488       return;
00489     }
00490 
00491   if (prev_value>0)
00492    {
00493      out << char(prev_value+('A'-1)); // output value
00494      prev_value=0;
00495    }
00496 
00497   if (w>26) 
00498    {
00499      out << w << " "; // output value without encoding
00500      return;
00501    }
00502   if (w>0)
00503    {
00504      if (w<=4) { prev_value=w; return; } // wait till next time...
00505      out << char(w+('A'-1)); // output value coded as char
00506      return;
00507    }
00508   switch (w)
00509    {
00510      case -2: out << "%"; break;
00511      case -1: out << "$"; break;
00512      case  0: out << "0"; break;
00513      default:
00514       MARK;
00515       cerr << "PutValue: don't know how to handle this..." << endl;
00516       cerr << "w=" << w << endl;
00517       out.setstate(std::ios::failbit);
00518       throw std::invalid_argument("PutValue: invalid value");
00519    }
00520 }
00521 
00522 bool CRelation::is_valid() const
00523 {
00524   mpz_t x,y;
00525   mpz_init(x);
00526   mpz_init_set_ui(y,1);
00527   if (Relation_sparse)
00528     {
00529       for (int i=0; i<Relation_sparse->size(); ++i)
00530         {
00531           mpz_mul_si(y,y,PrimeNumbers[(*Relation_sparse)[i]]);
00532           mpz_mod(y,y,n);
00533         }
00534     }
00535   else
00536     {
00537       for (int i=Relation_dense->first(); i>=0; i=Relation_dense->next(i))
00538         {
00539           mpz_mul_si(y,y,PrimeNumbers[i]);
00540           mpz_mod(y,y,n);
00541         }
00542     }
00543   
00544   mpz_invert(x,Delta,n); mpz_powm_ui(x,x,2,n);
00545 
00546 #ifdef VERBOSE
00547   cout << "checking for congruency: ";
00548   cout << x << " = " << y << " (mod N)" << endl;
00549 #endif
00550   if (mpz_cmp(x,y)!=0) 
00551     {
00552 #ifdef VERBOSE_WARN
00553       MARK; cout << "Relation is invalid: Values are NOT congruent!" << endl;
00554 #endif
00555       mpz_clear(x); mpz_clear(y);
00556       return false;
00557     }
00558  mpz_clear(x); mpz_clear(y);   
00559  return true;
00560 }
00561 
00562 
00563 #include <fstream>
00564 #include <set>
00565 struct myintcompare_
00566 {
00567   inline bool operator() (const int i1, const int i2) const
00568    {
00569      return i1 < i2;
00570    }
00571 };
00572 typedef std::set<int, myintcompare_> TMyIntSet;
00573 
00574 bool CRelation::is_valid(istream &in)
00575 {
00576   static TMyIntSet InductiveDynamicFactorSet; // set of already proven dynamic factors
00577 
00578   CStreamDecoder enc_in(in);
00579   bool retval = false;
00580 
00581   string s;
00582   CmpqsFactor MainFactor;
00583 
00584   mpz_t x,y,Delta;
00585   mpz_init_set_ui(x,1);
00586   mpz_init_set_ui(y,1);
00587   mpz_init_set_ui(Delta,1);
00588  
00589   // save file flags
00590   const ios::fmtflags oldFlags = in.flags(); // memorize old flags of the stream
00591   in.unsetf(ios::hex); in.setf(ios::dec); // enable decimal output (notice: because of "correction factors" there could be a recursive call!)
00592   in.unsetf(ios::showbase); // without any leading prefix
00593  
00594   in >> s; // starting symbol "G"
00595   if (s != "G")
00596     {
00597 #ifdef VERBOSE_WARN
00598       MARK;
00599       cerr << "error: wrong position while reading relation" << endl;
00600 #endif
00601       retval=false; goto done;
00602     }
00603   in >> MainFactor; // read factor (dynamic-factor or special-factor of relation or 1)
00604   in >> s; // delta
00605   mpz_set_str(Delta, s.c_str(), mpzbase_f);
00606   mpz_mod(Delta, Delta, n);
00607 
00608   // now we start to work in hexadecimal notation:
00609   in.unsetf(ios::dec); in.setf(ios::hex); // hexadecimal output
00610   in.unsetf(ios::showbase); // without "0x"-marker
00611   
00612   signed int distance; // hint: we work with differences instead of the values itself
00613 
00614   {
00615     const size_t sizeinbase_of_n = mpz_sizeinbase(n,2);
00616     mpz_set_ui(x,1); // for speedup: collect factors in x as long as x<n
00617 
00618     distance=enc_in.GetValue();
00619     int index=distance;
00620     while (distance >= 0)
00621      {
00622        if (index>=StaticFactorbaseSettings::Size())
00623         {
00624   #ifdef VERBOSE_INFO
00625           MARK;
00626   #endif
00627   #ifdef VERBOSE_WARN
00628         cerr << "static factor outside the factorbase (index " << index << ")" << endl;
00629   #endif
00630         retval=false; goto done;
00631         }
00632 
00633        mpz_mul_si(x,x,PrimeNumbers[index]);
00634        if (mpz_sizeinbase(x,2)>sizeinbase_of_n)
00635         {
00636           mpz_mod(x,x,n); mpz_mul(y,y,x);
00637           mpz_mod(y,y,n); mpz_set_ui(x,1);
00638         }
00639        distance=enc_in.GetValue(); index+=distance;
00640      }
00641     mpz_mul(y,y,x); mpz_mod(y,y,n);
00642   }
00643   
00644   if (distance == -2) // "correction factors" follow
00645     {
00646       /* Korrekturfaktoren sind dynamische Faktoren, die zum Zeitpunkt der Generierung
00647          der gelesenen Relation nicht aufgelöst wurden. Sie müssen daher jetzt verknüpft werden. */
00648       /* correction factors are dynamic factors, that weren't resolved at the time of generating
00649          this relation. They must be considered and combined now! */
00650       int Korrekturfaktor;
00651       while ( (Korrekturfaktor=enc_in.GetValue())>0 )
00652        {
00653           const TMyIntSet::const_iterator p = InductiveDynamicFactorSet.find(Korrekturfaktor);
00654           if (p==InductiveDynamicFactorSet.end())
00655             {
00656 #ifdef VERBOSE_INFO
00657               MARK;
00658 #endif
00659 #ifdef VERBOSE_WARN
00660               cerr << "Unknown correction value (Korrekturfaktor): " << Korrekturfaktor << endl;
00661 #endif
00662               retval=false; goto done;
00663             }
00664           mpz_mul_ui(y,y,Korrekturfaktor); mpz_mod(y,y,n);
00665         }
00666     }
00667 
00668   if (MainFactor.LP1()) mpz_mul_si(y,y,MainFactor.LP1());
00669   if (MainFactor.LP2()) mpz_mul_si(y,y,MainFactor.LP2());
00670   mpz_mod(y,y,n);
00671 
00672   mpz_invert(x,Delta,n); mpz_powm_ui(x,x,2,n);
00673   
00674 #ifdef VERBOSE
00675   cout << "checking for congruency: ";
00676   cout << x << " = " << y << " (mod N)" << endl;
00677 #endif
00678   if (mpz_cmp(x,y)!=0) 
00679     {
00680 #ifdef VERBOSE_WARN
00681       MARK; cout << "Relation is invalid: Values are NOT congruent!" << endl;
00682 #endif
00683       retval=false; goto done;
00684     }
00685 
00686   if (MainFactor.IsTypeOf(CmpqsFactor::single_large_prime))
00687    {
00688      // now, since this relation is correct, other relations that
00689      // rely on this dynamic factor (as Korrekturfaktor)
00690      // can safely use this factor without destroying their correctness
00691      InductiveDynamicFactorSet.insert(MainFactor.int_value());
00692    }
00693 
00694   retval=true; // relation is okay
00695 done:
00696   mpz_clear(Delta); mpz_clear(y); mpz_clear(x);
00697   in.flags(oldFlags); // restore memorized stream flags
00698   return retval;
00699 }
00700 
00701 void CRelation::SanityCheckRelationsFile(const std::string FileName)
00702 {
00703 #ifdef VERBOSE_NOTICE
00704   cout << "Performing sanity check for " << FileName << endl;
00705 #endif
00706   std::ifstream MyFile(FileName.c_str());
00707   if (!MyFile)
00708    {
00709      cerr << "problems to open \"" << FileName << "\"!" << endl;
00710      exit(1);
00711    }
00712 
00713   MyFile.seekg(0,ios::beg);
00714   unsigned int count = 0, line=0, invalid=0, obsolete=0;
00715   while (MyFile)
00716    {
00717      while (MyFile.peek()=='U') { ++line; ++obsolete; MyFile.ignore(1000000,'\n'); }
00718      while (MyFile.peek()=='G')
00719       {
00720         ++count; ++line;
00721         if (!is_valid(MyFile))
00722          {
00723            ++invalid;
00724            cerr << "invalid Relation in " << FileName << ", line " << line << endl;
00725            MyFile.ignore(1000000,'\n');
00726          } else MyFile.ignore(1,'\n');
00727        #ifdef VERBOSE_NOTICE
00728         if (count%500==0) cout << count << " relations validated.\r" << flush;
00729        #endif
00730       }
00731      if (MyFile.peek()!=EOF && MyFile.peek()!='U')
00732       {
00733         ++line; ++invalid;
00734         cerr << "Garbage in " << FileName << ", line " << line << endl;
00735         cerr << "Giving up!" << endl;
00736         break;
00737         //MyFile.ignore(1000000,'\n');
00738       }
00739      // it seems that gcc-3.2.3 has some problems detecting eof,
00740      // I hope this helps...
00741      MyFile.get();
00742      if (MyFile.eof()) break;
00743      MyFile.unget();
00744    }
00745 #ifdef VERBOSE_NOTICE
00746   cout << line << " lines scanned.       " << endl;
00747   if (obsolete) cout << obsolete << " obsolete relations skipped." << endl;
00748   cout << count << " relations validated." << endl;
00749 #endif
00750   if (invalid)
00751    {
00752      cout << invalid << " INVALID relations detected in " << FileName << endl;
00753      exit(1);
00754    }
00755 }

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