HermesCommon 1.0
array.h
Go to the documentation of this file.
00001 // This file is part of Hermes2D.
00002 //
00003 // Hermes2D is free software: you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation, either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // Hermes2D is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with Hermes2D.  If not, see <http://www.gnu.org/licenses/>.
00018 #ifndef __HERMES_COMMON_ARRAY_H
00019 #define __HERMES_COMMON_ARRAY_H
00020 
00021 #include <vector>
00022 #include <limits.h>
00023 
00024 #ifndef INVALID_IDX
00025 #define INVALID_IDX      INT_MAX
00026 #endif
00027 namespace Hermes
00028 {
00029   namespace Hermes2D
00030   {
00039     template<class TYPE>
00040     class Array
00041     {
00042     protected:
00043       Hermes::vector<TYPE*> pages; 
00044       Hermes::vector<int> unused;
00045       int  size, nitems;
00046       bool append_only;
00047 
00048       static const int HERMES_PAGE_BITS = 10;
00049       static const int HERMES_PAGE_SIZE = 1 << HERMES_PAGE_BITS;
00050       static const int HERMES_PAGE_MASK = HERMES_PAGE_SIZE-1;
00051 
00052     public:
00053 
00054       Array()
00055       {
00056         size = nitems = 0;
00057         append_only = false;
00058       }
00059 
00060       Array(Array& array) { copy(array); }
00061 
00062       ~Array() { free(); }
00063 
00065       void copy(const Array& array)
00066       {
00067         free();
00068 
00069         pages = array.pages;
00070         unused = array.unused;
00071         size = array.size;
00072         nitems = array.nitems;
00073         append_only = array.append_only;
00074 
00075         for (unsigned i = 0; i < pages.size(); i++)
00076         {
00077           TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
00078           memcpy(new_page, pages[i], sizeof(TYPE) * HERMES_PAGE_SIZE);
00079           pages[i] = new_page;
00080         }
00081       }
00082 
00084       void free()
00085       {
00086         for (unsigned i = 0; i < pages.size(); i++) delete [] pages[i];
00087         pages.clear();
00088         unused.clear();
00089         size = nitems = 0;
00090       }
00091 
00097       void set_append_only(bool append_only)
00098       {
00099         this->append_only = append_only;
00100       }
00101 
00103       int add(TYPE item)
00104       {
00105         TYPE* ptr = this->add();
00106         *ptr = item;
00107         return ptr->id;
00108       }
00109 
00114       TYPE* add()
00115       {
00116         TYPE* item;
00117         if (unused.empty() || append_only)
00118         {
00119           if (!(size & HERMES_PAGE_MASK))
00120           {
00121             TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
00122             pages.push_back(new_page);
00123           }
00124           item = pages[size >> HERMES_PAGE_BITS] + (size & HERMES_PAGE_MASK);
00125           item->id = size++;
00126           item->used = 1;
00127         }
00128         else
00129         {
00130           int id = unused.back();
00131           unused.pop_back();
00132           item = pages[id >> HERMES_PAGE_BITS] + (id & HERMES_PAGE_MASK);
00133           item->used = 1;
00134         }
00135         nitems++;
00136         return item;
00137       }
00138 
00143       void remove(int id)
00144       {
00145         assert(id >= 0 && id < size);
00146         TYPE* item = pages[id >> HERMES_PAGE_BITS] + (id & HERMES_PAGE_MASK);
00147         assert(item->used);
00148         item->used = 0;
00149         unused.push_back(id);
00150         nitems--;
00151       }
00152 
00153       // Iterators
00154 
00161       int first(int idx = 0)
00162       {
00163         int index = idx;
00164         while (get(index).used == false)
00165         {
00166           index++;
00167           if (index >= nitems) return INVALID_IDX;
00168         }
00169         return index;
00170       }
00171 
00178       int next(int idx = 0)
00179       {
00180         int index = idx + 1;
00181         while (get(index).used == false)
00182         {
00183           index++;
00184           if (index >= nitems) return INVALID_IDX;
00185         }
00186         return index;
00187       }
00188 
00195       int last(int idx = INT_MAX)
00196       {
00197         int index = idx;
00198         if (index > nitems - 1) index = nitems - 1;
00199         while (get(index).used == false)
00200         {
00201           index--;
00202           if (index < 0) return INVALID_IDX;
00203         }
00204         return index;
00205       }
00206 
00213       int prev(int idx = INT_MAX)
00214       {
00215         int index = idx - 1;
00216         if (index > nitems - 1) index = nitems - 1;
00217         while (get(index).used == false)
00218         {
00219           index--;
00220           if (index < 0) return INVALID_IDX;
00221         }
00222         return index;
00223       }
00224 
00226       bool exists(int idx)
00227       {
00228         if (get(idx).used == true) return true;
00229         else return false;
00230       }
00231 
00235       void force_size(int size)
00236       {
00237         free();
00238         while (size > 0)
00239         {
00240           TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
00241           memset(new_page, 0, sizeof(TYPE) * HERMES_PAGE_SIZE);
00242           pages.push_back(new_page);
00243           size -= HERMES_PAGE_SIZE;
00244         }
00245         this->size = pages.size() * HERMES_PAGE_SIZE;
00246       }
00247 
00251       void post_load_scan(int start = 0)
00252       {
00253         nitems = 0;
00254         for (int i = start; i < size; i++)
00255           if (get(i).used) nitems++;
00256           else unused.push_back(i);
00257       }
00258 
00261       void skip_slot()
00262       {
00263         if (!(size & HERMES_PAGE_MASK))
00264         {
00265           TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
00266           pages.push_back(new_page);
00267         }
00268         TYPE* item = pages[size >> HERMES_PAGE_BITS] + (size & HERMES_PAGE_MASK);
00269         item->id = size++;
00270         item->used = 0;
00271         nitems++;
00272       }
00273 
00274       int get_size() const { return size; }
00275       int get_num_items() const { return nitems; }
00276 
00277       TYPE& get(int id) const { return pages[id >> HERMES_PAGE_BITS][id & HERMES_PAGE_MASK]; }
00278       TYPE& operator[] (int id) const { return get(id); }
00279 
00280     };
00281 
00284     template<class TYPE>
00285     class LightArray
00286     {
00287     protected:
00288       Hermes::vector<TYPE*> pages; //\todo standard array for maximum access speed
00289       Hermes::vector<bool*> presence; //\todo standard array for maximum access speed
00290       unsigned int size;
00291 
00292       const unsigned int page_bits;
00293       const unsigned int page_size;
00294       const unsigned int page_mask;
00295 
00296     public:
00297 
00298       LightArray(unsigned int page_bits = 9) : page_bits(page_bits), page_size(1 << page_bits), page_mask((1 << page_bits) - 1)
00299       {
00300         size = 0;
00301       }
00302 
00303       ~LightArray()
00304       {
00305         for(unsigned int i = 0; i < pages.size(); i++)
00306         {
00307           delete [] pages[i];
00308           delete [] presence[i];
00309         }
00310         pages.clear();
00311         presence.clear();
00312       }
00313 
00315       void add(TYPE item, unsigned int id)
00316       {
00317         TYPE* temp;
00318         while(id >= pages.size() * page_size)
00319         {
00320           TYPE* new_page = new TYPE[page_size];
00321           pages.push_back(new_page);
00322 
00323           bool* new_page_presence = new bool[page_size];
00324           memset(new_page_presence, 0, page_size * sizeof(bool));
00325           presence.push_back(new_page_presence);
00326         }
00327 
00328         temp = pages[id >> page_bits] + (id & page_mask);
00329         *temp = item;
00330 
00331         presence[id >> page_bits][id & page_mask] = true;
00332 
00333         if(id >= size)
00334           size = id + 1;
00335         return;
00336       }
00337 
00338       unsigned int get_size() const
00339       {
00340         return size;
00341       }
00342 
00344       bool present(unsigned int id) const
00345       {
00346         if(id >= size)
00347           return false;
00348         return presence[id >> page_bits][id & page_mask];
00349       }
00350 
00352       TYPE& get(unsigned int id) const
00353       {
00354         assert(id < size);
00355         return pages[id >> page_bits][id & page_mask];
00356       }
00357 
00358     };
00359   }
00360 }
00361 #endif