qsieve.H

Go to the documentation of this file.
00001 #ifndef qsieve_header
00002 #define qsieve_header
00003 
00009 #include "qsieve-fwd.H"
00010 #include "utils.H"
00011 
00012 #ifdef CYGWIN_COMPAT
00013  extern "C"
00014  {
00015    #include <malloc.h>
00016  }
00017 #endif
00018 
00019 
00020 // use wrapped C++ stream I/O for mpz_t (multiple precision numbers)
00021 #include "mpz_wrapper.H"
00022 using namespace my_mpz_wrapper;
00023 
00024 #include "Tfactor.H"
00025 #include "TinyVector.H"
00026 typedef CTinyVector<StaticFactorbaseSettings::FBsizetype> CTinyFBsizetypeVector;
00027 
00028 #include "myBitString.H"
00029 
00030 using std::streampos;
00031 
00032 
00033 class CStreamEncoder
00034 {
00035  private:
00036   std::ostream &out;
00037   int prev_value; // previous value to write (but not yet written because of incomplete encoding)
00038  public:
00039   CStreamEncoder(std::ostream &out_) : out(out_), prev_value(0) { }
00040 
00042   void PutValue(const int w);
00043 };
00044 
00045 class CStreamDecoder
00046 {
00047  private:
00048   std::istream &in;
00049   int ahead_value; // already decoded value (will be returned on next read)
00050  public:
00051   CStreamDecoder(std::istream &in_) : in(in_), ahead_value(0) { }
00052 
00054   int GetValue();
00055 };
00056 
00057 class CProvideHelperVariables : private ForbidAssignment, protected StaticFactorbaseSettings
00058 {
00059  // it's not nice, but better than providing temporary mpz_t x,y
00060  // in the global namespace: threadsafe & restricted to the class
00061  // And we have no need to change the source code at 1000 places...
00062  protected:
00063   mpz_t x,y; // two helper variables
00064  public:
00065   CProvideHelperVariables() { mpz_init(x); mpz_init(y); }
00066   ~CProvideHelperVariables() { mpz_clear(x); mpz_clear(y); }
00067 };
00068 
00069 class CRelation : protected CProvideHelperVariables
00070 /* CRelation manages a relation of the form
00071        Delta^2 = product of factors (mod N)
00072    Our aim is to reduce the set of factors by combining relations.
00073    If two factors are equal, their product will be a square and can
00074    thus be eliminated (by taking the factor into Delta).
00075 
00076    If all factors are eliminated, the product on the right side will evaluate
00077    to 1. -> The system of equations is solved.
00078 
00079    Delta will be adjusted dynamically.
00080 */ 
00081 {
00082  public:
00083   static const int no_factor = -1;
00084   static const int dynamic_factor = -2;
00085   static const int special_factor = -3;
00086   int relevant_factor;
00087    // either the value is one out of { no_factor, dynamic_factor, special_factor }
00088    // or it is indexing a static factor (in the static factor base)
00089 
00090  private:
00091   CTinyFBsizetypeVector *Relation_sparse;
00092   myBitString *Relation_dense;
00093   mpz_t Delta; // Delta-value, that is the square-root part of the relation [a1*a2*a2 * (Delta)^2 = 1 mod n]
00094   std::istream *pDynamicRelations_from_file; // pointer to an istream, which provides us with correction factors (Korrekturfaktoren) for combine methods
00095 
00096  public:
00098   static void (*seek_emergency_handler)(istream &, const streampos);
00099 
00101   static void seek_emergency_default_handler(istream &, const streampos);
00102 
00105   class ProvideDynamicRelationsStream
00106    {
00107     public:
00108      typedef istream *Pistream; 
00109     private:
00110      Pistream &pistream;
00111      bool reuse;
00112     public:
00113      // constructor acquires an istream (usually for pDynamicRelations_from_file)
00114      ProvideDynamicRelationsStream(Pistream &pistream_); // acquire an istream for pistream_ (or reuse existing one)
00115      // destructor releases an istream (usually pDynamicRelations_from_file)
00116      ~ProvideDynamicRelationsStream(); // release istream (if it was acquired and not reused)
00117    }; 
00118 
00119  public:
00120   inline CRelation() // constructor
00121    : CProvideHelperVariables(), relevant_factor(no_factor),
00122      Relation_sparse(new CTinyFBsizetypeVector), Relation_dense(NULL),
00123      pDynamicRelations_from_file(NULL), pMulticombineData(NULL)
00124     {
00125       mpz_init_set_ui(Delta,1);
00126     }
00127 
00128   inline ~CRelation() // destructor
00129     {
00130 #if 0
00131       if (Relation_sparse) { delete Relation_sparse; Relation_sparse=NULL; }
00132       if (Relation_dense) { delete Relation_dense; Relation_dense=NULL; }
00133       mpz_clear(Delta);
00134       relevant_factor=no_factor;
00135 #else
00136       delete Relation_sparse;
00137       delete Relation_dense;
00138       mpz_clear(Delta);
00139 #endif
00140     }
00141   
00142   explicit CRelation(const signed int SievePos, short int HitCount=0); // constructor
00143   /* initialize "Deltas" with the value of Delta,
00144      fill in "Relationen" with the prime factors (containing odd exponents)
00145      of the reduced square.
00146    */
00147 
00148  public:
00149   int largest_factor_in_Relation() const
00150     /* (index) of biggest factor in relation */
00151     {
00152       if (Relation_sparse)
00153         if (Relation_sparse->empty()) return no_factor;
00154         else 
00155           {
00156             return Relation_sparse->last();
00157           }
00158       else 
00159         {
00160           return Relation_dense->last(1);
00161           /*
00162             int h = Relation_dense->last(1);
00163             if (h>=0) return h;
00164             else return no_factor;
00165           */
00166         }
00167     }
00168 
00169   int second_largest_factor_in_Relation() const
00170     /* (Index) of second-largest factor in relation */
00171     {
00172       if (Relation_sparse)
00173         if (Relation_sparse->size()>1)
00174           return (*Relation_sparse)[Relation_sparse->size()-2];
00175         else
00176           return no_factor;
00177       else // Relation ist dense
00178         {
00179           signed int vorletzter_Faktor=Relation_dense->last(1);
00180           if (vorletzter_Faktor>=0)
00181            return Relation_dense->prev(vorletzter_Faktor,1);
00182           else
00183            return no_factor;
00184         }
00185     }
00186 
00187   inline unsigned int SizeOfRelation() const
00188     {
00189       if (Relation_sparse) return Relation_sparse->size();
00190       else return Relation_dense->count(1);
00191     }
00192 
00197   inline void optisize(void)
00198     {
00199       // optimize (minimize) memory consumption of the relation
00200       // 1. if appropriate, implicitly convert dense<->sparse,
00201       // 2. minimize memory consumption inside the representation
00202 
00203       const int size=SizeOfRelation();
00204       const int largest=largest_factor_in_Relation();
00205       const int quotient = size ? largest/size : 0;
00206 
00207       if (Relation_sparse)
00208        {
00209          if (quotient<16-2) convert_Relation_to_dense();
00210          else Relation_sparse->optisize();
00211        }
00212       else // (Relation_dense)
00213        {
00214          if (quotient>16+2) convert_Relation_to_sparse();
00215          else Relation_dense->optisize();
00216        }
00217     }
00218   
00219   void convert_Relation_to_dense();
00220   void convert_Relation_to_sparse();
00221 
00223   inline bool empty() const
00224     {
00225       return (relevant_factor==no_factor);
00226       // if (Relation_sparse) return Relation_sparse->empty();
00227       // else return Relation_dense->last(1)==-1; 
00228     }
00229         
00230   void combine(const CRelation& GL2);
00232 
00233   // routines for speeding up multiple combine steps
00234  public:
00235 
00236   // TExponentArrayElement:
00237   // This type is used for multi-combine routines to collect the exponents
00238   // according to each element of the static factorbase.  It should be an
00239   // unsigned type which is able to store the maximum count of multi-combine
00240   // calls between a multi-combine init and a multi-combine exit call. 
00241   // However, if the type is too small, intermediate "multi-combine-exit"
00242   // calls will be automatically generated to avoid overflows.
00243   // "unsigned short int" is a little bit faster than "unsigned int" for
00244   // mmx-aware machines (as it needs less memory and thereby also provides
00245   // better cache effectiveness).
00246   typedef unsigned short int TExponentArrayElement;
00247 
00248   struct SMulticombineData
00249    {
00250      TExponentArrayElement ExponentArray[StaticFactorbaseSettings::MaxSize+64] __attribute__ ((aligned (16)));
00251       // initial value must be {0} (please assure in the corresponding ".cc-file" that all elements are zero by default!)
00252       // +64 because we want to allow fast routines to avoid costly range checks...
00253       // 16bit alignment for fastest access in case that MMX/SSE is used to process this array
00254      unsigned long int multi_combine_Counter; // (initial value must be 0!)
00255 
00256 #if 1 && defined(ASM_SSE2)
00257  #ifdef DEBUG
00258   #warning "CRelation::SMulticombineData: using own new/delete to overcome alignment problems"
00259  #endif
00260      // too bad: __attribute__ ((aligned (16))) does not work, if memory is allocated using "new".
00261      // Solution: a tiny new-operator that uses int posix_memalign(void **memptr, size_t alignment, size_t size);
00262      // this is only a tiny, ugly, basic replacement implementation to get things to work!!
00263 
00264      static void* operator new(size_t size)
00265       {
00266         void *p;
00267 #ifdef CYGWIN_COMPAT
00268         p = memalign(16,size);
00269         if ( p==NULL || (reinterpret_cast<int>(p)&0x0f) )
00270          {
00271            cout << "NULL or not aligned p: " << p << endl;
00272            throw std::bad_alloc();
00273          }
00274 #else
00275         if (posix_memalign(&p,16,size)) throw std::bad_alloc();
00276 #endif
00277         return p;
00278       }
00279      static void operator delete(void *p, size_t /* size */)
00280       {
00281         ::free(p);
00282       }
00283 #endif
00284 
00285      SMulticombineData() : multi_combine_Counter(0)
00286       {
00287 #if defined(DEBUG) && (defined(ASM_SSE) || defined(ASM_SSE2))
00288         if (reinterpret_cast<unsigned int>(&ExponentArray[0]) &0x0fU)
00289          {
00290            MARK; cerr << "not 16-byte aligned!" << endl;
00291            cout << ExponentArray << endl;
00292            cout << this << endl;
00293          }
00294 #endif
00295         for (int i=0; i<StaticFactorbaseSettings::Size(); i++) ExponentArray[i]=0;
00296       }
00297    };
00298 
00299  protected:
00300   SMulticombineData *pMulticombineData;
00301    // pointer to a MulticombineData structure, that will be used inside the
00302    // multicombine routines. Allocating/Deallocating the Structure is done outside of this class!
00303 
00304  public:
00305   void set_MulticombineData(SMulticombineData *Data) { pMulticombineData=Data; }
00306   void invalidate_MulticombineData() { pMulticombineData=NULL; }
00307   void dispose_MulticombineData() { delete pMulticombineData; invalidate_MulticombineData(); }
00308   void use_MulticombineData_from(const CRelation &GL) { pMulticombineData=GL.pMulticombineData; }
00309   void multi_combine_init();
00310   void multi_combine_main(const CRelation& GL2);
00311   void multi_combine_exit();
00312 
00313  protected:
00314   inline void adjust_multi_combine()
00315    {
00316      // increase multi_combine_Counter and protect against overflow
00317      if (++pMulticombineData->multi_combine_Counter>=std::numeric_limits<TExponentArrayElement>::max())
00318       {
00319 #ifdef VERBOSE
00320         cout << "intermediate multi_combine_exit() issued" << endl;
00321 #endif
00322         --pMulticombineData->multi_combine_Counter;
00323         multi_combine_exit(); // do intermediate combine_exit to avoid overflow
00324         ++pMulticombineData->multi_combine_Counter;
00325       }
00326    }
00327 
00328  public:
00329   bool ComputeQuadraticCongruence() const;
00330   bool is_valid() const; // check, whether the relation is valid (congruency must be valid)
00331   static bool is_valid(istream &in); // check, whether the relation given at the current file & fileposition is valid. (congruency must be valid)
00332   inline void SanityCheck() const // check, whether the relation is valid (congruency must be valid, otherwise: abort program)
00333    {
00334      if (!is_valid()) exit(1);
00335    }
00336   static void SanityCheck(istream &in) // check, whether the relation given at the current file & fileposition is valid. (congruency must be valid, otherwise: abort program)
00337    {
00338      if (!CRelation::is_valid(in)) exit(1);
00339    }
00340   static void SanityCheckRelationsFile(const std::string FileName); // check, whether the relations inside file are valid. (congruency must be valid, otherwise: abort program)
00341 
00342  private:
00343   inline void swap(CRelation &GL2)
00344     { 
00345       // swap content of this relation with the content of GL2
00346       // (using reference semantic)
00347       std::swap(Relation_sparse,GL2.Relation_sparse);
00348       std::swap(Relation_dense,GL2.Relation_dense);
00349       std::swap(relevant_factor,GL2.relevant_factor);
00350       mpz_swap(Delta,GL2.Delta);
00351     }
00352  public:
00353   inline bool operator< (const CRelation &GL2) const
00354     {   
00355       return relevant_factor < GL2.relevant_factor;
00356     }
00357   streampos save(ostream &out, const CmpqsFactor factor, const short int HitCount=0) const;
00358   inline streampos save(ostream &out, const int i=1, const short int HitCount=0) const
00359    {
00360      CmpqsFactor DLP;
00361      DLP=i;
00362      return save(out,DLP,HitCount);
00363    }
00364   CmpqsFactor combine(istream &in, const streampos pos);
00365   CmpqsFactor multi_combine_main(istream &in, const streampos pos);
00366   CmpqsFactor combine(istream &in);
00367   CmpqsFactor multi_combine_main(istream &in);
00368   friend ostream& operator<< (ostream& ostr, const CRelation& GL);
00369   friend class StaticRelations;
00370   friend class SpecialRelations;
00371   friend class Cprocess_clients;
00372 };
00373 
00374 
00376 ostream& operator<< (ostream& ostr, const CRelation& GL);
00377 
00378 
00379 
00390 class TDynamicFactorRelation
00391 {
00392   // If factor is not too big, then we can sieve with it as a dynamic factor.
00393   // At the moment dynamic factors are restricted to "int".
00394 private:
00395   static void append_DynamicFactor_for_sieving(const int DynFac);
00396 public:
00397   int factor; // factor is given as an integer value
00398   streampos fpos;
00399 
00400   TDynamicFactorRelation() : factor(0), fpos(-1) { }
00401 
00402   inline bool operator() (const TDynamicFactorRelation &t1, const TDynamicFactorRelation &t2) const
00403     { 
00404       // for STL: set
00405       return t1.factor<t2.factor;
00406     }
00407   inline int operator() (const TDynamicFactorRelation &t2) const
00408     { 
00409       // for GNU extension: hash_set
00410       return t2.factor;
00411     }
00412   inline bool operator== (const TDynamicFactorRelation &t2) const
00413     { 
00414       return factor==t2.factor;
00415     }
00416   inline bool sieveable() const
00417    {
00418      // are we allowed to sieve with this Large Prime?
00419      return factor<DynamicFactor_SievingThreshold;
00420    }
00421   inline void append_for_sieving() const
00422    {
00423 #ifndef IS_SERVER
00424      // since the server itself does no sieving at all,
00425      // this is done only for clients and standalone versions:
00426      if (sieveable()) append_DynamicFactor_for_sieving(factor);
00427 #endif
00428    }
00429 };
00430 
00431 
00437 struct TSieve_Delta
00438 {
00439   int delta;
00440   int factor;
00441   inline bool operator< (const TSieve_Delta &v) const
00442     {
00443 #if defined (USE_FIBHEAP)
00444       return (delta < v.delta);
00445 #else
00446       return (delta > v.delta);
00447 #endif
00448       // delta > v.delta , if queue is used
00449       // delta < v.delta , if fibonacci-heap is used
00450     }
00451 };
00452 
00453 
00454 #endif

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