TinyVector.H

Go to the documentation of this file.
00001 #ifndef tinyvector_header
00002 #define tinyvector_header
00003 
00004 // provide a simple dynamic array.
00005 // Main task: sparse representation of factor indices
00006 // for the static factorbase in qsieve.
00007 // (C) 1999 by Thorsten Reinecke
00008 // major rewrite 2003-10 by Thorsten Reinecke
00009 // last change: 2004-11-30 by Thorsten Reinecke
00010 
00017 #include <limits>
00018 #include <stdexcept>
00019 
00020 //
00021 // base types of C-Arrays, who are encapsulated in a "struct"
00022 //
00023 
00024 // the following prefixes are introduced, because identifiers of the form "_" + capital letter are reserved
00025 // prefix TT_ stands for "template type"
00026 // prefix VTBC_ stands for "virtual template base class"
00027 
00028 template <typename TT_Datatype, typename TT_Sizetype = int> class VTBC_StructArray
00029 {
00030 public:
00031  typedef TT_Datatype Datatype;
00032  typedef TT_Sizetype Sizetype;
00033 
00034  Datatype* v;           // property: v is allowed to get replaced by another pointer
00035  Sizetype Capacity;     // number of allocated elements
00036  Sizetype akt_size;
00037 
00038 
00039  VTBC_StructArray(Datatype* const _v, const Sizetype myCapacity, const Sizetype _size=0)
00040   : v(_v), Capacity(myCapacity), akt_size(_size) { }
00041 
00042 private:
00043  VTBC_StructArray(const VTBC_StructArray&);
00044  inline const VTBC_StructArray& operator= (const VTBC_StructArray&) const { MARK; exit(9); return *this; }
00045 
00046 public:
00047 
00048  // max_size is the maximum count of elements in the array.
00049  // (Allocating a larger array for "v" is allowed in this class!) 
00050  inline Sizetype max_size(void) const { return std::numeric_limits<Sizetype>::max(); }
00051 };
00052 
00053 template <typename TT_Datatype, typename TT_Sizetype = int> class VTBC_FixedStructArray
00054 {
00055 public:
00056  typedef TT_Datatype Datatype;
00057  typedef TT_Sizetype Sizetype;
00058 
00059  Datatype* const v;        // property: v is no more allowed to be changed
00060  const Sizetype Capacity;  // constant number of allocated elements
00061  Sizetype akt_size;
00062 
00063 
00064  VTBC_FixedStructArray(Datatype* const _v, const Sizetype myCapacity, const Sizetype _size=0)
00065   : v(_v), Capacity(myCapacity), akt_size(_size) { }
00066 
00067  // max_size is the maximum count of elements in the array.
00068  // (Allocating a larger array for "v" is forbidden in this class!) 
00069  inline Sizetype max_size(void) const { return Capacity; }
00070 };
00071 
00072 
00073 //
00074 // Enrich the base types with useful methods
00075 //
00076 
00077 //#define RANGE_CHECKS
00078 
00079 // some useful methods
00080 template <typename StructArraytype> class EnrichedArray
00081 : protected StructArraytype
00082 {
00083 public:
00084  typedef typename StructArraytype::Datatype Datatype;
00085  typedef typename StructArraytype::Sizetype Sizetype;
00086 
00087  EnrichedArray(Datatype* const _v, const Sizetype myCapacity, const Sizetype _size=0)
00088   : StructArraytype(_v,myCapacity,_size) { }
00089 
00090 #ifndef RANGE_CHECKS
00091  inline void set_size(const Sizetype new_size) { StructArraytype::akt_size=new_size; }
00092 #else
00093  inline void set_size(const Sizetype new_size)
00094   {
00095     if (new_size>StructArraytype::Capacity || new_size<0)
00096      {
00097        cerr << "set_size: Range Overflow! " << new_size << " > " << StructArraytype::Capacity << endl;
00098        throw std::length_error("set_size: new_size out of range!");
00099      } 
00100     StructArraytype::akt_size=new_size;
00101   }
00102 #endif
00103 
00104 
00105  inline Sizetype size(void) const { return StructArraytype::akt_size; }
00106  inline bool empty(void) const { return (StructArraytype::akt_size==0); }
00107  inline Sizetype capacity(void) const { return StructArraytype::Capacity; }
00108  // redefine max_size because of protected inheritance
00109  inline Sizetype max_size(void) const { return StructArraytype::max_size(); }
00110 
00111 #ifndef RANGE_CHECKS
00112  inline const Datatype& operator[] (const Sizetype pos) const { return StructArraytype::v[pos]; }
00113  inline Datatype& operator[] (const Sizetype pos) { return StructArraytype::v[pos]; }
00114 #else
00115  inline const Datatype& operator[] (const Sizetype pos) const
00116   {
00117     if ( pos>capacity() || pos<0 || capacity()<1 )
00118      {
00119        cerr << "r/operator[]: Range Overflow! " << pos << " > " << StructArraytype::Capacity << endl;
00120        throw std::out_of_range("r/operator[]: pos is out of range");
00121      } 
00122     return StructArraytype::v[pos];
00123   }
00124  inline Datatype& operator[] (const Sizetype pos)
00125   {
00126     if ( pos>capacity() || pos<0 || capacity()<1 )
00127      {
00128        cerr << "rw/operator[]: Range Overflow! " << pos << " > " << StructArraytype::Capacity << endl;
00129        throw std::out_of_range("rw/operator[]: pos is out of range");
00130      } 
00131     return StructArraytype::v[pos];
00132   }
00133 #endif
00134 };
00135 
00136 
00137 // constructor-/destructor, who do the real work of allocating/deallocating elements
00138 template <typename StructArraytype> class AutofiedStructArray
00139 : public StructArraytype
00140 {
00141 private:
00142   typedef typename StructArraytype::Datatype Datatype;
00143   typedef typename StructArraytype::Sizetype Sizetype;
00144 public:
00145  explicit AutofiedStructArray(const Sizetype myCapacity)
00146   : StructArraytype(new Datatype[myCapacity],myCapacity,0) { }
00147 
00148  AutofiedStructArray(Datatype* const _v, const Sizetype myCapacity, const Sizetype _size=0)
00149   : StructArraytype(_v,myCapacity,_size) { }
00150 
00151  virtual ~AutofiedStructArray() { delete [] AutofiedStructArray::v; }
00152 };
00153 
00154 
00155 
00156 // macro for template composition analogous to composition of mathematical functions: g(f(X))=(gof)(X)
00157 // "Composed_"-template (f) is composed by the "Composer_"-template (g);
00158 // the composition of these templates results in the "Compositum_" (gof).
00159 // example: B<A<T1,T2> >  --TemplateComposition--> C<T1,T2> (accessible as C<T1,T2>::Type)
00160 #define TemplateComposition(Composer_, Composed_, Compositum_) \
00161 template <typename T1, typename T2 = int> struct Compositum_ \
00162 { \
00163   typedef Composer_ < Composed_ <T1,T2> >  Type; \
00164 };
00165 
00166 
00167 TemplateComposition(EnrichedArray,VTBC_StructArray,StructArray)
00168 TemplateComposition(EnrichedArray,VTBC_FixedStructArray,FixedStructArray)
00169 
00170 
00171 #define TemplateComposition2(Composer_, Composed1_, Composed2_, Compositum_) \
00172 template <typename T1, typename T2 = int> struct Compositum_ \
00173 { \
00174   typedef Composer_ < Composed1_ < Composed2_ <T1,T2> > >  Type; \
00175 };
00176 
00177 // two-step composition: h(g(f(X)))=(hogof)(X)
00178 TemplateComposition2(AutofiedStructArray,EnrichedArray,VTBC_StructArray,AutoStructArray)
00179 TemplateComposition2(AutofiedStructArray,EnrichedArray,VTBC_FixedStructArray,AutoFixedStructArray)
00180 
00181 
00182 
00183 template <typename Datatype, typename Sizetype=int, Sizetype DefaultResizeStep=32> class CTinyVector
00184 : public AutoStructArray<Datatype,Sizetype>::Type
00185 {
00186   typedef typename AutoStructArray<Datatype,Sizetype>::Type Ancestor;
00187 public:
00188   inline explicit CTinyVector(const Sizetype MaxSize = DefaultResizeStep) // constructor
00189    : Ancestor(new Datatype [MaxSize],MaxSize) { }
00190 
00191   inline CTinyVector(const Datatype* Feld, const Sizetype Size)
00192    : Ancestor(Size)
00193     // constructor: initialize with a given array
00194     {
00195       for(Sizetype i=0; i<Size; i++) Ancestor::v[i]=Feld[i];
00196       Ancestor::akt_size=Size;
00197     }
00198   inline CTinyVector(const CTinyVector<Datatype>& tv)
00199     // constructor: initialize with another TinyVector
00200    : Ancestor(tv.size())
00201     {
00202       Ancestor::akt_size=tv.akt_size;
00203       for(Sizetype i=0; i<Ancestor::akt_size; i++) Ancestor::v[i]=tv[i];
00204     }
00205   inline void reset(void)
00206     {
00207       Ancestor::akt_size=0;
00208     }
00209   inline void resize(const Sizetype new_size)
00210     {
00211       if (new_size<Ancestor::akt_size)
00212         {
00213           cerr << "CTinyVector: Resizing not possible!" << endl;
00214           throw std::runtime_error("CTinyVector: Resizing not possible!");
00215         }
00216       if (new_size==Ancestor::capacity()) return; // nothing to do...
00217 #ifdef VERBOSE
00218       cout << "CTinyVector: resizing from " << Ancestor::capacity() << " to " << new_size << endl;
00219 #endif
00220       Datatype* vnew = new Datatype [new_size];
00221       for (Sizetype i=0; i<Ancestor::akt_size; i++) vnew[i]=Ancestor::v[i];
00222       delete [] Ancestor::v; Ancestor::v=vnew; Ancestor::Capacity=new_size;
00223     }
00224   inline void optisize(void) // optimize size of dynamic array
00225     {
00226       // to avoid heap pollution do not resize when difference in size is marginal
00227       if (Ancestor::capacity()>Ancestor::akt_size+DefaultResizeStep)
00228        resize(Ancestor::akt_size);
00229     }
00230   inline void append(const Datatype value)
00231     {
00232       if (Ancestor::akt_size>=Ancestor::Capacity) 
00233         {
00234           cerr << "TinyVector: Index " << Ancestor::akt_size
00235                << " is out Of Range!"
00236                << " Auto-Resizing by " << DefaultResizeStep << endl;
00237           resize(Ancestor::akt_size+DefaultResizeStep);
00238         }
00239       if (!Ancestor::empty() && value<=Ancestor::v[Ancestor::akt_size-1])
00240         { cerr << "TinyVector: unsorted append!" << endl; } 
00241       Ancestor::v[Ancestor::akt_size++]=value; 
00242     }
00243   inline void fast_append(const Datatype value)
00244     {
00245       Ancestor::v[Ancestor::akt_size++]=value;
00246     }
00247   inline Datatype last(void) const
00248     {
00249       if (!Ancestor::empty()) return Ancestor::v[Ancestor::akt_size-1];
00250       else
00251         {
00252           cerr << "TinyVector: no last Element!" << endl;
00253           throw std::runtime_error("TinyVector: last() called for empty vector");
00254         }
00255     }
00256 
00257   inline void copy_from(const Datatype* Feld, const Sizetype Size)
00258    {
00259      if (Size>Ancestor::capacity()) 
00260       {
00261 #ifdef VERBOSE
00262          cout << "CTinyVector:copy_from(), reallocate from " << Ancestor::capacity() << " to " << Size << endl;
00263 #endif
00264          delete [] Ancestor::v;
00265          Ancestor::v = new Datatype [Size];
00266          Ancestor::Capacity=Size;
00267       }
00268      Ancestor::akt_size=Size;
00269      for(Sizetype i=0; i<Size; i++) Ancestor::v[i]=Feld[i];
00270    }
00271   inline void copy_from(const CTinyVector<Datatype> &tv)
00272    {
00273 #if 0
00274      // this alternative ignores v.capacity()
00275      copy_from(tv.v,tv.size());
00276 #else
00277      // this alternative allocates v.capacity() entries, if reallocation is necessary
00278      if (tv.size()>Ancestor::capacity()) 
00279       {
00280 #ifdef VERBOSE
00281          cout << "CTinyVector:copy_from(), reallocate from " << Ancestor::capacity() << " to " << tv.capacity()
00282               << " using " << tv.size() << endl;
00283 #endif
00284          delete [] Ancestor::v;
00285          Ancestor::v = new Datatype [tv.capacity()];
00286          Ancestor::Capacity=tv.capacity();
00287       }
00288      Ancestor::akt_size=tv.size();
00289      for(Sizetype i=0; i<tv.size(); i++) Ancestor::v[i]=tv[i];
00290 #endif
00291    }
00292   inline void optisized_copy_from(const Datatype* Feld, const Sizetype Size)
00293    {
00294      if (Size>Ancestor::capacity() || Size+DefaultResizeStep<Ancestor::capacity())
00295       {
00296         cout << "CTinyVector:optisized_copy_from(), reallocate from " << Ancestor::capacity() << " to " << Size << endl;
00297         delete [] Ancestor::v; Ancestor::v = new Datatype [Size];
00298       }
00299      Ancestor::akt_size=Ancestor::Capacity=Size;
00300      for(Sizetype i=0; i<Size; i++) Ancestor::v[i]=Feld[i];
00301    }
00302   inline void optisized_copy_from(const CTinyVector<Datatype> &tv)
00303    {
00304      if (this==&tv) { optisize(); return; } // optimize copy from myself!
00305      optisized_copy_from(tv.v,tv.size());
00306    }
00307   inline const CTinyVector<Datatype>& operator= (const CTinyVector<Datatype> &tv)
00308    {
00309      copy_from(tv.v,tv.size()); return *this;
00310    }
00311 
00312 };
00313 
00314 #endif

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