00001
00006 #include "StaticFactorbase.H"
00007 #include "Sieving.H"
00008 #include <cmath>
00009
00010 StaticFactorbaseSettings::FBsizetype StaticFactorbaseSettings::Size_StaticFactorbase = 5000;
00011
00012
00013
00014
00015
00016
00017 int StaticFactorbaseSettings::PrimeNumbers[StaticFactorbaseSettings::MaxSize] __attribute__ ((aligned (64)));
00018 int StaticFactorbaseSettings::PrimeNumberReciprocals[StaticFactorbaseSettings::MaxSize] __attribute__ ((aligned (64)));
00019 float StaticFactorbaseSettings::PrimeNumberFloatReciprocals[StaticFactorbaseSettings::MaxSize] __attribute__ ((aligned (64)));
00020 int StaticFactorbaseSettings::biggest_Prime_in_Factorbase = 0;
00021
00022
00023 int StaticFactorbase::NumberOf_more_PrimePowers = 0;
00024 int StaticFactorbase::FB_maxQuadrate = 0;
00025 int StaticFactorbase::PrimePowers[StaticFactorbase::max_additional_Powers];
00026 int StaticFactorbase::PrimePowerReciprocals[StaticFactorbase::max_additional_Powers];
00027 int StaticFactorbase::SQRT_kN_of_PrimeNumbers[MaxSize];
00028 int StaticFactorbase::SQRT_kN_of_PrimePowers[StaticFactorbase::max_additional_Powers];
00029 int StaticFactorbase::SQRT_kN_of_PrimeSquares[StaticFactorbase::MaxSize];
00030
00031
00032
00046 int LogicalSieveSize = 1000000;
00047
00048
00049 int MPQS_Multiplier;
00050
00051 using std::cin;
00052 using std::cout;
00053 using std::cerr;
00054 using std::endl;
00055 using std::flush;
00056 using std::sqrt;
00057 using namespace numtheory;
00058
00059 int check_SQRT_kN_mod_PrimeNumber(const int Primzahl)
00060 {
00061
00062
00063 int w1 = SQRT_kN_mod_PrimeNumber(Primzahl);
00064 if (w1>Primzahl/2) w1=Primzahl-w1;
00065
00066 mpz_t x;
00067 mpz_init_set_ui(x,w1); mpz_mul(x,x,x); mpz_sub(x,x,kN);
00068 if (mpz_mod_ui(x,x,Primzahl)!=0)
00069 {
00070 MARK;
00071 cerr << "wrong result! " << w1 << " mod " << Primzahl << endl;
00072 exit(1);
00073 }
00074 mpz_clear(x);
00075 return w1;
00076 }
00077
00078
00079 #include "mpqsMultiplier.cc"
00080
00081
00082
00083
00084 void StaticFactorbase::compute_StaticFactorbase()
00085 {
00086 #if defined(ASM_MMX) || defined(ASM_3DNOW) || defined(ASM_ATHLON) || defined(ASM_SSE) || defined(ASM_SSE2) || defined(ASM_X86_64)
00087
00088 if ( LogicalSieveSize>(1<<23) || (StaticFactorbase::Size()&3) )
00089 {
00090 MARK;
00091 cerr << "Sorry! Processor specific constraints not met." << endl;
00092 cerr << "For using AMD-3DNow! or SSE optimized version we need:" << endl;
00093 cerr << "Constraint 1 (SIMD): (Size_StaticFactorbase&3)==0" << endl;
00094 cerr << "Constraint 2 (float precision): LogicalSieveSize<=(1<<23) [=8388608]" << endl;
00095 cerr << "Please edit ConfigFile according to these constraints" << endl;
00096 cerr << "OR use a version without these optimizations." << endl;
00097 exit(1);
00098 }
00099 #endif
00100
00101 #ifdef VERBOSE_NOTICE
00102 cout << "Calculating static factorbase." << endl;
00103 #endif
00104 PrimeNumbers[0]=-1;
00105 SieveControl::set_logVal_for_Primenumber(0,0,0);
00106
00107 int Primzahl=2;
00108
00109
00110 PrimeNumbers[1]=2;
00111 SieveControl::set_logVal_for_Primenumber(1,static_cast<TSieveElement>(ceil(log_SieveEntryMultiplier*log(Primzahl))),static_cast<TSieveElement>(ceil(log_SieveEntryMultiplier*log(Primzahl))));
00112
00113 Primzahl=1;
00114 mpz_t x,y,wuqu;
00115 mpz_init(x); mpz_init(y); mpz_init(wuqu);
00116 for (int Primzahl_nr=2; Primzahl_nr<StaticFactorbase::Size(); Primzahl_nr++)
00117 {
00118 do
00119 {
00120 do Primzahl+=2; while(!is_prime(Primzahl));
00121 mpz_set_ui(x,Primzahl);
00122 }
00123 while (mpz_legendre(kN,x)<0);
00124
00125 PrimeNumbers[Primzahl_nr]=Primzahl;
00126 PrimeNumberReciprocals[Primzahl_nr]=reciprocal(Primzahl);
00127 PrimeNumberFloatReciprocals[Primzahl_nr]=static_cast<float>(1.0)/static_cast<float>(Primzahl);
00128
00129
00130 SieveControl::set_logVal_for_Primenumber(Primzahl_nr,
00131 static_cast<TSieveElement>(ceil(log_SieveEntryMultiplier*log(Primzahl))),
00132 static_cast<TSieveElement>(ceil(log_SieveEntryMultiplier*log(Primzahl)*SieveControl::DirtyFactor(Primzahl_nr))));
00133
00134
00135 SQRT_kN_of_PrimeNumbers[Primzahl_nr]=SQRT_kN_mod_PrimeNumber(Primzahl);
00136
00137
00138 if ( squaremod(SQRT_kN_of_PrimeNumbers[Primzahl_nr],Primzahl) != mpz_remainder_ui(kN,Primzahl) )
00139 {
00140 cerr << "square root not correct!" << endl;
00141 cerr << SQRT_kN_of_PrimeNumbers[Primzahl_nr] << "^2 <> "
00142 << mpz_remainder_ui(kN,Primzahl) << " (mod " << Primzahl << ")" << endl;
00143 exit(1);
00144 }
00145
00146
00147 if ( Primzahl < sqrt(std::numeric_limits<int>::max()) && MPQS_Multiplier%Primzahl!=0 )
00148 {
00149
00150 const unsigned int P = Primzahl*Primzahl;
00151 const unsigned int Wu = SQRT_kN_of_PrimeNumbers[Primzahl_nr];
00152 unsigned int iy = invmod(2*Wu,P);
00153 unsigned int ix = mpz_remainder_ui(kN,P);
00154
00155 unsigned int wuq=Wu*Wu;
00156 if (ix>=wuq) ix-=wuq; else ix=ix-wuq+P;
00157 ix=mulmod(ix,iy,P)+Wu;
00158 wuq = (ix<P) ? ix : ix-P;
00159
00160 #if 1 || defined(DEBUG)
00161 if (mulmod(wuq,wuq,P)!=mpz_remainder_ui(kN,P))
00162 {
00163 cerr << "PQ-root incorrect!" << endl;
00164 cerr << "Primzahl=" << PrimeNumbers[Primzahl_nr] << endl;
00165 cerr << "kN= " << kN << endl;
00166 cerr << mulmod(Wu,Wu,P) << " != " << mpz_remainder_ui(kN,P) << endl;
00167 exit(1);
00168 }
00169 #endif
00170 SQRT_kN_of_PrimeSquares[Primzahl_nr]=wuq;
00171 } else SQRT_kN_of_PrimeSquares[Primzahl_nr]=-1;
00172
00173
00174 const int Threshold = LogicalSieveSize < std::numeric_limits<int>::max()/8 ? 8*LogicalSieveSize/Primzahl : LogicalSieveSize/Primzahl;
00175 if (Primzahl<=Threshold && Primzahl>2 && mpz_remainder_ui(kN,Primzahl)!=0)
00176
00177
00178 {
00179 FB_maxQuadrate=Primzahl_nr;
00180
00181
00182
00183 int P_Potenz = Primzahl*Primzahl;
00184 int Wu = SQRT_kN_of_PrimeNumbers[Primzahl_nr];
00185
00186 double Weight = Primzahl_nr<SieveControl::FBLowestStartIndex ? 2.0 : 1.0;
00187
00188
00189
00190
00191
00192
00193
00194
00195 for (int pot=2; ;pot++)
00196 {
00197
00198
00199 mpz_set_ui(y,2*Wu); mpz_set_ui(x,P_Potenz);
00200 if (mpz_invert(y,y,x)==0)
00201 {
00202 cerr << "PPot-root for " << Primzahl << ": inverse doesn't exist!" << endl;
00203 break;
00204 }
00205
00206 if (NumberOf_more_PrimePowers>=StaticFactorbase::max_additional_Powers)
00207 {
00208 static char weitermachen = 'n';
00209 if (weitermachen!='y')
00210 {
00211 cerr << "Overflow for " << Primzahl << "^" << pot << endl;
00212 cerr << "Reserved memory for storing prime powers is too small..." << endl;
00213 cerr << "sieving will be less efficient..." << endl;
00214 cerr << "(You may increase \"StaticFactorbase::max_additional_Powers\" and recompile the program.)" << endl;
00215 cerr << "continue anyway? (y/n) " << flush;
00216 cin >> weitermachen;
00217 if (weitermachen=='n') exit(1);
00218 }
00219 break;
00220 }
00221
00222 mpz_mod_ui(x,kN,P_Potenz); mpz_set_ui(wuqu,Wu); mpz_mul_ui(wuqu,wuqu,Wu); mpz_sub(x,x,wuqu);
00223 mpz_mul(x,x,y); mpz_add_ui(x,x,Wu); mpz_mod_ui(x,x,P_Potenz);
00224 Wu = mpz_get_ui(x); if (Wu>P_Potenz-Wu) Wu=P_Potenz-Wu;
00225
00226
00227
00228 mpz_set_ui(x,Wu); mpz_mul(x,x,x); mpz_sub(x,kN,x);
00229 if (mpz_mod_ui(x,x,P_Potenz)!=0)
00230 {
00231 cerr << "PPot-root incorrect!" << endl;
00232 cerr << "Primzahl=" << PrimeNumbers[Primzahl_nr] << " Nr. " << Primzahl_nr << endl;
00233 cerr << "kN= " << kN << endl;
00234 cerr << "SQRT(kN) mod p=" << SQRT_kN_of_PrimeNumbers[Primzahl_nr] << endl;
00235 cerr << "SQRT(kN) mod p^i=" << SQRT_kN_of_PrimePowers[NumberOf_more_PrimePowers] << endl;
00236 cerr << "but we got a wrong value: " << x << endl;
00237 exit(1);
00238 }
00239
00240
00241
00242 if (P_Potenz>Threshold) Weight+=4.0/Primzahl;
00243
00244 #if 1
00245
00246
00247
00248
00249
00250
00251 if ( P_Potenz<250 && mpz_sizeinbase(kN,10)<70 ) Weight+=1.0;
00252 else
00253 #endif
00254 {
00255 PrimePowers[NumberOf_more_PrimePowers]=P_Potenz;
00256 PrimePowerReciprocals[NumberOf_more_PrimePowers]=numtheory::reciprocal(P_Potenz);
00257 SQRT_kN_of_PrimePowers[NumberOf_more_PrimePowers]=Wu;
00258
00259 SieveControl::set_logVal_for_Primepower(NumberOf_more_PrimePowers,
00260 static_cast<TSieveElement>(ceil(log_SieveEntryMultiplier*Weight*log(Primzahl))));
00261 Weight=1.0;
00262 ++NumberOf_more_PrimePowers;
00263 }
00264
00265 if (P_Potenz>Threshold) break;
00266 P_Potenz*=Primzahl;
00267 }
00268 }
00269 }
00270 mpz_clear(x); mpz_clear(y); mpz_clear(wuqu);
00271
00272 biggest_Prime_in_Factorbase=Primzahl;
00273 #ifdef VERBOSE_INFO
00274 cout << "prime numbers in static factorbase have been computed." << endl;
00275 if (Primzahl>=PhysicalSieveSize)
00276 cout << "Remark: Some members of the static factorbase are bigger than the sieve size!" << endl;
00277
00278 cout << "The first 20 members of the static factorbase are" << endl;
00279 for (int i=0; i<20; i++) cout << StaticFactorbase::PrimeNumbers[i] << " "; cout << endl;
00280 cout << "Biggest prime in static factorbase: " << StaticFactorbase::BiggestPrime() << endl;
00281 cout << "#squares (of primes) in FB: " << StaticFactorbase::FB_maxQuadrate << endl;
00282 cout << "#powers (of primes) in FB: " << StaticFactorbase::NumberOf_more_PrimePowers << endl;
00283 #endif
00284 }