DynamicRelations.H

Go to the documentation of this file.
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 }

Generated on Wed Nov 7 23:29:25 2007 for Qsieve by  doxygen 1.5.4