Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

toolbox/dynArray.hh
Go to the documentation of this file.
00001 /* dynamic array
00002  */
00003 
00004 #ifndef dynarray_hh
00005 #define dynarray_hh
00006 
00007 #include "basics/outputOperator.hh"
00008 #include "basics/exceptions.hh"
00009 #include "basics/typedefs.hh"
00010 #include "basics/debug.hh"
00011 
00012 // debugging
00013 #define DynArrayPageConstr_D 0
00014 #define DynArrayDestr_D 0
00015 #define DynArrayIndex_D 0
00016 
00017 namespace concepts {
00018 
00019   // ********************************************************** DynArrayBase **
00020 
00025   class DynArrayBase : public OutputOperator {
00026   public:
00027     DynArrayBase(const uint htblsz, const uint htblmsk,
00028      const uint pgsz, const uint pgmsk,
00029      const bool init = false);
00031     DynArrayBase(const DynArrayBase& base);
00032     virtual ~DynArrayBase();
00033 
00035     uint max() const { return max_; }
00036 
00038     uint min() const { return min_; }
00039   protected:
00040     bool init_;
00041     bool empty_;
00042     uint max_;
00043     uint min_;
00044     uint npg_;
00045  
00047     const uint htblsz_;
00048 
00050     const uint htblmsk_;
00051 
00053     const uint pgsz_;
00054     const uint pgmsk_;
00055 
00056     void operator=(DynArrayBase&) {
00057       throw conceptsException(ExceptionBase());
00058     }
00059 
00060     virtual std::ostream& info(std::ostream& os) const;
00061   };
00062 
00063   // ********************************************************** DynArrayPage **
00064 
00069   template <class T>
00070   class DynArrayPage {
00071     DynArrayPage* lnk_;
00072     uint idx_;
00073     uint sz_;
00074     T* mem_;
00075   public:
00076     DynArrayPage(uint idx, uint sz, DynArrayPage* lnk = 0) :
00077       lnk_(lnk), idx_(idx), sz_(sz), mem_(new T[sz]) {
00078       DEBUGL(DynArrayPageConstr_D, "done.");
00079     }
00081     DynArrayPage(const DynArrayPage& pg) :
00082       lnk_(0), idx_(pg.idx_), sz_(pg.sz_), mem_(new T[sz_]) {
00083       std::memcpy(mem_, pg.mem_, sz_*sizeof(T));
00084       if (pg.lnk_)
00085   lnk_ = new DynArrayPage<T>(*pg.lnk_);
00086     }
00087     ~DynArrayPage() { delete[] mem_; }
00088 
00089     T& operator[](uint i) { return mem_[i]; }
00090 
00091     uint index() const { return idx_; }
00092     DynArrayPage* link() const { return lnk_; }
00093   };
00094 
00095   // ************************************************************** DynArray **
00096 
00102   template <class T>
00103   class DynArray : public DynArrayBase {
00104   public:
00119     inline DynArray(uint htblsz = 2, uint pgsz = 2);
00120     inline DynArray(uint htblsz, uint pgsz, const T& dflt);
00122     inline DynArray(const DynArray& d);
00123     inline ~DynArray();
00124 
00132     T& operator [](uint i);
00133 
00138     const T& operator [](uint i) const;
00139 
00143     bool isElm(uint i);
00144     const bool isElm(uint i) const;
00145 
00147     inline float memory() const; 
00148 
00150     void reset();                
00151   protected:
00152     virtual std::ostream& info(std::ostream& os) const;
00153   private:
00154     DynArrayPage<T>** htbl_;
00155     DynArrayPage<T>*  lru_;
00156     T dflt_;
00157   };
00158 
00159   template<class T> 
00160   DynArray<T>::DynArray(uint htblsz, uint pgsz) :
00161     DynArrayBase(htblsz, (1 << htblsz) - 1, pgsz, (1 << pgsz) - 1, false),
00162     htbl_(new DynArrayPage<T>*[htblmsk_ + 1]), lru_(0) {
00163     for(uint i = htblmsk_ + 1; i--;)
00164       htbl_[i] = 0;
00165   }
00166 
00167   template<class T> 
00168   DynArray<T>::DynArray(uint htblsz, uint pgsz, const T& dflt) : 
00169     DynArrayBase(htblsz, (1 << htblsz) - 1, pgsz, (1 << pgsz) - 1, true),
00170     htbl_(new DynArrayPage<T>*[htblmsk_ + 1]), lru_(0), dflt_(dflt) {
00171     for(uint i = htblmsk_ + 1; i--;)
00172       htbl_[i] = 0; 
00173   }
00174 
00175   template <class T>
00176   DynArray<T>::DynArray(const DynArray<T>& d)
00177     : DynArrayBase(d), htbl_(new DynArrayPage<T>*[htblmsk_ + 1]),
00178       lru_(0), dflt_(d.dflt_) {
00179     for(uint i = d.htblmsk_ + 1; i--;)
00180       if (d.htbl_[i])
00181   htbl_[i] = new DynArrayPage<T>(*d.htbl_[i]);
00182   }
00183 
00184   template <class T> 
00185   DynArray<T>::~DynArray() {
00186     DEBUGL(DynArrayDestr_D, "start.");
00187     for(uint i = htblmsk_ + 1; i--;) {
00188       DynArrayPage<T>* pg = htbl_[i];
00189       while (pg != NULL) {
00190   DynArrayPage<T>* foo = pg; pg = pg->link();
00191   delete foo;
00192       }
00193     }
00194     delete[] htbl_;
00195     DEBUGL(DynArrayDestr_D, "done.");
00196   }
00197 
00198   template <class T> 
00199   T& DynArray<T>::operator[](uint i) {
00200     DEBUGL(DynArrayIndex_D, "i = " << i);
00201 
00202     if (!(i < max_))
00203       max_ = i + 1;
00204     if (lru_ == NULL || i < min_)
00205       min_ = i;
00206 
00207     uint pgidx = i >> pgsz_;
00208 
00209     if (lru_ != NULL && lru_->index() == pgidx)
00210       return (*lru_)[i & pgmsk_];
00211 
00212     DynArrayPage<T>** htbl = htbl_ + (pgidx & htblmsk_);
00213 
00214     DynArrayPage<T>* pg = *htbl;
00215     while(pg != 0) {
00216       if (pg->index() == pgidx) 
00217   return (*(lru_ = pg))[i & pgmsk_];
00218       pg = pg->link();
00219     }
00220 
00221     *htbl = pg = new DynArrayPage<T>(pgidx, pgmsk_ + 1, *htbl);
00222     npg_++;
00223     if (init_)
00224       for(uint j = pgmsk_ + 1; j--;)
00225   (*pg)[j] = dflt_;
00226 
00227     return (*(lru_ = pg))[i & pgmsk_];
00228   }
00229 
00230   template <class T> 
00231   const T& DynArray<T>::operator[](uint i) const {
00232 
00233     if (!(i < max_)) {
00234       DEBUGL(DynArrayIndex_D, *this);
00235       DEBUGL(DynArrayIndex_D, "i = " << i);
00236       throw conceptsException(IndexNotExisting());
00237     }
00238     if (lru_ == NULL || i < min_) {
00239       DEBUGL(DynArrayIndex_D, *this);
00240       DEBUGL(DynArrayIndex_D, "i = " << i);
00241       throw conceptsException(IndexNotExisting());
00242     }
00243 
00244     uint pgidx = i >> pgsz_;
00245 
00246     if (lru_ != NULL && lru_->index() == pgidx)
00247       return (*lru_)[i & pgmsk_];
00248 
00249     DynArrayPage<T>** htbl = htbl_ + (pgidx & htblmsk_);
00250 
00251     DynArrayPage<T>* pg = *htbl;
00252     while(pg != 0) {
00253       if (pg->index() == pgidx) 
00254   return (*pg)[i & pgmsk_];
00255       pg = pg->link();
00256     }
00257     DEBUGL(DynArrayIndex_D, *this);
00258     DEBUGL(DynArrayIndex_D, "i = " << i);
00259     throw conceptsException(IndexNotExisting());
00260   }
00261 
00262   template <class T> 
00263   bool DynArray<T>::isElm(uint i) {
00264 
00265     if (!(i < max_))  return 0;
00266     if (lru_ == 0 || i < min_)  return 0;
00267 
00268     uint pgidx = i >> pgsz_;
00269 
00270     if (lru_ != 0 && lru_->index() == pgidx)
00271       return (init_) ? ((*lru_)[i & pgmsk_] != dflt_) : 1;
00272 
00273     DynArrayPage<T>** htbl = htbl_ + (pgidx & htblmsk_);
00274 
00275     DynArrayPage<T>* pg = *htbl;
00276     while(pg != 0) {
00277       if (pg->index() == pgidx) {
00278         lru_ = pg;
00279   return (init_) ? ((*lru_)[i & pgmsk_] != dflt_) : 1;
00280       }
00281       pg = pg->link();
00282     }
00283     return 0;
00284   }
00285 
00286   template <class T> 
00287   const bool DynArray<T>::isElm(uint i) const {
00288 
00289     if (!(i < max_))  return 0;
00290     if (lru_ == 0 || i < min_)  return 0;
00291 
00292     uint pgidx = i >> pgsz_;
00293 
00294     DynArrayPage<T>* lru = lru_;
00295 
00296     if (lru != 0 && lru->index() == pgidx)
00297       return (init_) ? (&(*lru)[i & pgmsk_] != &dflt_) : 1;
00298 
00299     DynArrayPage<T>** htbl = htbl_ + (pgidx & htblmsk_);
00300 
00301     DynArrayPage<T>* pg = *htbl;
00302     while(pg != 0) {
00303       if (pg->index() == pgidx) {
00304         lru = pg;
00305   return (init_) ? ((*lru)[i & pgmsk_] != dflt_) : 1;
00306       }
00307       pg = pg->link();
00308     }
00309     return 0;
00310   }
00311 
00312   template <class T> 
00313   inline float DynArray<T>::memory() const {
00314     return sizeof(DynArray) + (float)(1 << htblsz_) * 
00315       sizeof(DynArrayPage<T>*) + (float)npg_ *
00316       (sizeof(DynArrayPage<T>) + (float)(1 << pgsz_) * sizeof(T));
00317   }
00318 
00319   template <class T>
00320   void DynArray<T>::reset() {
00321     for(uint i = htblmsk_ + 1; i--;) {
00322       DynArrayPage<T>* pg = htbl_[i]; 
00323       while (pg != NULL) {
00324   DynArrayPage<T>* foo = pg;
00325   pg = pg->link();
00326   delete foo;
00327       }
00328       htbl_[i] = NULL;
00329     }
00330     lru_ = NULL; max_ = min_ = 0; npg_ = 0;
00331   }
00332 
00333   template <class T>
00334   std::ostream& DynArray<T>::info(std::ostream& os) const {
00335     os << "DynArray(init = " << init_ << ", emtpy = " << empty_
00336        << ", min = " << min_ << ", max = " << max_ << ", npg = "
00337        << npg_ << ", htblsz = " << htblsz_ << ", htblmsk = "
00338        << htblmsk_ << ", pgsz = " << pgsz_ << ", pgmsk = " << pgmsk_
00339        << ", [" << std::endl;
00340     for(uint i = htblmsk_ + 1; i--;) {
00341       DynArrayPage<T>* pg = htbl_[i]; 
00342       while (pg != NULL) {
00343   uint pgidx = pg->index();
00344   os << pgidx << " | ";
00345   for (uint j = 0; j <= pgmsk_; ++j)
00346     os << '(' << (pgidx << pgsz_) + j << ", " << (*pg)[j] << "), ";
00347   pg = pg->link();
00348   os << std::endl;
00349       }
00350     }
00351     os << "])";
00352     return os;
00353   }
00354 
00355 } // namespace concepts
00356 
00357 #endif // dynarray_hh

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)