HermesCommon  2.0
array.h
Go to the documentation of this file.
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
18 #ifndef __HERMES_COMMON_ARRAY_H
19 #define __HERMES_COMMON_ARRAY_H
20 
21 #include <vector>
22 #include <limits.h>
23 
24 #ifndef INVALID_IDX
25 #define INVALID_IDX INT_MAX
26 #endif
27 namespace Hermes
28 {
29  namespace Hermes2D
30  {
39  template<class TYPE>
40  class Array
41  {
42  protected:
44  Hermes::vector<int> unused;
45  int size, nitems;
46  bool append_only;
47 
48  static const int HERMES_PAGE_BITS = 10;
49  static const int HERMES_PAGE_SIZE = 1 << HERMES_PAGE_BITS;
50  static const int HERMES_PAGE_MASK = HERMES_PAGE_SIZE-1;
51 
52  public:
53 
54  Array()
55  {
56  size = nitems = 0;
57  append_only = false;
58  }
59 
60  Array(Array& array) { copy(array); }
61 
62  ~Array() { free(); }
63 
65  void copy(const Array& array)
66  {
67  free();
68 
69  pages = array.pages;
70  unused = array.unused;
71  size = array.size;
72  nitems = array.nitems;
73  append_only = array.append_only;
74 
75  for (unsigned i = 0; i < pages.size(); i++)
76  {
77  TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
78  memcpy(new_page, pages[i], sizeof(TYPE) * HERMES_PAGE_SIZE);
79  pages[i] = new_page;
80  }
81  }
82 
84  void free()
85  {
86  for (unsigned i = 0; i < pages.size(); i++) delete [] pages[i];
87  pages.clear();
88  unused.clear();
89  size = nitems = 0;
90  }
91 
97  void set_append_only(bool append_only)
98  {
99  this->append_only = append_only;
100  }
101 
103  int add(TYPE item)
104  {
105  TYPE* ptr = this->add();
106  *ptr = item;
107  return ptr->id;
108  }
109 
114  TYPE* add()
115  {
116  TYPE* item;
117  if (unused.empty() || append_only)
118  {
119  if (!(size & HERMES_PAGE_MASK))
120  {
121  TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
122  pages.push_back(new_page);
123  }
124  item = pages[size >> HERMES_PAGE_BITS] + (size & HERMES_PAGE_MASK);
125  item->id = size++;
126  item->used = 1;
127  }
128  else
129  {
130  int id = unused.back();
131  unused.pop_back();
132  item = pages[id >> HERMES_PAGE_BITS] + (id & HERMES_PAGE_MASK);
133  item->used = 1;
134  }
135  nitems++;
136  return item;
137  }
138 
143  void remove(int id)
144  {
145  assert(id >= 0 && id < size);
146  TYPE* item = pages[id >> HERMES_PAGE_BITS] + (id & HERMES_PAGE_MASK);
147  assert(item->used);
148  item->used = 0;
149  unused.push_back(id);
150  nitems--;
151  }
152 
153  // Iterators
154 
161  int first(int idx = 0)
162  {
163  int index = idx;
164  while (get(index).used == false)
165  {
166  index++;
167  if (index >= nitems) return INVALID_IDX;
168  }
169  return index;
170  }
171 
178  int next(int idx = 0)
179  {
180  int index = idx + 1;
181  while (get(index).used == false)
182  {
183  index++;
184  if (index >= nitems) return INVALID_IDX;
185  }
186  return index;
187  }
188 
195  int last(int idx = INT_MAX)
196  {
197  int index = idx;
198  if (index > nitems - 1) index = nitems - 1;
199  while (get(index).used == false)
200  {
201  index--;
202  if (index < 0) return INVALID_IDX;
203  }
204  return index;
205  }
206 
213  int prev(int idx = INT_MAX)
214  {
215  int index = idx - 1;
216  if (index > nitems - 1) index = nitems - 1;
217  while (get(index).used == false)
218  {
219  index--;
220  if (index < 0) return INVALID_IDX;
221  }
222  return index;
223  }
224 
226  bool exists(int idx)
227  {
228  if (get(idx).used == true) return true;
229  else return false;
230  }
231 
235  void force_size(int size)
236  {
237  free();
238  while (size > 0)
239  {
240  TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
241  memset(new_page, 0, sizeof(TYPE) * HERMES_PAGE_SIZE);
242  pages.push_back(new_page);
243  size -= HERMES_PAGE_SIZE;
244  }
245  this->size = pages.size() * HERMES_PAGE_SIZE;
246  }
247 
251  void post_load_scan(int start = 0)
252  {
253  nitems = 0;
254  for (int i = start; i < size; i++)
255  if (get(i).used) nitems++;
256  else unused.push_back(i);
257  }
258 
261  void skip_slot()
262  {
263  if (!(size & HERMES_PAGE_MASK))
264  {
265  TYPE* new_page = new TYPE[HERMES_PAGE_SIZE];
266  pages.push_back(new_page);
267  }
268  TYPE* item = pages[size >> HERMES_PAGE_BITS] + (size & HERMES_PAGE_MASK);
269  item->id = size++;
270  item->used = 0;
271  nitems++;
272  }
273 
274  int get_size() const { return size; }
275  int get_num_items() const { return nitems; }
276 
277  TYPE& get(int id) const { return pages[id >> HERMES_PAGE_BITS][id & HERMES_PAGE_MASK]; }
278  TYPE& operator[] (int id) const { return get(id); }
279 
280  };
281 
284  template<class TYPE>
286  {
287  protected:
288  Hermes::vector<TYPE*> pages; //\todo standard array for maximum access speed
289  Hermes::vector<bool*> presence; //\todo standard array for maximum access speed
290  unsigned int size;
291 
292  const unsigned int page_bits;
293  const unsigned int page_size;
294  const unsigned int page_mask;
295 
296  public:
297 
298  LightArray(unsigned int page_bits = 9) : page_bits(page_bits), page_size(1 << page_bits), page_mask((1 << page_bits) - 1)
299  {
300  size = 0;
301  }
302 
303  ~LightArray()
304  {
305  for(unsigned int i = 0; i < pages.size(); i++)
306  {
307  delete [] pages[i];
308  delete [] presence[i];
309  }
310  pages.clear();
311  presence.clear();
312  }
313 
315  void add(TYPE item, unsigned int id)
316  {
317  TYPE* temp;
318  while(id >= pages.size() * page_size)
319  {
320  TYPE* new_page = new TYPE[page_size];
321  pages.push_back(new_page);
322 
323  bool* new_page_presence = new bool[page_size];
324  memset(new_page_presence, 0, page_size * sizeof(bool));
325  presence.push_back(new_page_presence);
326  }
327 
328  temp = pages[id >> page_bits] + (id & page_mask);
329  *temp = item;
330 
331  presence[id >> page_bits][id & page_mask] = true;
332 
333  if(id >= size)
334  size = id + 1;
335  return;
336  }
337 
338  unsigned int get_size() const
339  {
340  return size;
341  }
342 
344  bool present(unsigned int id) const
345  {
346  if(id >= size)
347  return false;
348  return presence[id >> page_bits][id & page_mask];
349  }
350 
352  TYPE& get(unsigned int id) const
353  {
354  assert(id < size);
355  return pages[id >> page_bits][id & page_mask];
356  }
357 
358  };
359  }
360 }
361 #endif