00001
00006 #include "easy_factor.H"
00007 #include <cmath>
00008 #include "modulo.H"
00009 #include "elliptic_curve.H"
00010 #include <sstream>
00011
00012 extern std::string MAL(const mpz_t factor, const std::ostringstream &comment);
00013 extern std::string MAL(const mpz_t factor, const unsigned int exponent, const std::ostringstream &comment);
00014 extern std::string MAL(const mpz_t factor, const unsigned int exponent=1);
00015 extern std::string MAL(const unsigned long int factor, const unsigned int exponent=1);
00016 extern void tune_parameters(const unsigned int Dezimalstellen);
00017
00018 #include <fstream>
00019 extern std::ofstream Factorization_to_file;
00020
00021 #ifdef REACT_ON_SIGUSR
00022 #include "usr_signals.H"
00023 extern Cusr_signal_proxy USRSignalHandler;
00024 #endif
00025
00026 class ExitManager
00027 {
00028 public:
00029 static void StopFactorization();
00030 };
00031
00032
00033
00034 extern bool compiled_IS_STANDALONE();
00035
00036
00037
00038 void pollard(const int runden)
00039 {
00040 #ifdef VERBOSE_INFO
00041 cout << "Trying Pollard-rho up to " << runden << endl;
00042 #endif
00043 mpz_t a,a2,x;
00044 mpz_init(a); mpz_init(a2); mpz_init(x);
00045 mpz_set_ui(a,1); mpz_set(a2,a);
00046
00047 for (int i=1; i<=runden; i++)
00048 {
00049 #ifdef REACT_ON_SIGUSR
00050 if (USRSignalHandler.got_SIGUSR1()) break;
00051 if (USRSignalHandler.got_SIGUSR2()) break;
00052 #endif
00053 mpz_mul(a,a,a); mpz_add_ui(a,a,1); mpz_mod(a,a,n);
00054 mpz_mul(a2,a2,a2); mpz_add_ui(a2,a2,1); mpz_mod(a2,a2,n);
00055 mpz_mul(a2,a2,a2); mpz_add_ui(a2,a2,1); mpz_mod(a2,a2,n);
00056 mpz_sub(x,a2,a);
00057 mpz_gcd(x,x,n);
00058 while (mpz_cmp_ui(x,1)!=0)
00059 {
00060 if (mpz_cmp(x,n)==0)
00061 {
00062 #ifdef VERBOSE_INFO
00063 cout << "trivial factor in round " << i << endl;
00064 #endif
00065 continue;
00066 }
00067 unsigned int exp=mpz_remove(n,n,x);
00068 if (mpz_probab_prime_p(x,probab_prime_checks))
00069 {
00070 cout << x << " is factor. [round " << i <<"]" << endl;
00071 Factorization_to_file << MAL(x,exp) << flush;
00072 }
00073 else
00074 {
00075 cout << x << " is a composite factor. [round " << i <<"]" << endl;
00076 std::ostringstream comment;
00077 comment << " [rho/composite]";
00078 Factorization_to_file << MAL(x,exp,comment) << flush;
00079 }
00080 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00081 mpz_gcd(x,x,n);
00082 }
00083 };
00084 done:
00085 mpz_clear(a); mpz_clear(a2); mpz_clear(x);
00086 }
00087
00088 bool try_memorized_factors(mpz_t n, const std::string& memfilename)
00089 {
00090
00091 bool reduced = false;
00092
00093 std::ifstream in(memfilename.c_str());
00094 if (in)
00095 {
00096 #ifdef VERBOSE_INFO
00097 cout << "Trial division by factors in " << memfilename << endl;
00098 #endif
00099 mpz_t x;
00100 mpz_init(x);
00101 while (!in.eof())
00102 {
00103 while (isspace(in.peek())) in.get();
00104 if (in.peek()=='#')
00105 {
00106 in.ignore(1000,'\n');
00107 continue;
00108 }
00109
00110
00111
00112 in.get();
00113 if (in.eof()) break;
00114 in.unget();
00115
00116 in >> x;
00117
00118 if (mpz_cmp(n,x)==0) return reduced;
00119 while (mpz_divisible_p(n,x))
00120 {
00121 if (mpz_probab_prime_p(x,probab_prime_checks))
00122 {
00123 cout << x << " is factor. [memorized]" << endl;
00124 std::ostringstream comment;
00125 comment << " [memorized]";
00126 Factorization_to_file << MAL(x,comment) << flush;
00127 }
00128 else
00129 {
00130 cout << x << " is a composite factor. [memorized]" << endl;
00131 std::ostringstream comment;
00132 comment << " [composite/memorized]";
00133 Factorization_to_file << MAL(x,comment) << flush;
00134 }
00135 mpz_divexact(n,n,x); reduced=true;
00136 }
00137 while (isspace(in.peek())) in.get();
00138 }
00139 mpz_clear(x);
00140 }
00141 else
00142 {
00143 #ifdef VERBOSE_WARN
00144 cerr << memfilename << " inaccessible!" << endl;
00145 #endif
00146 }
00147 return reduced;
00148 }
00149
00150 #include "pollard_phi.cc"
00151 #include "fibonacci_ppm1.cc"
00152
00153 bool Potenztest(const mpz_t n)
00154 {
00155
00156
00157 mpz_t y;
00158 mpz_init(y);
00159 for (unsigned int k=mpz_sizeinbase(n,256); k>1; k--)
00160 {
00161
00162 if (mpz_root(y,n,k))
00163 {
00164 cout << y << "^" << k << " is ";
00165 Factorization_to_file << MAL(y,k);
00166 if (!mpz_probab_prime_p(y,probab_prime_checks))
00167 {
00168 cout << "composite ";
00169 Factorization_to_file << " [composite power]";
00170 }
00171 Factorization_to_file << flush;
00172 cout << "factor." << endl;
00173 mpz_clear(y);
00174 return true;
00175 }
00176 }
00177 mpz_clear(y);
00178 return false;
00179 }
00180
00181
00182 #include "fermat.cc"
00183
00184 void easy_factor()
00185 {
00186
00187
00188
00189
00190 if (!SkipFermat) fermat_like_method();
00191
00192
00193
00194 const unsigned long int UpperLimit_Easy = 1000000;
00195 #ifdef VERBOSE_INFO
00196 cout << "Trialdivision up to " << UpperLimit_Easy << endl;
00197 #endif
00198 {
00199 const unsigned int some_primes [] = { 2,3,5,7,11,13,0 };
00200 unsigned long int p = 0;
00201
00202
00203 for (unsigned int index=0; some_primes[index]; ++index)
00204 {
00205 p=some_primes[index];
00206
00207 int exp=0;
00208 while (mpz_divisible_ui_p(n,p)) { mpz_divexact_ui(n,n,p); exp++; }
00209 if (exp>0)
00210 {
00211 cout << p << "^" << exp << " is factor." << endl;
00212 Factorization_to_file << MAL(p,exp);
00213 }
00214 }
00215
00216
00217 unsigned int delta;
00218 if (p%6==1) delta=4;
00219 else
00220 if (p%6==5) delta=2;
00221 else
00222 {
00223 MARK;
00224 cerr << "Something is wrong with some_primes!" << endl;
00225 exit(1);
00226 }
00227
00228 while (p<UpperLimit_Easy)
00229 {
00230 p+=delta; delta=6-delta;
00231 if ( p%5==0 || p%7==0 || p%11==0 || p%13==0 ) continue;
00232
00233 int exp=0;
00234 while (mpz_divisible_ui_p(n,p)) { mpz_divexact_ui(n,n,p); exp++; }
00235 if (exp>0)
00236 {
00237 cout << p << "^" << exp << " is factor." << endl;
00238 Factorization_to_file << MAL(p,exp);
00239 if (mpz_cmp_ui(n,1)==0) break;
00240 }
00241 }
00242
00243 Factorization_to_file.flush();
00244 }
00245
00246 if (Potenztest(n)) mpz_set_ui(n,1);
00247 if (mpz_cmp_ui(n,1)==0) goto done;
00248 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00249
00250 {
00251 std::string cached_factorfile;
00252 #if defined(PKGDATADIR)
00253 cached_factorfile = PKGDATADIR;
00254 cached_factorfile+="/";
00255 #endif
00256 cached_factorfile+= "fibonacci.factors";
00257
00258 if (try_memorized_factors(n,cached_factorfile))
00259 {
00260 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00261 }
00262 }
00263
00264 {
00265 unsigned int dezimalstellen = mpz_sizeinbase(n,10);
00266 tune_parameters(dezimalstellen);
00267 pollard(rho_Phase);
00268
00269 if (Potenztest(n)) mpz_set_ui(n,1);
00270 if (mpz_cmp_ui(n,1)==0) goto done;
00271 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00272
00273 if (dezimalstellen != mpz_sizeinbase(n,10))
00274 {
00275 dezimalstellen=mpz_sizeinbase(n,10);
00276 tune_parameters(dezimalstellen);
00277 }
00278
00279 if (UsePhimat)
00280 {
00281
00282
00283
00284 phimat2(); if (mpz_cmp_ui(n,1)==0) goto done;
00285 }
00286
00287 #if 1
00288 if (dezimalstellen>200)
00289 {
00290
00291
00292
00293
00294 fibonacci_ppm1(100000,0);
00295 if (dezimalstellen != mpz_sizeinbase(n,10))
00296 {
00297 if (Potenztest(n)) mpz_set_ui(n,1);
00298 if (mpz_cmp_ui(n,1)==0) goto done;
00299 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00300 dezimalstellen=mpz_sizeinbase(n,10);
00301 tune_parameters(dezimalstellen);
00302 }
00303 }
00304 #endif
00305
00306
00307 #if 1
00308
00309
00310
00311
00312
00313
00314
00315 if ( !compiled_IS_STANDALONE() || (compiled_IS_STANDALONE() && mpz_sizeinbase(n,10)>70))
00316 if (!SkipEasyECM)
00317 {
00318
00319
00320
00321
00322
00323 for (int i=0; i<10; ++i)
00324 {
00325 elliptic_curves elliptic_curve;
00326 elliptic_curve.go(7+i,60000,15000000);
00327
00328 if (dezimalstellen != mpz_sizeinbase(n,10))
00329 {
00330 if (Potenztest(n)) mpz_set_ui(n,1);
00331 if (mpz_cmp_ui(n,1)==0) goto done;
00332 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00333 dezimalstellen=mpz_sizeinbase(n,10);
00334 tune_parameters(dezimalstellen);
00335 }
00336 }
00337 }
00338 #endif
00339
00340
00341 #if 1
00342 if (SkipPhi || (phi_Phase1<=0 && phi_Phase2<=0))
00343 {
00344 #ifdef VERBOSE_NOTICE
00345 cout << "Phi-Phase is deactivated!" << endl;
00346 #endif
00347 }
00348 else
00349 {
00350 pollard_phi(phi_Phase1,phi_Phase2);
00351 if (dezimalstellen != mpz_sizeinbase(n,10))
00352 {
00353 if (Potenztest(n)) mpz_set_ui(n,1);
00354 if (mpz_cmp_ui(n,1)==0) goto done;
00355 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00356 dezimalstellen=mpz_sizeinbase(n,10);
00357 tune_parameters(dezimalstellen);
00358 }
00359 }
00360 #endif
00361
00362 if (SkipFibonacci || (phi_Phase1<=0 && phi_Phase2<=0))
00363 {
00364 #ifdef VERBOSE_NOTICE
00365 cout << "Fibonacci-Phase is deactivated!" << endl;
00366 #endif
00367 }
00368 else
00369 {
00370 fibonacci_ppm1(phi_Phase1,phi_Phase2);
00371 if (dezimalstellen != mpz_sizeinbase(n,10))
00372 {
00373 if (Potenztest(n)) mpz_set_ui(n,1);
00374 if (mpz_cmp_ui(n,1)==0) goto done;
00375 if (mpz_probab_prime_p(n,probab_prime_checks)) goto done;
00376 dezimalstellen=mpz_sizeinbase(n,10);
00377 tune_parameters(dezimalstellen);
00378 }
00379 }
00380 }
00381
00382 done:
00383 #ifdef VERBOSE_NOTICE
00384 cout << "remaining number:" << endl << n << endl;
00385 #endif
00386
00387 if ( (mpz_cmp_ui(n,1)==0) || Potenztest(n) )
00388 {
00389 Factorization_to_file << endl;
00390 ExitManager::StopFactorization();
00391 }
00392
00393 if (mpz_probab_prime_p(n,probab_prime_checks))
00394 {
00395 Factorization_to_file << MAL(n) << endl;
00396 cout << "remaining number is most probably a prime!" << endl;
00397 mpz_set_ui(n,1);
00398 ExitManager::StopFactorization();
00399 }
00400
00401 }