00001
00011 #include "utils.H"
00012 #include "mpz_wrapper.H"
00013 #include "modulo.H"
00014 #include <cmath>
00015
00016
00017 #define BEWERTUNG_MIT_POTENZEN
00018
00019
00020
00031 void determine_best_MPQS_Multiplier(const mpz_t n, mpz_t kN, int &new_MPQS_Multiplier)
00032 {
00033
00034
00035
00036
00037
00038
00039
00040
00041 using numtheory::is_prime;
00042 using namespace my_mpz_wrapper;
00043
00044
00045 const int P=2;
00046
00047 int bound_k = 1000000;
00048
00049
00050 const int FB_SIM_Size = 100;
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #ifdef VERBOSE_INFO
00061 cout << "Determining a multiplier for MPQS" << endl;
00062 #endif
00063
00064 if (mpz_sizeinbase(n,10)<50)
00065 bound_k=100;
00066
00067
00068
00069 double optimal_w, good_w;
00070 int p;
00071
00072 p=2; optimal_w= -2*log(2);
00073 while (p<P)
00074 {
00075 while (!is_prime(p)) p++;
00076 #ifdef BEWERTUNG_MIT_POTENZEN
00077 optimal_w -= 2*log(p)/(p-1);
00078 #else
00079 optimal_w -= 2*log(p)/p;
00080 #endif
00081 p++;
00082 }
00083
00084
00085 for (int z=0; z<FB_SIM_Size; p++)
00086 {
00087 while (!is_prime(p)) p++;
00088 z++;
00089 #ifdef BEWERTUNG_MIT_POTENZEN
00090 optimal_w -= 2*log(p)/(p-1);
00091 #else
00092 optimal_w -= 2*log(p)/p;
00093 #endif
00094 }
00095
00096
00097 good_w=0.85*optimal_w;
00098
00099 #ifdef VERBOSE_INFO
00100 cout << "theoretically optimal valuation: " << std::setprecision(10) << optimal_w << endl;
00101 cout << "theoretically good valuation : " << good_w << endl;
00102 cout << "Starting simulation of MPQS multipliers..." << endl;
00103 #endif
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 struct tFeldeintrag
00114 {
00115 double w; int k;
00116 inline tFeldeintrag() : w(0.0), k(0) { }
00117 inline ~tFeldeintrag() { }
00118 };
00119 const short int sort_bis = 5;
00120 tFeldeintrag Feld[sort_bis];
00121
00122
00123
00124 double best_w = 1e20;
00125 double akt_w;
00126 int best_k = 1;
00127 int k=1;
00128 int z=0;
00129 mpz_t x; mpz_init(x);
00130
00131 while (k<=bound_k)
00132 {
00133 mpz_mul_ui(kN,n,k);
00134
00135
00136 if (mpz_remainder_ui(kN,8)!=1) goto next;
00137
00138 akt_w=-2*log(2);
00139
00140 p=2; z=1;
00141 while (p<P)
00142 {
00143 do p++; while(!is_prime(p));
00144 mpz_set_ui(x,p); if (mpz_legendre(kN,x)==-1) goto next;
00145 z++;
00146
00147
00148 #ifdef BEWERTUNG_MIT_POTENZEN
00149 #ifdef BEWERTUNG_MIT_DIRTY_SIEVING
00150 if (z<SieveControl::FBLowestStartIndex)
00151 akt_w -= (k%p!=0)? 2*log(p)/(p-1) - 1.75*log(p)/p: 0.1*log(p)/p;
00152 else
00153 akt_w -= (k%p!=0)? 2*log(p)/(p-1) : 1*log(p)/p;
00154 #else // ohne BEWERTUNG_MIT_DIRTY_SIEVING
00155 akt_w -= (k%p!=0)? 2*log(p)/(p-1) : 1*log(p)/p;
00156 #endif
00157 #else
00158 #ifdef BEWERTUNG_MIT_DIRTY_SIEVING
00159 if (z<SieveControl::FBLowestStartIndex)
00160 akt_w -= 0.5*((k%p!=0)? 2*log(p)/p : log(p)/p);
00161 else
00162 akt_w -= (k%p!=0)? 2*log(p)/p : 1*log(p)/p;
00163 #else // ohne BEWERTUNG_MIT_DIRTY_SIEVING
00164 akt_w -= (k%p!=0)? 2*log(p)/p : 1*log(p)/p;
00165 #endif
00166 #endif
00167
00168 }
00169
00170
00171 {
00172 for ( ; z<FB_SIM_Size; z++)
00173 {
00174 do
00175 {
00176 do p++; while(!is_prime(p));
00177 mpz_set_ui(x,p);
00178 }
00179 while (mpz_legendre(kN,x)==-1);
00180
00181
00182
00183 #ifdef BEWERTUNG_MIT_POTENZEN
00184 #ifdef BEWERTUNG_MIT_DIRTY_SIEVING
00185 if (z<SieveControl::FBLowestStartIndex)
00186 akt_w -= (k%p!=0)? 2*log(p)/(p-1) - 1.75*log(p)/p : 0.1*log(p)/p;
00187 else
00188 akt_w -= (k%p!=0)? 2*log(p)/(p-1) : 1*log(p)/p;
00189 #else // ohne BEWERTUNG_MIT_DIRTY_SIEVING
00190 akt_w -= (k%p!=0)? 2*log(p)/(p-1) : 1*log(p)/p;
00191 #endif
00192 #else
00193 #ifdef BEWERTUNG_MIT_DIRTY_SIEVING
00194 if (z<SieveControl::FBLowestStartIndex)
00195 akt_w -= 0.5*((k%p!=0)? 2*log(p)/p : log(p)/p);
00196 else
00197 akt_w -= (k%p!=0)? 2*log(p)/p : 1*log(p)/p;
00198 #else // ohne BEWERTUNG_MIT_DIRTY_SIEVING
00199 akt_w -= (k%p!=0)? 2*log(p)/p : 1*log(p)/p;
00200 #endif
00201 #endif
00202
00203 }
00204
00205 akt_w += 0.5*log(k);
00206
00207
00208
00209
00210 {
00211
00212 signed short int i=sort_bis-1;
00213 if (akt_w<Feld[i].w)
00214 {
00215 while (i>0 && akt_w<Feld[i-1].w) { Feld[i]=Feld[i-1]; --i; }
00216 Feld[i].w=akt_w; Feld[i].k=k;
00217 }
00218 }
00219
00220 if (akt_w<best_w)
00221 {
00222 #ifdef VERBOSE
00223 cout << "best multiplier so far: " << k
00224 << " valuation: " << akt_w << endl;
00225 #endif
00226 best_w=akt_w; best_k=k;
00227 int computed_bound_k;
00228 if (akt_w>good_w)
00229 computed_bound_k = static_cast<int>(ceil(exp(2*(akt_w-good_w))));
00230 else computed_bound_k = 0;
00231 if (computed_bound_k<bound_k) bound_k=computed_bound_k;
00232 #ifdef VERBOSE
00233 cout << "New (practical) bound: " << bound_k
00234 << " (theoretical bound: " << computed_bound_k << ")" << endl;
00235 #endif
00236 }
00237 }
00238
00239
00240 next:
00241 #if 0
00242 do k++; while(!is_prime(k));
00243 #else
00244
00245 k++;
00246 {
00247 int square=4, i=5;
00248 while (square<=k)
00249 {
00250 if (k%square==0) goto next;
00251 square+=i; i+=2;
00252 }
00253
00254 }
00255 #endif
00256 }
00257
00258 #ifdef VERBOSE_INFO
00259 cout << endl;
00260 cout << "The " << sort_bis << " best MPQS multipliers are" << endl;
00261 for (short int i=0; i<sort_bis; i++)
00262 cout << i+1 << ". " << Feld[i].k << " with valuation " << Feld[i].w << endl;
00263 cout << endl;
00264 #endif
00265
00266 #if 0
00267
00268 cout << "Please input a multiplier: ";
00269 cin >> best_k;
00270 #endif
00271
00272 new_MPQS_Multiplier=best_k;
00273 #ifdef VERBOSE_NOTICE
00274 cout << "MPQS multiplier set to " << best_k << endl;
00275 #endif
00276 mpz_mul_ui(kN,n,best_k);
00277 mpz_clear(x);
00278 }