00001
00007 void fermat_like_method()
00008 {
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef VERBOSE_NOTICE
00029 cout << "starting Fermat factorization method" << endl;
00030 #endif
00031 if (mpz_sizeinbase(n,10)<50)
00032 {
00033 cout << "number too small, it's not worthwhile do proceed; skipping fermat..." << endl;
00034 return;
00035 }
00036
00037 const unsigned int Witnesses = 4;
00038 const unsigned int Witness[Witnesses] = { 23*41*59, 35*29*37, 31*43*47, 61*67 };
00039 const unsigned int Maxbits = 65536;
00040 unsigned char squareflags[Maxbits];
00041
00042
00043 for (unsigned int j=0; j<Maxbits; ++j) squareflags[j]=0;
00044 for (unsigned int i=0; i<Witnesses; ++i)
00045 for (unsigned int j=0; j<Witness[i]; ++j) squareflags[(j*j)%Witness[i]] |= 1<<i;
00046
00047 mpz_t c,r,h;
00048 mpz_init(c); mpz_init(r); mpz_init(h);
00049
00050 const unsigned int k_max = 0x100;
00051 for (unsigned int k=0; k<k_max; ++k)
00052 {
00053 #ifdef REACT_ON_SIGUSR
00054 if (USRSignalHandler.got_SIGUSR1()) break;
00055 if (USRSignalHandler.got_SIGUSR2()) break;
00056 #endif
00057 mpz_set_ui(c,2*2*3*5*7*11*13*17*19); mpz_pow_ui(c,c,4);
00058 unsigned int m = 1;
00059 if (k&0x001) m*=2;
00060 if (k&0x002) m*=3;
00061 if (k&0x004) m*=5;
00062 if (k&0x008) m*=7;
00063 if (k&0x010) m*=11;
00064 if (k&0x020) m*=13;
00065 if (k&0x040) m*=17;
00066 if (k&0x080) m*=19;
00067 mpz_mul_ui(c,c,m);
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 #if defined(VERBOSE_INFO)
00089 cout << "using Fermat multiplier " << c << " \r" << flush;
00090 #endif
00091 mpz_mul(c,c,n); mpz_sqrt(r,c); mpz_mul(h,r,r); mpz_sub(h,h,c);
00092 mpz_mul_ui(r,r,2);
00093
00094 struct { unsigned int h,r; } ring[Witnesses];
00095 for (unsigned int i=0; i<Witnesses; ++i)
00096 {
00097 ring[i].h=mpz_remainder_ui(h,Witness[i]);
00098 ring[i].r=mpz_remainder_ui(r,Witness[i]);
00099
00100 }
00101
00102 for (unsigned int delta=1; delta<50000; ++delta)
00103 {
00104
00105 mpz_add(h,h,r); mpz_add_ui(h,h,1); mpz_add_ui(r,r,2);
00106 for (unsigned int i=0; i<Witnesses; ++i)
00107 {
00108 ring[i].h+=ring[i].r+1; if (ring[i].h>=Witness[i]) ring[i].h-=Witness[i];
00109 ring[i].r+=2; if (ring[i].r>=Witness[i]) ring[i].r-=Witness[i];
00110 }
00111
00112 if (!(squareflags[ring[0].h] & 0x01)) continue;
00113 if (!(squareflags[ring[1].h] & 0x02)) continue;
00114 if (!(squareflags[ring[2].h] & 0x04)) continue;
00115 if (!(squareflags[ring[3].h] & 0x08)) continue;
00116
00117 if (mpz_perfect_square_p(h))
00118 {
00119 #if 1 || defined(VERBOSE_INFO)
00120 cout << endl << "delta=" << delta << ": Square detected..." << endl;
00121 #endif
00122 mpz_div_ui(r,r,2); mpz_sqrt(h,h); mpz_add(h,h,r);
00123 mpz_gcd(h,h,n);
00124 if (mpz_cmp_ui(h,1)!=0)
00125 {
00126 mpz_divexact(n,n,h);
00127
00128
00129 if (mpz_probab_prime_p(h,probab_prime_checks))
00130 {
00131 #if 0
00132
00133 {
00134 mpz_t sum,N,x;
00135 mpz_init(sum); mpz_init(N); mpz_init(x);
00136 mpz_add(sum,n,h); mpz_div_ui(sum,sum,2); mpz_mul(N,n,h);
00137 mpz_sqrt(x,N); mpz_sub(sum,sum,x);
00138 cout << "phimat-value --> " << sum << endl;
00139 mpz_clear(x); mpz_clear(N); mpz_clear(sum);
00140 }
00141 #endif
00142
00143 cout << h << " is factor." << endl;
00144 std::ostringstream comment;
00145 comment << " [fer]";
00146 Factorization_to_file << MAL(h,comment) << flush;
00147 }
00148 else
00149 {
00150 fermat_like_method();
00151 mpz_swap(n,h);
00152 if (mpz_probab_prime_p(h,probab_prime_checks))
00153 {
00154 cout << h << " is factor." << endl;
00155 std::ostringstream comment;
00156 comment << " [fer]";
00157 Factorization_to_file << MAL(h,comment) << flush;
00158 }
00159 else
00160 {
00161 cout << h << " is a composite factor." << endl;
00162 if (Potenztest(h)) Factorization_to_file << " [fer]" << flush;
00163 else
00164 {
00165 std::ostringstream comment;
00166 comment << " [fer] [composite]";
00167 Factorization_to_file << MAL(h,comment) << flush;
00168 }
00169 }
00170 }
00171 if (!mpz_probab_prime_p(h,probab_prime_checks)) fermat_like_method();
00172 k=k_max; break;
00173 }
00174 }
00175 }
00176 }
00177 #ifdef VERBOSE_INFO
00178 cout << endl;
00179 #endif
00180 mpz_clear(h); mpz_clear(r); mpz_clear(c);
00181 }
00182
00183
00184 #include "utils.H"
00185 #include <vector>
00186 #include <algorithm>
00187
00188 class entry
00189 {
00190 private:
00191 mp_limb_t hashval;
00192 friend class phimahashvecs;
00193 static unsigned int iL;
00194 static mpz_t L;
00195 public:
00196 static mpz_t Base;
00197 entry(const unsigned int index)
00198 {
00199 if (index==iL+1)
00200 {
00201
00202 ++iL; mpz_mul(L,L,Base); mpz_mod(L,L,n);
00203 }
00204 else
00205 {
00206 mpz_powm_ui(L,Base,index,n);
00207 }
00208 hashval=mpz_getlimbn(L,0);
00209 }
00210
00211 ~entry() { }
00212 const mpz_t& get_mpz(const unsigned int index) const
00213 {
00214 if (index==iL) return L;
00215 else
00216 {
00217 mpz_powm_ui(L,Base,index,n);
00218 return L;
00219 }
00220 }
00221 mp_limb_t get_hash() const { return hashval; }
00222 bool operator< (const entry &rhs) const
00223 {
00224
00225
00226 return (hashval<rhs.hashval);
00227 }
00228 bool operator== (const entry &rhs) const
00229 {
00230 return (hashval==rhs.hashval);
00231 }
00232 signed int compare(const mp_limb_t rhs) const
00233 {
00234
00235 return (hashval<rhs) ? -1 : (hashval>rhs) ? 1 : 0;
00236 }
00237
00238 };
00239
00240 class phimavec : private std::vector<entry>
00241 {
00242 private:
00243 friend class phimahashvecs;
00244 double d_linear_approx_multiplicator;
00245 public:
00246 phimavec() : d_linear_approx_multiplicator(0.0) { }
00247 ~phimavec() { }
00248 void sort()
00249 {
00250
00251 std::sort(begin(),end());
00252
00253 erase(std::unique(begin(),end()),end());
00254
00255 d_linear_approx_multiplicator = static_cast<double>(size())/(at(size()-1).get_hash()-at(0).get_hash());
00256 }
00257 bool found(const mpz_t &val) const
00258 {
00259 #ifdef VERBOSE_INFO
00260 static unsigned int cs = 0;
00261 #endif
00262
00263
00264 signed int L=0, R=size()-1;
00265 const mp_limb_t hash = mpz_getlimbn(val,0);
00266
00267 #if 1
00268
00269
00270 const signed int d = static_cast<signed int>(static_cast<double>(hash) * d_linear_approx_multiplicator);
00271
00272 const signed int dd = 127;
00273 __builtin_prefetch(&operator[](d),0,1);
00274 if (d-dd>L && at(d-dd).get_hash()<hash) L=d-dd;
00275 if (d+dd<R && at(d+dd).get_hash()>hash) R=d+dd;
00276
00277 #endif
00278
00279 while (R>=L)
00280 {
00281
00282 const signed int pos = (L+R)>>1;
00283 __builtin_prefetch(&operator[]((L+pos-1)>>1),0,0);
00284 __builtin_prefetch(&operator[]((R+pos+1)>>1),0,0);
00285 const signed int vgl = operator[](pos).compare(hash);
00286 #ifdef VERBOSE_INFO
00287 ++cs;
00288 #endif
00289 if (vgl==0)
00290 {
00291 #ifdef VERBOSE_INFO
00292 cout << cs << " comparisons performed so far" << endl;
00293 #endif
00294 return true;
00295 }
00296 if (vgl<0) L=pos+1; else R=pos-1;
00297 }
00298
00299
00300 return false;
00301 }
00302 };
00303
00304
00305 class phimahashvecs
00306 {
00307 private:
00308 static const mp_size_t hashlimb = 1;
00309 static const unsigned int lookup_bins = 0x1000;
00310 static const mp_limb_t limbmask = lookup_bins-1;
00311 phimavec lookup[lookup_bins];
00312 size_t myIntervalsize;
00313 const static unsigned int redundancy = 8;
00314 public:
00315 phimahashvecs() : myIntervalsize(0)
00316 {
00317 entry::iL=0; mpz_init_set_ui(entry::L,1);
00318 }
00319 ~phimahashvecs() { }
00320
00321 size_t size() const
00322 {
00323 size_t s = 0;
00324 for (unsigned int i=0; i<lookup_bins; ++i) s+=lookup[i].size();
00325 return s;
00326 }
00327 size_t max_size() const { return lookup[0].max_size(); }
00328
00329 void insert(const unsigned int i)
00330 {
00331 const entry e(i);
00332 const mp_limb_t h=mpz_getlimbn(e.get_mpz(i),hashlimb) & limbmask;
00333 lookup[h].push_back(e);
00334 }
00335 void prepare(const size_t tablesize)
00336 {
00337
00338
00339
00340 cout << "optimizing memory layout" << endl;
00341 entry::iL=0; mpz_set_ui(entry::L,1);
00342 size_t bin_size[lookup_bins] = { 0 };
00343 for (unsigned int i=0; i<tablesize; ++i)
00344 {
00345 const mp_limb_t h=mpz_getlimbn(entry::L,hashlimb) & limbmask;
00346 ++bin_size[h];
00347 mpz_mul(entry::L,entry::L,entry::Base); mpz_mod(entry::L,entry::L,n);
00348 }
00349 entry::iL=0; mpz_set_ui(entry::L,1);
00350 for (unsigned int i=0; i<lookup_bins; ++i)
00351 {
00352
00353 lookup[i].reserve(bin_size[i]);
00354 }
00355
00356
00357 cout << "inserting items" << endl;
00358 for (size_t i=0; i<tablesize; ++i) insert(i);
00359
00360 myIntervalsize = size()-redundancy;
00361
00362 #ifdef VERBOSE_INFO
00363 size_t s = 0;
00364 for (unsigned int i=0; i<lookup_bins; ++i)
00365 {
00366 lookup[i].sort();
00367 s+=lookup[i].size();
00368 cout << s << " items prepared.\r" << flush;
00369 }
00370 cout << endl;
00371 #else
00372 for (unsigned int i=0; i<lookup_bins; ++i) lookup[i].sort();
00373 #endif
00374
00375 }
00376
00377 size_t Intervalsize() const { return myIntervalsize; }
00378
00379 bool found(const mpz_t &val) const
00380 {
00381
00382 const mp_limb_t hash = mpz_getlimbn(val,hashlimb) & limbmask;
00383 if (!lookup[hash].found(val)) return false;
00384
00385
00386
00387
00388
00389
00390 bool retval=true;
00391 mpz_t x;
00392 mpz_init_set(x,val);
00393 for (unsigned int i=0; i<redundancy; ++i)
00394 {
00395 mpz_mul(x,x,entry::Base); mpz_mod(x,x,n);
00396 const mp_limb_t hash = mpz_getlimbn(x,hashlimb) & limbmask;
00397 retval=lookup[hash].found(x);
00398
00399 if (!retval) break;
00400 }
00401 mpz_clear(x);
00402 return retval;
00403 }
00404
00405 bool found(const mpz_t &val, unsigned int &the_index) const
00406 {
00407
00408 if (!found(val)) return false;
00409
00410
00411
00412
00413 mpz_t x;
00414 mpz_init(x);
00415 size_t d = Intervalsize()-1;
00416 {
00417 register unsigned int i = 0;
00418 while (d>>=1) ++i;
00419 d=1<<i;
00420 }
00421 cout << "candidate found; performing binary search for the_index" << endl;
00422 size_t hhh=0;
00423 while (d)
00424 {
00425 mpz_powm_ui(x,entry::Base,hhh+d,n);
00426 mpz_invert(x,x,n); mpz_mul(x,x,val); mpz_mod(x,x,n);
00427 if (found(x)) hhh+=d;
00428 d>>=1;
00429 }
00430 mpz_powm_ui(x,entry::Base,hhh,n);
00431 if (mpz_cmp(x,val)!=0)
00432 {
00433 cout << "binary search failed? try slowsearch..." << endl;
00434 mpz_t y; mpz_init(y); mpz_invert(y,entry::Base,n);
00435 while (hhh>0)
00436 {
00437 mpz_mul(x,x,y); mpz_mod(x,x,n); --hhh;
00438 if (mpz_cmp(x,val)==0) break;
00439 }
00440 mpz_clear(y);
00441 }
00442 the_index=hhh;
00443 cout << "the_index = " << the_index << endl;
00444 mpz_clear(x);
00445 return true;
00446 }
00447 };
00448
00449
00450 unsigned int entry::iL = 0;
00451 mpz_t entry::L, entry::Base;
00452
00453 extern unsigned long int allowed_memory_usage_KB(void);
00454
00455
00456 class lambda_delta
00457 {
00458 private:
00459 mpf_t SQRTN, DELTA;
00460 mpf_t fres, f1res;
00461 static const unsigned int bits = 2048;
00462 public:
00463
00464 static void Delta_by_ratio(mpz_t &Delta, const mpz_t n, const double ratio_p=1.0, const double ratio_q=1.0)
00465 {
00466 mpf_set_default_prec(bits);
00467 mpf_t x,y;
00468 mpf_init(x); mpf_init(y);
00469 mpf_set_d(x,ratio_p); mpf_set_d(y,ratio_q);
00470 mpf_div(x,x,y);
00471 mpf_sqrt(x,x);
00472 mpf_ui_div(y,1,x); mpf_add(x,x,y); mpf_sub_ui(x,x,2);
00473 mpf_set_z(y,n); mpf_sqrt(y,y); mpf_mul(x,x,y);
00474 mpz_set_f(Delta,x);
00475 }
00476
00477
00478 lambda_delta(const mpz_t n, const mpz_t delta)
00479 {
00480 mpf_set_default_prec(bits);
00481 mpf_init(SQRTN); mpf_set_z(SQRTN,n); mpf_sqrt(SQRTN,SQRTN);
00482 mpf_init(DELTA); mpf_set_z(DELTA,delta);
00483 mpf_init(fres); mpf_init(f1res);
00484 }
00485 ~lambda_delta()
00486 {
00487 mpf_clear(f1res); mpf_clear(fres);
00488 mpf_clear(DELTA); mpf_clear(SQRTN);
00489 }
00490
00491 const mpf_t& f(const mpf_t &x)
00492 {
00493 mpf_t h;
00494 mpf_init(h);
00495 mpf_sqrt(fres,x); mpf_ui_div(h,1,fres); mpf_add(fres,fres,h);
00496 mpf_sub_ui(fres,fres,2);
00497 mpf_mul(fres,fres,SQRTN);
00498 mpf_sub(fres,fres,DELTA);
00499 mpf_clear(h);
00500 return fres;
00501 }
00502 const mpf_t& f1(const mpf_t &x)
00503 {
00504 mpf_t h;
00505 mpf_init(h);
00506 mpf_sqrt(f1res,x); mpf_ui_div(f1res,1,f1res);
00507 mpf_pow_ui(h,f1res,3); mpf_sub(f1res,f1res,h);
00508 mpf_div_ui(f1res,f1res,2);
00509 mpf_mul(f1res,f1res,SQRTN);
00510 mpf_clear(h);
00511 return f1res;
00512 }
00513 #if 0
00514 void newton()
00515 {
00516 mpf_t x0,x1;
00517 mpf_init(x0);
00518 mpf_init_set_d(x1,1.1);
00519 do
00520 {
00521 mpf_set(x0,x1);
00522 mpf_div(x1,f(x0),f1(x0)); mpf_sub(x1,x0,x1);
00523
00524 } while (mpf_eq(x1,x0,bits-64)==0);
00525 cout << "newton: "; mpf_out_str(NULL,10,50,x1); cout << endl;
00526
00527
00528
00529
00530 mpf_clear(x1); mpf_clear(x0);
00531 }
00532 #endif
00533 };
00534
00535
00536 void phimat2()
00537 {
00538 cout << "Starting experimental Phimat factoring method." << endl;
00539 cout << "Warning: This method runs very long except for special constructed numbers" << endl;
00540 cout << "of the form N=p*q; p,q prime and q=p+x, x small compared to p." << endl;
00541
00542 mpz_init_set_ui(entry::Base,2);
00543
00544 mpz_t V,x;
00545 mpz_init(x); mpz_sqrt(x,n); mpz_mul_ui(x,x,2);
00546
00547 unsigned int step=2;
00548 mpz_t Delta,initial_Delta,stop_Delta;
00549 mpz_init_set_ui(Delta,0);
00550 mpz_init(stop_Delta);
00551
00552
00553
00554
00555 lambda_delta::Delta_by_ratio(Delta,n,1.0,1.0);
00556 lambda_delta::Delta_by_ratio(stop_Delta,n,2.0,1.0);
00557
00558 mpz_sub_ui(Delta,Delta,mpz_remainder_ui(Delta,3*32));
00559 mpz_init_set(initial_Delta,Delta);
00560
00561 {
00562 unsigned int r = mpz_remainder_ui(n,32);
00563 unsigned int disp=0;
00564 if (r%4==1) { disp=2; step=4; }
00565 else if (r%8==3) { disp=4; step=8; }
00566 else if (r%8==7) { disp=0; step=8; }
00567 else { cerr << "unknown state " << r << endl; exit(1); }
00568 if (mpz_remainder_ui(n,6)==5) { step*=3; disp*=3; }
00569 cout << "phimat multiplier is " << step << endl;
00570 step/=2;
00571
00572 r=mpz_remainder_ui(x,step);
00573 mpz_sub_ui(Delta,Delta,r); mpz_add_ui(Delta,Delta,disp);
00574 mpz_sub_ui(x,x,r); mpz_add_ui(x,x,disp);
00575 }
00576
00577 mpz_init_set(V,n); mpz_add_ui(V,V,1); mpz_sub(V,V,x);
00578 mpz_powm(V,entry::Base,V,n);
00579 mpz_powm_ui(entry::Base,entry::Base,step,n);
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593 phimahashvecs entries;
00594
00595 {
00596
00597 const unsigned int t1 = entries.max_size();
00598 unsigned int t2 = static_cast<size_t>((allowed_memory_usage_KB()/sizeof(entry)));
00599 if (t2>65536) t2-=32768;
00600 t2*=1024;
00601 const unsigned int tablesize = MIN(t1,t2);
00602 cout << "Creating table of " << tablesize << " items." << endl;
00603 cout << "This may take a while..." << endl;
00604 entries.prepare(tablesize);
00605 cout << "Okay, items are prepared. Now searching for factors..." << endl;
00606 }
00607
00608
00609 {
00610
00611 mpz_t x;
00612 mpz_init(x);
00613 mpz_div_ui(x,initial_Delta,step);
00614 mpz_powm(x,entry::Base,x,n);
00615 mpz_invert(x,x,n);
00616 mpz_mod(x,x,n);
00617 mpz_mul(V,V,x); mpz_mod(V,V,n);
00618 mpz_clear(x);
00619 }
00620
00621 mpz_t PowIntervalStep;
00622 mpz_init_set(PowIntervalStep,entry::Base);
00623 mpz_powm_ui(PowIntervalStep,PowIntervalStep,entries.Intervalsize(),n);
00624 mpz_invert(PowIntervalStep,PowIntervalStep,n);
00625 mpz_mod(PowIntervalStep,PowIntervalStep,n);
00626
00627 mpz_t TableStep;
00628 mpz_init_set_ui(TableStep,entries.Intervalsize()); mpz_mul_ui(TableStep,TableStep,step);
00629
00630 for (unsigned int i=0; ; ++i)
00631 {
00632 unsigned int index;
00633 if (entries.found(V,index))
00634 {
00635 mpz_t x,y,z,myDelta;
00636 mpz_init(x); mpz_init(y); mpz_init(z); mpz_init_set(myDelta,Delta);
00637 mpz_set_ui(x,index); mpz_mul_ui(x,x,step); mpz_add(myDelta,myDelta,x);
00638 cout << "Found a candidate at Delta=" << myDelta << endl;
00639 mpz_sqrt(x,n); mpz_mul_ui(x,x,2); mpz_add(x,x,myDelta);
00640 mpz_mul(y,x,x); mpz_mul_ui(z,n,4); mpz_sub(y,y,z);
00641 mpz_sqrt(y,y); mpz_add(y,y,x);
00642 mpz_gcd(z,y,n); mpz_mod(z,z,n);
00643 if (mpz_cmp_ui(z,1)>0)
00644 {
00645 cout << "looks good :-)" << endl;
00646 mpz_set(Delta,myDelta);
00647
00648 while (mpz_cmp_ui(n,1)!=0)
00649 {
00650 if (mpz_probab_prime_p(z,probab_prime_checks))
00651 {
00652 cout << z << " is factor." << endl;
00653 std::ostringstream comment;
00654 comment << " [phimat]";
00655 Factorization_to_file << MAL(z,comment) << flush;
00656 }
00657 else
00658 {
00659 cout << z << " is a composite factor." << endl;
00660 if (Potenztest(z)) Factorization_to_file << " [phimat]" << flush;
00661 else
00662 {
00663 std::ostringstream comment;
00664 comment << " [phimat] [composite]";
00665 Factorization_to_file << MAL(z,comment) << flush;
00666 }
00667 }
00668 mpz_divexact(n,n,z);
00669 mpz_set(z,n);
00670 }
00671 }
00672 mpz_clear(myDelta); mpz_clear(z); mpz_clear(y); mpz_clear(x);
00673 if (mpz_cmp_ui(n,1)==0) break;
00674 }
00675 mpz_add(Delta,Delta,TableStep);
00676 mpz_mul(V,V,PowIntervalStep); mpz_mod(V,V,n);
00677 if ((i&0x3ffff)==0)
00678 {
00679 if ((i&0x1ffffff)==0)
00680 {
00681 mpz_t x,y,z;
00682 mpz_init(x); mpz_init(y); mpz_init(z);
00683 mpz_sqrt(x,n); mpz_mul_ui(x,x,2); mpz_add(x,x,Delta);
00684 mpz_mul(y,x,x); mpz_mul_ui(z,n,4); mpz_sub(y,y,z);
00685 mpz_sqrt(y,y); mpz_add(y,y,x);
00686 mpz_div_ui(y,y,2);
00687 mpz_div(x,n,y);
00688 cout << "new bound p<" << x << endl;
00689 mpz_clear(z); mpz_clear(y); mpz_clear(x);
00690
00691 if (mpz_cmp(Delta,stop_Delta)>0) break;
00692 }
00693 cout << "Delta=" << Delta << '\r' << flush;
00694 }
00695 }
00696
00697
00698
00699 mpz_div_ui(Delta,Delta,2);
00700 cout << "Fermat Delta would be " << Delta << endl;
00701
00702 mpz_clear(TableStep); mpz_clear(PowIntervalStep);
00703 mpz_clear(initial_Delta); mpz_clear(stop_Delta); mpz_clear(Delta);
00704 mpz_clear(x); mpz_clear(V);
00705
00706 mpz_clear(entry::Base);
00707 }
00708
00709
00710
00711 void phimat(mpz_t n)
00712 {
00713 mpz_t x,y;
00714 mpz_init(x); mpz_init(y);
00715
00716 mpz_mul_ui(x,n,4); mpz_sqrt(x,x);
00717 mpz_add_ui(y,n,1); mpz_sub(y,y,x);
00718 mpz_set_ui(x,2); mpz_powm(x,x,y,n);
00719
00720 cout << "trying phimat..." << x << endl;
00721
00722
00723 unsigned long int z=0;
00724 while (z<1000000000)
00725 {
00726 int p=mpz_scan1(x,0); z+=p;
00727 mpz_tdiv_q_2exp(x,x,p);
00728
00729 if (mpz_cmp_ui(x,1)==0) break;
00730 mpz_add(x,x,n);
00731 }
00732
00733 cout << z << ":" << x << endl;
00734
00735 if (mpz_cmp_ui(x,1)==0)
00736 {
00737 cout << "x=1 ... " << endl;
00738 mpz_mul_ui(x,n,4); mpz_sqrt(x,x); mpz_add_ui(x,x,z);
00739 mpz_mul(y,x,x);
00740 mpz_sub(y,y,n); mpz_sub(y,y,n); mpz_sub(y,y,n); mpz_sub(y,y,n);
00741 mpz_sqrt(y,y);
00742 mpz_add(y,x,y); mpz_div_ui(y,y,2);
00743 mpz_div(x,n,y);
00744 mpz_mul(x,x,y);
00745 cout << x << endl;
00746 if (mpz_cmp(x,n)==0)
00747 {
00748 mpz_div(x,n,y);
00749 if (mpz_probab_prime_p(x,probab_prime_checks))
00750 {
00751 cout << x << " is factor." << endl;
00752 Factorization_to_file << MAL(x) << flush;
00753 }
00754 else
00755 {
00756 cout << x << " is a composite factor." << endl;
00757 Factorization_to_file << MAL(x) << " [composite]" << flush;
00758 }
00759 if (mpz_probab_prime_p(y,probab_prime_checks))
00760 {
00761 cout << y << " is factor." << endl;
00762 Factorization_to_file << MAL(y) << flush;
00763 }
00764 else
00765 {
00766 cout << y << " is a composite factor." << endl;
00767 Factorization_to_file << MAL(y) << " [composite]" << flush;
00768 }
00769 mpz_set_ui(n,1);
00770 }
00771 }
00772
00773 mpz_clear(x); mpz_clear(y);
00774 }