00001 00006 /* About Dynamic-Factors/Special-Factors: 00007 00008 This program uses a modified Multi-Large-Prime-Variant: 00009 Dynamic-Factors are like Single-Large-Primes, except that we are 00010 sieving with these factors as they get detected. 00011 00012 Special-Factors are composite rests (esp. Double-Large-Primes variant). 00013 On the one hand, we try to split Special-Factors by new Dynamic-Factors 00014 to get other Dynamic-Factors. On the other hand a cycle search is 00015 performed occasionally to gain relations. 00016 00017 In future implementations the cycle search may be extended to hyper edges 00018 as well (for multi-Large-Primes). [But most probably this approach would 00019 end up in using a standard method for solving a linear system of equations.] 00020 */ 00021 00022 00023 #ifdef IS_SERVER 00024 #include "Semaphore.H" 00025 #endif 00026 00027 extern std::string DynamicRelationsFile; 00028 00029 class DynamicRelations 00030 { 00031 // this class encapsulates access to the functions 00032 // which are specific for handling dynamic relations 00033 // (SLP relations = SingleLargePrime relations; 00034 // synonymic: dynamic factor relations, dynamic relations) 00035 00036 protected: 00037 // provide streams to store SLP relations 00038 static filebuf FileBuffer; 00039 static ostream DynamicRelations_to_file; 00040 static istream DynamicRelations_from_file; 00041 00042 class IstreamPool 00043 { 00044 private: 00045 static const int PoolSize=6; 00046 #ifdef IS_SERVER 00047 static CCriticalSection::Mutex PoolMutex; 00048 static CSemaphore Semaphore; // #resources to be protected by a semaphore 00049 #endif 00050 typedef istream* Pistream; 00051 static Pistream Pistream_slots[PoolSize]; // = { NULL }; 00052 static bool slot_occupied[PoolSize]; // = { false }; 00053 public: 00054 static istream* acquire_istream() 00055 { 00056 { 00057 #ifdef IS_SERVER 00058 if (!Semaphore.trywait()) 00059 { 00060 cout << "IStreamPool: thread " << pthread_self() << " waiting for free slot!" << endl; 00061 Semaphore.wait(); 00062 cout << "IStreamPool: thread " << pthread_self() << " got free slot!" << endl; 00063 } 00064 CCriticalSection CriticalSection(PoolMutex); 00065 #endif 00066 for (int i=0; i<PoolSize; ++i) 00067 if (!slot_occupied[i]) 00068 { 00069 slot_occupied[i]=true; 00070 if (i>1) cout << "IStreamPool: using slot " << i << endl; 00071 if (!Pistream_slots[i]) Pistream_slots[i]=new ifstream(DynamicRelationsFile.c_str()); 00072 return Pistream_slots[i]; 00073 } 00074 } 00075 MARK; cout << "semaphore handling failed! all slots in use, wasn't able to acquire a slot." << endl; 00076 exit(1); // this is not supposed to happen!! 00077 } 00078 static void release_istream(std::istream *pis) 00079 { 00080 #ifdef IS_SERVER 00081 CCriticalSection CriticalSection(PoolMutex); 00082 #endif 00083 for (int i=0; i<PoolSize; ++i) 00084 if (pis==Pistream_slots[i]) 00085 { 00086 slot_occupied[i]=false; 00087 #ifdef IS_SERVER 00088 Semaphore.post(); 00089 #endif 00090 return; 00091 } 00092 throw std::runtime_error("cannot release istream due to invalid pointer"); 00093 } 00094 static void cleanup() // free all allocated slots 00095 { 00096 for (int i=0; i<PoolSize; ++i) 00097 { 00098 delete Pistream_slots[i]; 00099 Pistream_slots[i]=NULL; 00100 slot_occupied[i]=false; 00101 } 00102 } 00103 }; 00104 00105 public: 00106 static void Load(); 00107 static void cleanup_files() 00108 { 00109 IstreamPool::cleanup(); // free allocated slots 00110 FileBuffer.close(); 00111 remove(DynamicRelationsFile.c_str()); 00112 } 00113 00114 friend int main(const int argc, const char* const argv[]); 00115 friend class CRelation; 00116 friend class CRelation::ProvideDynamicRelationsStream; 00117 }; 00118 00119 #include "DynamicFactorRelations.H" 00120 00121 #ifdef IS_SERVER 00122 #include "Cprocess_clients.H" 00123 class CServerDynamicFactorRelations : protected TDynamicFactorRelations 00124 { 00125 private: 00126 mutable CMutex monitor_mutex, SLP_mutex; 00127 vector<int> DynamicFactorList; 00128 int size_active_SLP, size_passive_SLP; 00129 00130 public: 00131 inline void insert(const TDynamicFactorRelation& x) 00132 { 00133 SLP_mutex.lock(); 00134 const bool flag=TDynamicFactorRelations::insert(x).second; 00135 SLP_mutex.unlock(); 00136 if (flag) 00137 { 00138 if (!x.sieveable()) 00139 { 00140 // x is a Single Large Prime, but a passive one: not sieveable 00141 ++size_passive_SLP; 00142 return; 00143 } 00144 monitor_mutex.lock(); 00145 ++size_active_SLP; 00146 DynamicFactorList.push_back(x.factor); 00147 monitor_mutex.unlock(); 00148 } 00149 else 00150 { 00151 cerr << "CServerDynamicFactorRelations::insert duplicate (rejected)!" << endl; 00152 cerr << "This indicates an inconsistency in dynamic factor handling!" << endl; 00153 cerr << "(The inconsistency is harmless, but we abort nevertheless.)" << endl; 00154 cerr << "SLP: " << x.factor << endl; 00155 exit(1); 00156 } 00157 } 00158 inline int monitoredSize() // const /* const attribute could be dangerous due to multithreading!? */ 00159 { 00160 monitor_mutex.lock(); 00161 const int s=DynamicFactorList.size(); 00162 monitor_mutex.unlock(); 00163 return s; 00164 } 00165 inline int size_active() const { return size_active_SLP; } 00166 inline int size_passive() const { return size_passive_SLP; } 00167 inline size_t size() const { return TDynamicFactorRelations::size(); } 00168 inline const int operator[] (const int i) // const /* const attribute could be dangerous due to multithreading!? */ 00169 { 00170 monitor_mutex.lock(); 00171 const int x=DynamicFactorList[i]; 00172 monitor_mutex.unlock(); 00173 return x; 00174 } 00175 friend inline void fillin_streampos(TDynamicFactorRelation& x); 00176 friend bool is_dynamic_factor(const int number); 00177 friend bool is_dynamic_factor(TDynamicFactorRelation &FaRelSearch); 00178 friend class Cprocess_clients; 00179 }; 00180 CServerDynamicFactorRelations DynamicFactorRelations; 00181 #else 00182 TDynamicFactorRelations DynamicFactorRelations; 00183 #endif 00184 00185 00186 // *************** implementation part **************** 00187 00188 00189 inline void fillin_streampos(TDynamicFactorRelation &FaRelSearch) 00190 { 00191 #ifdef IS_SERVER 00192 CUnlockMutexAtDestruction CriticalSection(DynamicFactorRelations.SLP_mutex); 00193 DynamicFactorRelations.SLP_mutex.lock(); 00194 #endif 00195 const TDynamicFactorRelations::const_iterator p = DynamicFactorRelations.find(FaRelSearch); 00196 if (p==DynamicFactorRelations.end()) throw std::runtime_error("SLP not found in DynamicFactorRelations."); 00197 FaRelSearch.fpos=(*p).fpos; 00198 } 00199 00200 // not explicit inline, because it must be linked! 00201 bool is_dynamic_factor(const int number) 00202 { 00203 // returns, whether this number is already registered as a dynamic factor; 00204 // (dynamic factor -> prime number outside the static factorbase, also known as Single Large Prime) 00205 TDynamicFactorRelation relation; 00206 relation.factor = number; 00207 #ifdef IS_SERVER 00208 CUnlockMutexAtDestruction CriticalSection(DynamicFactorRelations.SLP_mutex); 00209 DynamicFactorRelations.SLP_mutex.lock(); 00210 #endif 00211 const TDynamicFactorRelations::const_iterator pos = DynamicFactorRelations.find(relation); // search dynamic factor 00212 return (pos != DynamicFactorRelations.end()); 00213 } 00214 00215 // not explicit inline, because it must be linked! 00216 bool is_dynamic_factor(TDynamicFactorRelation &FaRelSearch) 00217 { 00218 // returns, whether this number is already registered as a dynamic factor; 00219 // (dynamic factor -> prime number outside the static factorbase, also known as Single Large Prime) 00220 #ifdef IS_SERVER 00221 CUnlockMutexAtDestruction CriticalSection(DynamicFactorRelations.SLP_mutex); 00222 DynamicFactorRelations.SLP_mutex.lock(); 00223 #endif 00224 const TDynamicFactorRelations::const_iterator pos = DynamicFactorRelations.find(FaRelSearch); // search dynamic factor 00225 if (pos!=DynamicFactorRelations.end()) { FaRelSearch=*pos; return true; } 00226 return false; 00227 } 00228 00229 00230 filebuf DynamicRelations::FileBuffer; 00231 ostream DynamicRelations::DynamicRelations_to_file(&DynamicRelations::FileBuffer); 00232 istream DynamicRelations::DynamicRelations_from_file(&DynamicRelations::FileBuffer); 00233 00234 #ifdef IS_SERVER 00235 CCriticalSection::Mutex DynamicRelations::IstreamPool::PoolMutex; 00236 CSemaphore DynamicRelations::IstreamPool::Semaphore( DynamicRelations::IstreamPool::PoolSize); // #resources to be protected by a semaphore 00237 #endif 00238 DynamicRelations::IstreamPool::Pistream DynamicRelations::IstreamPool::Pistream_slots[DynamicRelations::IstreamPool::PoolSize] = { NULL }; 00239 bool DynamicRelations::IstreamPool::slot_occupied[DynamicRelations::IstreamPool::PoolSize] = { false }; 00240 00241 00242 void DynamicRelations::Load() 00243 { 00244 // read in Dynamic Relations 00245 #ifdef VERBOSE_NOTICE 00246 cout << "Reading dynamic relations from file..." << endl; 00247 #endif 00248 DynamicRelations_from_file.seekg(0,ios::beg); 00249 unsigned int line = 0; 00250 while (DynamicRelations_from_file.peek()=='G' || DynamicRelations_from_file.peek()=='U') 00251 { 00252 ++line; 00253 if (line%1000==0) cout << line << " relations processed.\r" << flush; 00254 if (DynamicRelations_from_file.peek()=='U') 00255 { 00256 #ifdef VERBOSE_WARN 00257 cerr << "skipping obsolete/invalid relation." << endl; 00258 #endif 00259 DynamicRelations_from_file.ignore(1000000,'\n'); 00260 continue; 00261 } 00262 TDynamicFactorRelation relation; 00263 relation.fpos = DynamicRelations_from_file.tellg(); 00264 string s; DynamicRelations_from_file >> s; 00265 DynamicRelations_from_file >> relation.factor; 00266 relation.append_for_sieving(); 00267 DynamicRelations_from_file.ignore(1000000,'\n'); 00268 DynamicFactorRelations.insert(relation); 00269 } 00270 cout << line << " relations processed." << endl; 00271 if (DynamicRelations_from_file.peek()!=EOF) 00272 { 00273 cerr << "Dynamic Relations: garbage detected. Giving up. Please validate." << endl; 00274 exit(1); 00275 } 00276 DynamicRelations_from_file.clear(); 00277 DynamicRelations_to_file.seekp(0, ios::end); // as a precaution... 00278 #ifdef VERBOSE_NOTICE 00279 cout << "Recover: " << DynamicFactorRelations.size() 00280 << " dynamic relations read." << endl; 00281 #endif 00282 }