qsieve.cc

Go to the documentation of this file.
00001 
00007 #include "at_startup.H"
00008 
00009 // sanity checks
00010 #ifdef IS_CLIENT
00011  #error "qsieve is not a client!"
00012 #endif
00013 
00014 #ifdef IS_SERVER
00015  #error "qsieve is not a server!"
00016 #endif
00017 
00018 #ifdef USE_NETWORK
00019  #error "qsieve uses no network features!"
00020 #endif
00021 
00022 #ifndef IS_STANDALONE
00023  #error "qsieve is a standalone application!"
00024 #endif
00025 
00026 
00027 
00028 extern "C"
00029 {
00030  #include <unistd.h>
00031 }
00032 
00033 #include <cstdio>
00034 #include <cstdlib>
00035 #include <fstream>
00036 #include <sstream>
00037 #include <cmath>
00038 #include <gmp.h>
00039 #include <list>
00040 #include <set>
00041 #include <ctime>
00042 
00043 #include "qsieve.H"
00044 #include "StaticFactorbase.H"
00045 
00046 
00047 #include "FactorFound.H"
00048 TFoundFactors FoundFactors;
00049 
00050 
00051 
00052 #include <vector>
00053 #include <stack>
00054 #include <algorithm>
00055 
00056 
00057 #ifdef NOTIFY_PARENT
00058  #warning "undefining NOTIFY_PARENT, since this is not a networked server"
00059  #undef NOTIFY_PARENT
00060 #endif
00061 
00062 
00063 
00064 
00065 const string RecoveryFile         = "recovery.dat";
00066 const string FoundFactorsFile     = "FoundFactors.dat";
00067 const string StaticRelationsFile  = "static_relations.dat";
00068 const string SpecialRelationsFile = "special_relations.dat";
00069 
00070 
00071 // provide streams for storing relations and other data
00072 // *************************************************************************
00073 // **** important:
00074 // **** If "ostream" and "istream" are handled by the same filebuf,
00075 // **** then you *must not* rely on 
00076 // **** "tellp()" and "tellg()" behave independently from each other!
00077 // **** Any write operation may change also the value of "tellg()"
00078 // **** and any read operation may change the value of "tellp()"!
00079 // ************************************************************************* 
00080 
00081 
00082 // for Recovery
00083 filebuf Recovery_buffer;
00084 ostream Recovery_to_file (&Recovery_buffer);
00085 istream Recovery_from_file (&Recovery_buffer);
00086 
00087 
00088 
00089 #include "mpqsPolynom.H"
00090 
00091 
00092 mpz_t n, // number to factorize (will be reduced during factorization)
00093       kN; // input for MPQS (includes a suitable multiplier)
00094 
00095 
00096 #include "StaticRelations.H"
00097 #include "DynamicRelations.H"
00098 #include "SpecialRelations.H"
00099 
00100 #include "Sieving.H"
00101 #include "ConfigFile.cc"
00102 
00103 
00104 CmpqsPolynom Polynom; // object to manage polynomial computations for multipolynomial sieve (MPQS)
00105 #include "mpqsStatistics.cc" // statistical stuff about found relations, client connections, etc.
00106 
00107 
00108 #include "modulo.H" // modulo operations for unsigned int
00109 using namespace numtheory;
00110 
00111 #include "FactorFound.cc"
00112 #include "polynomial.H" /* for fast polynomial arithmetic & fft-continuation */
00113 #include "fft_param.cc"  /* discrete fast fourier transform */
00114 #include "elliptic_curve.H" /* invariant part of elliptic curve method (ecm) */
00115 #include "elliptic_curve-variant.cc" /* variant part of elliptic curve method (ecm) */
00116 
00117 #include "ExitManager.cc" /* controlled termination of program */
00118 #include "StaticRelations.cc"
00119 
00120 // this stuff may only be needed by server or stand-alone version
00121 #include "easy_factor.H"
00122 
00123 
00124 // this is a predicate stating "false"
00125 const bool without_multi_combine_init = false; // true ->multi-init, false ->no multi_init on StaticRelations::insert
00126 
00127 #include "CRelation-inc.cc"
00128 #include "SpecialRelations.cc"
00129 
00130 #include "parse_term.cc"
00131 
00132 
00133 void process_ecm()
00134 {
00135   streampos fpos = Recovery_from_file.tellg();
00136   int Anzahl_Kurven = 0;
00137   string s;
00138 
00139   srand(time(NULL)); // setting a random seed (time(NULL) should satisfy for our needs)
00140   
00141   unsigned int dezimalstellen = mpz_sizeinbase(n,10);
00142   tune_parameters(dezimalstellen); // as the name says: tuning of parameters according to our input number
00143 
00144   Recovery_from_file >> Anzahl_Kurven;
00145   Recovery_from_file.ignore(1,'\n'); // overread "end of line"
00146 
00147   {
00148    ifstream in("ecm-recover.dat");
00149    if (in) // does a recovery file exist?
00150     {
00151      in.close();
00152      elliptic_curves elliptic_curve; // create a curve
00153      elliptic_curve.go(-1,elcu_Phase1,elcu_Phase2); // try to recover curve and retry factorization with elliptic curve
00154     }
00155   }
00156 
00157   while (Anzahl_Kurven<elcu_Kurven)
00158   {
00159 
00160     Anzahl_Kurven++;
00161     cout << "elliptic curve #" << Anzahl_Kurven << "/" << elcu_Kurven << endl;
00162 
00163     int ecm_sigma = rand(); // choose a random curve
00164     elliptic_curves elliptic_curve; // create curve
00165     elliptic_curve.go(ecm_sigma,elcu_Phase1,elcu_Phase2); // try factorization with elliptic curve
00166 
00167     // write number of processed curves to recovery file
00168     Recovery_to_file.seekp(fpos); 
00169     Recovery_to_file << Anzahl_Kurven << endl << flush;
00170 
00171     // found a factor?
00172     if (dezimalstellen==mpz_sizeinbase(n,10)) continue; // no new factor
00173     
00174     // digits of n has changed -> new factor
00175 
00176     if (mpz_probab_prime_p(n,probab_prime_checks))
00177       {
00178         Factorization_to_file << MAL(n);
00179         cout << "remaining factor: " << n << endl;
00180         cout << "remaining factor is most probably prime!" << endl;
00181         mpz_set_ui(n,1); // n has been factorized
00182       }
00183 
00184     if ( (mpz_cmp_ui(n,1)==0) || Potenztest(n) ) // factorization complete?
00185       { 
00186         cout << "factorization successfully completed." << endl;
00187         Factorization_to_file << endl;
00188         ExitManager::StopFactorization(); // terminate program (do finalize work)
00189       }
00190 
00191     // tune parameters for further ecm-rounds...
00192     dezimalstellen=mpz_sizeinbase(n,10);
00193     tune_parameters(dezimalstellen);
00194 
00195     // since the number to factorize has become smaller, the recovery-file need to be updated as well!
00196     Recovery_buffer.close(); // close file
00197     Recovery_buffer.open(RecoveryFile.c_str(),ios::in|ios::out|ios::trunc); // re-open (-> create empty file)
00198     Recovery_to_file << n << endl; // write out number to factorize
00199     fpos = Recovery_from_file.tellg(); // mark position
00200     Recovery_to_file << Anzahl_Kurven << endl << flush; // store number of curves done so far
00201     ecm_curves_processed=Anzahl_Kurven;
00202 
00203   }
00204   cout << "ECM-Phase (standalone) completed." << endl;
00205 }
00206 
00207 
00208 
00209 
00210 void cleanup_files()
00211 {
00212 #ifdef VERBOSE_INFO
00213   cout << "cleaning files..." << endl;
00214 #endif
00215   StaticRelations::cleanup_files();
00216   SpecialRelations::cleanup_files();
00217   DynamicRelations::cleanup_files();
00218   Recovery_buffer.close();
00219   remove(RecoveryFile.c_str());
00220 }
00221 
00222 void cleanup_memory()
00223 {
00224 #ifdef VERBOSE_INFO
00225   cout << "cleanup allocated memory" << endl;
00226 #endif
00227   StaticRelations::cleanup_memory();
00228   CSieveStaticFactors::destruct();
00229   mpz_clear(CmpqsFactor::DLP_Threshold);
00230   mpz_clear(kN); mpz_clear(n);
00231 }
00232 
00233 
00234 
00235 
00236 int main(const int argc, const char* const argv[])
00237 {
00238 
00239 #ifdef USE_NCURSES
00240   new Cncursed(); // trigger activation of ncursed streams
00241 #endif
00242 
00243   PrintHeader("Qsieve standalone");
00244     
00245   if (argc>2)
00246     {
00247       cerr << "number for factorization expected!" << endl;
00248       exit(1);
00249     }
00250   
00251   const bool recover = (argc==1); // without argument: Recovery-Mode
00252 
00253   cout.setf(ios::fixed); // fixed decimal notation, not scientific notation!
00254 
00255   mpz_init(n); // our number to factorize
00256   mpz_init(kN);
00257   ExitManager::register_exithandler(cleanup_memory); // on successful exit free allocated data
00258 
00259   Read_ConfigFile();
00260 
00261   if (!recover) // not in recovery-mode -> evaluate arguments
00262     { 
00263       // get and evaluate given number
00264       char* const neuer_str = strdup(argv[1]);
00265       char* str = neuer_str; 
00266       if (!parse_term::get_number(n, str))
00267         {
00268           cout << "Wrong input at: '" << str << "'" << endl;
00269           exit(1);
00270         }
00271       else
00272         if (str[0]!='\0')
00273           {    
00274             cout << "Syntax error in input term. (parenthesis?)" << endl;
00275             exit(1);
00276           }
00277         else
00278           if (mpz_cmp_ui(n,0)<=0)
00279             {
00280               cout << "Input must be positive natural number!" << endl;
00281               exit(1);
00282             }
00283       free(neuer_str); // don't call "delete []" because of "stdup/malloc"
00284       FoundFactors.regarding=argv[1];
00285       mpz_set(FoundFactors.regarding_numeric_value,n);
00286     }
00287 
00288   if (recover)
00289     {
00290       // Recovery: continue a factorization, which was previously aborted
00291       // (try to) open the necessary file streams
00292       StaticRelations::FileBuffer.open(StaticRelationsFile.c_str(),ios::in|ios::out);
00293       SpecialRelations::FileBuffer.open(SpecialRelationsFile.c_str(),ios::in|ios::out);
00294       if (!DynamicRelations::FileBuffer.open(DynamicRelationsFile.c_str(),ios::in|ios::out))
00295        {
00296          cerr << "Cannot access " << DynamicRelationsFile << endl;
00297          exit(1);
00298        }
00299       Recovery_buffer.open(RecoveryFile.c_str(),ios::in|ios::out|ios::ate);
00300 
00301       // offenbar wird trotz ios::ate nicht (immer) ans Ende positioniert
00302       // deshalb wird die Testabfrage modifiziert:
00303       if (Recovery_from_file) Recovery_from_file.seekg(0,ios::end);
00304 #ifdef STL_STREAM_workaround
00305       if ( (!Recovery_from_file) || (Recovery_from_file.tellg()==std::streampos(0)) || (Recovery_from_file.tellg()==std::streampos(-1)) )
00306 // tellg()==0 indicates empty file -> we cannot recover
00307 // tellg()==-1 indicates failure -> we cannot recover
00308 // remark:
00309 //  in gcc 3.4 (cvs-experimental-2003-10-17 we cannot compare with "<" !!)
00310 //  do we really need a workaround to check this condition? 
00311 #else
00312       if ( (!Recovery_from_file) || (Recovery_from_file.tellg()<1) )
00313 #endif /* STL_STREAM_workaround */
00314         {
00315           cerr << "Recovery not possible!" << endl;
00316           exit(1);
00317         }
00318       
00319       Recovery_from_file.seekg(0,ios::beg);
00320       Recovery_to_file.seekp(0,ios::beg);
00321       Recovery_from_file >> n; // retrieve number
00322       Recovery_from_file.ignore(1,'\n');
00323 
00324       cout << "Continue factorization for " << endl;
00325       cout << n << endl;
00326 
00327       // mark recovery-mode in Factorization-File! One never knows, what has
00328       // happened to that file in the mean time!
00329       Factorization_to_file << " [RECOVERY] "; // flush not necessary... 
00330       FoundFactors.AutoLoad();
00331     }
00332   else
00333     {
00334       // First start of this factorization (i.e. not a recovery)
00335       // open streams
00336       StaticRelations::FileBuffer.open(StaticRelationsFile.c_str(),ios::out|ios::trunc);
00337       SpecialRelations::FileBuffer.open(SpecialRelationsFile.c_str(),ios::in|ios::out|ios::trunc);
00338       if (!DynamicRelations::FileBuffer.open(DynamicRelationsFile.c_str(),ios::in|ios::out|ios::trunc))
00339        {
00340          cerr << "Cannot access " << DynamicRelationsFile << endl;
00341          exit(1);
00342        }
00343 
00344       Recovery_buffer.open(RecoveryFile.c_str(),ios::in|ios::out|ios::trunc);
00345       
00346       cout_status << "Starting factorization for" << endl;
00347       cout_status << n << endl;
00348       
00349       Factorization_to_file << endl << "Factorization of " << argv[1] << ":" << endl;
00350       Factorization_to_file << n << " = " << endl;
00351       
00352       easy_factor(); // remove "easy" detectable factors
00353       
00354 #ifdef VERBOSE_NOTICE
00355       cout_status << "Starting factorization with ECM and MPQS for" << endl;
00356       cout_status << n << endl;
00357 #endif
00358       Recovery_to_file << n << endl;
00359       unlink("ecm-recover.dat"); // remove any existent ecm recovery file
00360     }
00361   ExitManager::register_exithandler(cleanup_files); // on successful exit delete the files
00362 
00363 
00364 
00365   // The standalone-version should use elliptic curves, too.
00366   if (!SkipECM) process_ecm(); // start ECM...
00367 
00368 #if defined(USE_DFT) || (CONTINUATION_METHOD==2)
00369   // at this place, all possible functions that made possible use of
00370   // discrete fast fourier transform have been finished.
00371   //  --> we can release the DFT-object and associated auxiliary memory...
00372   polynomial::clear_dft_tempmemory();
00373 #endif /* USE_DFT */
00374 
00375   // now prepare everything for the Quadratic Sieve...
00376 
00377   determine_best_MPQS_Multiplier(n,kN,MPQS_Multiplier); // calculate a good/optimal value for fastest possible sieving
00378   tune_parameters(mpz_sizeinbase(n,10)); // tune parameters for n
00379 
00380   
00381   if ( sqrt(mpz_get_d(kN)) < PhysicalSieveSize )
00382     {
00383       cerr << "Sieve size too big (you may want to reduce its size)!" << endl;
00384       exit(1);
00385     }
00386 
00387   // Set a threshold for Double-Large-Primes,
00388   // this is the square of the maximal Single Large Prime...
00389   mpz_init(CmpqsFactor::DLP_Threshold);
00390   mpz_set_ui(CmpqsFactor::DLP_Threshold,SingleLargePrime_Threshold);
00391   mpz_mul(CmpqsFactor::DLP_Threshold,CmpqsFactor::DLP_Threshold,CmpqsFactor::DLP_Threshold);
00392   
00393   StaticFactorbase::compute_StaticFactorbase();
00394   CSieveStaticFactors::initialize();
00395   SieveControl::compute_SieveThreshold(); // Threshold for detecting relations during sieving phase
00396   for (int i=0; i<64; ++i) SieveArray_[i]=-1; // initialize array underflow trigger values
00397   Polynom.compute_first_polynomial(kN,LogicalSieveSize); // compute the first MPQS polynomial to sieve with
00398   
00399   if (recover)
00400     {
00401       StaticRelations::Load(); // read in Static Relations
00402       DynamicRelations::Load(); // read in Dynamic Relations
00403       SpecialRelations::Load();
00404       statistical_data::ProgressStats.take_sample(); // first statistical sample right here
00405         // CycleSearch triggers taking a sample when finding a cycle,
00406         // but this sample wouldn't contain the full DLP size (see CycleSearch)!
00407         // So we need the first sample taken before the first CycleSearch...
00408       SpecialRelations::CycleSearch();
00409 
00410 #ifdef SAFEMODE
00411       // are all the relations valid?
00412       CRelation::SanityCheckRelationsFile(StaticRelationsFile);
00413       CRelation::SanityCheckRelationsFile(DynamicRelationsFile);
00414       CRelation::SanityCheckRelationsFile(SpecialRelationsFile);
00415 #endif      
00416       streampos fpos = Recovery_from_file.tellg();
00417       Polynom.load_if_available(Recovery_from_file); // get current polynomial (to continue factorization)
00418       Recovery_to_file.seekp(fpos);
00419     }
00420 
00421 
00422   display_StatusLegend();
00423   
00424   // The ultimate loop:
00425   while(true) // sieve relations as long no factorization has been found.
00426    {
00427      // for Recovery:
00428      streampos fpos = Recovery_to_file.tellp();
00429      Polynom.save(Recovery_to_file); // store current MPQS polynomial (for recovery)
00430      Recovery_to_file.seekp(fpos);
00431      do_sieving();
00432      Polynom.compute_next_polynomial();
00433    }
00434 
00435 #ifdef VERBOSE_INFO  
00436   cout << endl << "Session ended successfully." << endl;
00437 #endif
00438   return 0;
00439 }

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