|
HermesCommon 1.0
|
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
1.7.4