00001
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
00013 #define DynArrayPageConstr_D 0
00014 #define DynArrayDestr_D 0
00015 #define DynArrayIndex_D 0
00016
00017 namespace concepts {
00018
00019
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
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
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 }
00356
00357 #endif // dynarray_hh