INMOST
A toolkit for distributed mathematical modeling
container.hpp
1 #ifndef _CONTAINER_HPP
2 #define _CONTAINER_HPP
3 
4 #include <cstdlib>
5 #include <cstddef>
6 #include <cstring>
7 #include <cmath>
8 #include <cassert>
9 #include <memory>
10 #include <new>
11 #include <iterator>
12 #include <limits>
13 #include "inmost_common.h"
14 
15 //#define DEBUGMEM
16 
17 #define NEW_CHUNKS
18 #define __VOLATILE volatile
19 //#define OUT_OF_RANGE
20 
21 #if defined(_OPENMP)
22 #include <omp.h>
23 #endif
24 
25 //#define PACK_ARRAY
26 
27 //TODO
28 // 1. change to uniform size_type instead of size_t, make it INMOST_DATA_ENUM_TYPE
29 /*
30 template<class element, class T1> struct isInputRandomIterators
31 {
32  static void constraints(T1 a, T1 b) { ++a; (void)a++; a==a; a!=a; a-b; }
33  isInputRandomIterators() { void(*p)(T1,T1) = constraints; (void)p; }
34 };
35 
36 template<class element, class T1> struct isInputForwardIterators
37 {
38  static void constraints(T1 a) {++a; (void)a++; }
39  isInputForwardIterators() { void(*p)(T1) = constraints; (void)p; }
40 };
41 */
42 
43 namespace INMOST
44 {
45  //add more templates as needed
46  template<class T> struct make_unsigned;
47  template<> struct make_unsigned<char> {typedef unsigned char type;};
48  template<> struct make_unsigned<short> {typedef unsigned short type;};
49  template<> struct make_unsigned<int> {typedef unsigned int type;};
50  template<> struct make_unsigned<long> {typedef unsigned long type;};
51  template<> struct make_unsigned<long long> {typedef unsigned long long type;};
52  template<> struct make_unsigned<unsigned char> {typedef unsigned char type;};
53  template<> struct make_unsigned<unsigned short> {typedef unsigned short type;};
54  template<> struct make_unsigned<unsigned int> {typedef unsigned int type;};
55  template<> struct make_unsigned<unsigned long> {typedef unsigned long type;};
56  template<> struct make_unsigned<unsigned long long> {typedef unsigned long long type;};
57 
58 
59 #if defined(PACK_ARRAY)
60 #pragma pack(push,r1,4)
61 #endif
62  // notice: array class would not properly support classes that contain self-references
63  // like std::map
64  // notice: next class shell have to implement same algorithms as array
65  template<typename element>//, typename enumerator = unsigned int>
66  class array
67  {
68  public:
69  typedef unsigned size_type;
70  typedef make_unsigned<size_type>::type uenum;
71  template<typename etype>
72  class _iterator
73  {
74  private:
75  etype * e;
76  public:
77  typedef etype * pointer;
78  typedef etype & reference;
79  typedef etype value_type;
80  typedef ptrdiff_t difference_type;
81  typedef std::random_access_iterator_tag iterator_category;
82  _iterator():e(NULL){}
83  _iterator(etype * i):e(i){}
84  _iterator(const _iterator & other){e = other.e;}
85  ~_iterator() {};
86  _iterator operator -(size_t n) const { return _iterator(e-n); }
87  _iterator & operator -=(size_t n) { e-=n; return *this; }
88  _iterator operator +(size_t n) const { return _iterator(e+n); }
89  _iterator & operator +=(size_t n) { e+=n; return *this; }
90  _iterator & operator ++(){ ++e; return *this;}
91  _iterator operator ++(int) { return _iterator(e++); }
92  _iterator & operator --(){ --e; return *this; }
93  _iterator operator --(int) { return _iterator(e--); }
94  ptrdiff_t operator -(const _iterator & other) const {return e-other.e;}
95  etype & operator *() const { return *e; }
96  etype * operator ->() const { return e; }
97  _iterator & operator =(_iterator const & other) { e = other.e; return *this; }
98  bool operator ==(const _iterator & other) const { return e == other.e;}
99  bool operator !=(const _iterator & other) const { return e != other.e;}
100  bool operator <(const _iterator & other) const { return e < other.e;}
101  bool operator >(const _iterator & other) const { return e > other.e;}
102  bool operator <=(const _iterator & other) const { return e <= other.e;}
103  bool operator >=(const _iterator & other) const { return e >= other.e;}
104  operator void *() const {return static_cast<void *> (e);}
105  };
108  template<typename etype>
110  {
111  private:
112  etype * e;
113  public:
114  typedef etype * pointer;
115  typedef etype & reference;
116  typedef etype value_type;
117  typedef ptrdiff_t difference_type;
118  typedef std::random_access_iterator_tag iterator_category;
119  _reverse_iterator():e(NULL){}
120  _reverse_iterator(etype * i):e(i){}
121  _reverse_iterator(const _reverse_iterator & other){e = other.e;}
122  ~_reverse_iterator() {};
123  _reverse_iterator operator -(size_t n) const { return _reverse_iterator(e+n); }
124  _reverse_iterator & operator -=(size_t n) { e+=n; return *this; }
125  _reverse_iterator operator +(size_t n) const {return _reverse_iterator(e-n); }
126  _reverse_iterator & operator +=(size_t n) { e-=n; return *this; }
127  _reverse_iterator & operator ++(){ --e; return *this;}
128  _reverse_iterator operator ++(int) { return _reverse_iterator(e--); }
129  _reverse_iterator & operator --(){ ++e; return *this; }
130  _reverse_iterator operator --(int) { return _reverse_iterator(e++); }
131  ptrdiff_t operator -(const _reverse_iterator & other) const {return other.e-e;}
132  etype & operator *() const { return *e; }
133  etype * operator ->() const { return e; }
134  _reverse_iterator & operator =(_reverse_iterator const & other) { e = other.e; return *this;}
135  bool operator ==(const _reverse_iterator & other) const { return e == other.e;}
136  bool operator !=(const _reverse_iterator & other) const { return e != other.e;}
137  bool operator <(const _reverse_iterator & other) const { return e < other.e;}
138  bool operator >(const _reverse_iterator & other) const { return e > other.e;}
139  bool operator <=(const _reverse_iterator & other) const { return e <= other.e;}
140  bool operator >=(const _reverse_iterator & other) const { return e >= other.e;}
141  operator void *()const {return static_cast<void *> (e);}
142  };
145  private:
146 
147  element * m_arr;
148  size_type m_size;
149 
150  //notice: push_back, pop_back, insert, erase are optimized for current growth_formula
151  __INLINE static size_type growth_formula(size_type future_size)
152  {
153  uenum v = static_cast<uenum>(future_size);
154  v--;
155  v|= (v>>1);
156  v|= (v>>2);
157  v|= (v>>4);
158  v|= (v>>8);
159  v|= (v>>16);
160  //TODO produces compiler warning
161  //if( sizeof(size_type) > 4 ) v|= (v>>32); //must be compile time brench
162  v++;
163  return static_cast<size_type>(v);
164  }
165  protected:
166  static element * realloc(element * ptr, size_type old_size, size_type new_size)
167  {
168  size_type gf = growth_formula(new_size);
169  if( gf != growth_formula(old_size) )
170  {
171  element * tmp = new element[gf];
172 #if defined(DEBUGMEM)
173  if( tmp == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
174 #endif
175  std::copy(ptr,ptr+std::min(old_size,new_size),tmp);
176  delete [] ptr;
177  ptr = tmp;
178  assert(ptr != NULL);
179  }
180  return ptr;
181  }
182  static element * alloc(size_type init_size)
183  {
184  element * tmp = new element[growth_formula(init_size)];
185 #if defined(DEBUGMEM)
186  if( tmp == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
187 #endif
188  assert(tmp != NULL);
189  return tmp;
190  }
191  static element * copy(const element * ibeg, const element * iend, element * obeg)
192  {
193  if (std::less<const element *>()(ibeg, obeg))
194  {
195  obeg += (iend - ibeg);
196  std::copy_backward(ibeg, iend, obeg);
197  return obeg;
198  } else return std::copy(ibeg, iend, obeg);
199  }
200  public:
201  __INLINE element * data() {return m_arr;}
202  __INLINE const element * data() const {return m_arr;}
203  array() {m_arr = NULL; m_size = 0;}
204  array(size_type n,element c = element())
205  {
206  m_size = n;
207  m_arr = alloc(n);
208  std::fill(m_arr,m_arr+m_size,c);
209  }
210  template<class InputIterator>
211  array(InputIterator first, InputIterator last)
212  {
213  m_size = static_cast<size_type>(std::distance(first,last));
214  m_arr = alloc(m_size);
215  std::copy(first,last,m_arr);
216  }
217  array(const array & other)
218  {
219  m_size = other.m_size;
220  if( m_size )
221  {
222  m_arr = alloc(m_size);
223  std::copy(other.m_arr,other.m_arr+other.m_size,m_arr);
224  }
225  else m_arr = NULL;
226  }
227  ~array() {clear();}
228  __INLINE const element & operator [] (size_type n) const
229  {
230  assert(n < m_size);
231  return m_arr[n];
232  }
233  __INLINE element & operator [] (size_type n)
234  {
235  assert(n < m_size);
236  return m_arr[n];
237  }
238  __INLINE const element & at (size_type n) const
239  {
240  assert(n < m_size);
241  return m_arr[n];
242  }
243  __INLINE element & at (size_type n)
244  {
245  assert(n < m_size);
246  return m_arr[n];
247  }
248  __INLINE element & at_safe (size_type n)
249  {
250  if( n >= m_size ) resize(n+1);
251  return m_arr[n];
252  }
253  array & operator =(array const & other)
254  {
255  if( this != &other )
256  {
257  if(m_arr != NULL )
258  clear();
259  if( other.m_arr != NULL )
260  {
261  m_size = other.m_size;
262  m_arr = alloc(m_size);
263  std::copy(other.m_arr,other.m_arr+other.m_size,m_arr);
264  }
265  }
266  return *this;
267  }
268  void push_back(const element & e)
269  {
270  m_arr = realloc(m_arr,m_size,m_size+1);
271  m_arr[m_size++] = e;
272  }
273  void pop_back()
274  {
275  assert(m_arr != NULL);
276  if( m_size > 0)
277  {
278  m_arr = realloc(m_arr,m_size,m_size-1);
279  m_size--;
280  }
281  else clear();
282  }
283  __INLINE element & back()
284  {
285  assert(m_arr != NULL);
286  assert(m_size > 0);
287  return m_arr[m_size-1];
288  }
289  __INLINE const element & back() const
290  {
291  assert(m_arr != NULL);
292  assert(m_size > 0);
293  return m_arr[m_size-1];
294  }
295  __INLINE element & front()
296  {
297  assert(m_arr != NULL);
298  assert(m_size > 0);
299  return m_arr[0];
300  }
301  __INLINE const element & front() const
302  {
303  assert(m_arr != NULL);
304  assert(m_size > 0);
305  return m_arr[0];
306  }
307  __INLINE size_type capacity() { return growth_formula(m_size); }
308  __INLINE bool empty() const { if( m_size ) return false; return true; }
309  void resize(size_type n, element c = element() )
310  {
311  size_type oldsize = m_size;
312  m_size = n;
313  if( m_size > 0 )
314  {
315  m_arr = realloc(m_arr,oldsize,m_size);
316  if( oldsize < m_size ) std::fill(m_arr+oldsize,m_arr+m_size,c);
317  }
318  else clear();
319  }
320  __INLINE size_type size() const {return m_size;}
321  __INLINE size_type capacity() const {return growth_formula(m_size);}
322  void clear()
323  {
324  if( m_arr ) delete [] m_arr;
325  m_arr = NULL;
326  m_size = 0;
327  }
328  void swap(array<element> & other)
329  {
330  element * t_m_arr = m_arr;
331  size_type t_m_size = m_size;
332  m_arr = other.m_arr;
333  m_size = other.m_size;
334  other.m_arr = t_m_arr;
335  other.m_size = t_m_size;
336  }
337  __INLINE iterator begin() { return m_arr; }
338  __INLINE iterator end() { return m_arr+m_size; }
339  __INLINE const_iterator begin() const { return m_arr; }
340  __INLINE const_iterator end() const { return m_arr+m_size; }
341  __INLINE reverse_iterator rbegin() { return reverse_iterator(m_arr+m_size-1); }
342  __INLINE reverse_iterator rend() { return reverse_iterator(m_arr-1); }
343  __INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator(m_arr+m_size-1); }
344  __INLINE const_reverse_iterator rend() const { return const_reverse_iterator(m_arr-1); }
345  iterator erase(iterator pos)
346  {
347  ptrdiff_t d = pos-begin();
348  ptrdiff_t s = iterator(m_arr+(m_size-1))-pos;
349  m_size--;
350  if( m_size > 0 )
351  {
352  if( s ) copy(m_arr+d+1, m_arr+d+1+s, m_arr+d);
353  m_arr = realloc(m_arr, m_size+1, m_size);
354  }
355  else clear();
356  return m_arr+d;
357  }
358  iterator erase(iterator b, iterator e)
359  {
360  ptrdiff_t d = b-begin();
361  ptrdiff_t s = end()-e;
362  ptrdiff_t n = e-b;
363  m_size -= n;
364  if( m_size > 0 )
365  {
366  if( s ) copy(m_arr+d+1,m_arr+d+1+s,m_arr+d);
367  m_arr = realloc(m_arr,m_size+n,m_size);
368 
369  }
370  else clear();
371  return m_arr+d;
372  }
373  iterator insert(iterator pos, const element & x)
374  {
375  if( static_cast<void *>(pos) == NULL)
376  {
377  assert(m_arr == NULL);
378  m_size = 1;
379  m_arr = alloc(m_size);
380  m_arr[0] = x;
381  return m_arr;
382  }
383  else
384  {
385  ptrdiff_t d = pos-begin();
386  ptrdiff_t s = end()-pos;
387  m_arr = realloc(m_arr,m_size,m_size+1);
388  if( s ) copy(m_arr+d,m_arr+d+s,m_arr+d+1);
389  m_arr[d] = x;
390  m_size++;
391  return m_arr+d;
392  }
393  }
394  void insert(iterator pos, size_type n, const element & x)
395  {
396  if( n > 0 )
397  {
398  if( static_cast<void *>(pos) == NULL)
399  {
400  assert(m_arr == NULL);
401  m_arr = alloc(n);
402  m_size = n;
403  std::fill(m_arr,m_arr+m_size,x);
404  }
405  else
406  {
407  ptrdiff_t d = pos-begin();
408  ptrdiff_t s = end()-pos;
409  m_arr = realloc(m_arr,m_size,m_size+n);
410  m_size += n;
411  if( s ) copy(m_arr+d,m_arr+d+s,m_arr+d+n);
412  std::fill(m_arr+d,m_arr+d+n,x);
413  }
414  }
415  }
416  template <class InputIterator>
417  void insert(iterator pos, InputIterator first, InputIterator last)
418  {
419  size_type n = static_cast<size_type>(std::distance(first,last));
420  if( n > 0 )
421  {
422  if( static_cast<void *>(pos) == NULL)
423  {
424  assert(m_arr == NULL);
425  m_arr = alloc(n);
426  m_size = n;
427  std::copy(first,last,m_arr);
428  }
429  else
430  {
431  ptrdiff_t d = pos-begin();
432  ptrdiff_t s = end()-pos;
433  m_arr = realloc(m_arr,m_size,m_size+n);
434  m_size += n;
435  if( s ) copy(m_arr+d,m_arr+d+s,m_arr+d+n);
436  std::copy(first,last,m_arr+d);
437  }
438  }
439  }
440  template <class InputIterator>
441  void replace(iterator m_first, iterator m_last, InputIterator first, InputIterator last)
442  {
443  assert( m_size >= 0 );
444  size_type n = static_cast<size_type>(std::distance(first,last));
445  if( static_cast<void *>(m_first) == NULL && m_arr == NULL)
446  {
447  assert(m_arr == NULL);
448  m_arr = alloc(n);
449  m_size = n;
450  std::copy(first,last,m_arr);
451  }
452  else
453  {
454  ptrdiff_t q = m_last-m_first;
455  ptrdiff_t d = m_first-iterator(m_arr);
456  ptrdiff_t s = iterator(m_arr+m_size)-m_last;
457  if( n-q != 0 )
458  {
459  m_arr = realloc(m_arr,m_size,m_size+static_cast<size_type>(n-q));
460  m_size+=static_cast<size_type>(n-q);
461  if( s ) copy(m_arr+d+q,m_arr+d+q+s,m_arr+d+n);
462  }
463  std::copy(first,last,m_arr+d);
464  }
465  }
466  template <class InputIterator>
467  void assign(InputIterator first, InputIterator last)
468  {
469  replace(begin(),end(),first,last);
470  }
471  template<class> friend class shell;
472  };
473 #if defined(PACK_ARRAY)
474 #pragma pack(pop,r1)
475 #endif
476  template<typename element>
477  class shell
478  {
479  public:
480  typedef typename array<element>::size_type size_type;
481  template<typename dtype>
482  class _iterator
483  {
484  private:
485  dtype * e;
486  public:
487  typedef dtype * pointer;
488  typedef dtype & reference;
489  typedef dtype value_type;
490  typedef ptrdiff_t difference_type;
491  typedef std::random_access_iterator_tag iterator_category;
492  _iterator():e(NULL){}
493  _iterator(dtype * i):e(i){}
494  _iterator(const _iterator & other){e = other.e;}
495  ~_iterator() {};
496  _iterator operator -(size_t n) const { return _iterator(e-n); }
497  _iterator & operator -=(size_t n) { e-=n; return *this; }
498  _iterator operator +(size_t n) const { return _iterator(e+n); }
499  _iterator & operator +=(size_t n) { e+=n; return *this; }
500  _iterator & operator ++(){ ++e; return *this;}
501  _iterator operator ++(int) { return _iterator(e++); }
502  _iterator & operator --(){ --e; return *this; }
503  _iterator operator --(int) { return _iterator(e--); }
504  ptrdiff_t operator -(const _iterator & other) const {return e-other.e;}
505  dtype & operator *() const { return *e; }
506  dtype * operator ->() const { return e; }
507  _iterator & operator =(_iterator const & other) { e = other.e; return *this; }
508  bool operator ==(const _iterator & other) const { return e == other.e;}
509  bool operator !=(const _iterator & other) const { return e != other.e;}
510  bool operator <(const _iterator & other) const { return e < other.e;}
511  bool operator >(const _iterator & other) const { return e > other.e;}
512  bool operator <=(const _iterator & other) const { return e <= other.e;}
513  bool operator >=(const _iterator & other) const { return e >= other.e;}
514  operator void *() const {return static_cast<void *> (e);}
515  };
518  template<typename dtype>
520  {
521  private:
522  dtype * e;
523  public:
524  typedef dtype * pointer;
525  typedef dtype & reference;
526  typedef dtype value_type;
527  typedef ptrdiff_t difference_type;
528  typedef std::random_access_iterator_tag iterator_category;
529  _reverse_iterator():e(NULL){}
530  _reverse_iterator(dtype * i):e(i){}
531  _reverse_iterator(const _reverse_iterator & other){e = other.e;}
532  ~_reverse_iterator() {};
533  _reverse_iterator operator -(size_t n) const { return _reverse_iterator(e+n); }
534  _reverse_iterator & operator -=(size_t n) { e+=n; return *this; }
535  _reverse_iterator operator +(size_t n) const {return _reverse_iterator(e-n); }
536  _reverse_iterator & operator +=(size_t n) { e-=n; return *this; }
537  _reverse_iterator & operator ++(){ --e; return *this;}
538  _reverse_iterator operator ++(int) { return _reverse_iterator(e--); }
539  _reverse_iterator & operator --(){ ++e; return *this; }
540  _reverse_iterator operator --(int) { return _reverse_iterator(e++); }
541  ptrdiff_t operator -(const _reverse_iterator & other) const {return other.e-e;}
542  dtype & operator *() const { return *e; }
543  dtype * operator ->() const { return e; }
544  _reverse_iterator & operator =(_reverse_iterator const & other) { e = other.e; return *this;}
545  bool operator ==(const _reverse_iterator & other) const { return e == other.e;}
546  bool operator !=(const _reverse_iterator & other) const { return e != other.e;}
547  bool operator <(const _reverse_iterator & other) const { return e < other.e;}
548  bool operator >(const _reverse_iterator & other) const { return e > other.e;}
549  bool operator <=(const _reverse_iterator & other) const { return e <= other.e;}
550  bool operator >=(const _reverse_iterator & other)const { return e >= other.e;}
551  operator void *() const {return static_cast<void *> (e);}
552  };
555  private:
556  element ** m_arr;
557  size_type * m_size;
558  element * local_link;
559  size_type local_size;
560  bool fixed;
561  public:
562  __INLINE element * data() {return *m_arr;}
563  __INLINE const element * data() const {return *m_arr;}
564  shell() :m_arr(NULL), m_size(NULL), local_link(NULL), local_size(0), fixed(false) { }
565  shell(array<element> & arr) //dynamic
566  :m_arr(&arr.m_arr), m_size(&arr.m_size), local_link(NULL), local_size(0), fixed(false) {}
567  shell(element * link, size_type size) //fixed
568  :m_arr(&local_link), m_size(&local_size), local_link(NULL),local_size(0), fixed(true)
569  {
570  *m_arr = link;
571  *m_size = size;
572  }
573  shell(const shell & other)
574  :m_arr(&local_link), m_size(&local_size), local_link(NULL), local_size(0),fixed(other.fixed)
575  {
576  if( fixed )
577  {
578  *m_size = *other.m_size;
579  *m_arr = *other.m_arr;
580  }
581  else
582  {
583  m_size = other.m_size;
584  m_arr = other.m_arr;
585  }
586  }
587  ~shell()
588  {
589  }
590  __INLINE const element & operator [] (size_type n) const
591  {
592  assert(n < *m_size );
593  return *((*m_arr)+n);
594  }
595  __INLINE element & operator [] (size_type n)
596  {
597  assert(n < *m_size );
598  return *((*m_arr)+n);
599  }
600  __INLINE const element & at (size_type n) const
601  {
602  assert(n < *m_size );
603  return *((*m_arr)+n);
604  }
605  __INLINE element & at (size_type n)
606  {
607  assert(n < *m_size );
608  return *((*m_arr)+n);
609  }
610  shell & operator =(shell const & other)
611  {
612  fixed = other.fixed;
613  if( fixed )
614  {
615  m_size = &local_size;
616  m_arr = &local_link;
617  *m_size = *other.m_size;
618  *m_arr = *other.m_arr;
619  }
620  else
621  {
622  m_size = other.m_size;
623  m_arr = other.m_arr;
624  }
625  return *this;
626  }
627  void push_back(const element & e)
628  {
629  assert( !fixed ); // array size is fixed
630  *m_arr = array<element>::realloc(*m_arr,*m_size,(*m_size)+1);
631  (*m_arr)[(*m_size)++] = e;
632  }
633  void pop_back()
634  {
635  assert( !fixed ); // array size is fixed
636  assert((*m_arr) != NULL);
637  if( *m_size > 0)
638  {
639  *m_arr = array<element>::realloc(*m_arr,*m_size,(*m_size)-1);
640  (*m_size)--;
641  }
642  else clear();
643  }
644  __INLINE element & back()
645  {
646  assert(*m_arr != NULL);
647  assert(*m_size > 0 );
648  return (*m_arr)[(*m_size)-1];
649  }
650  __INLINE const element & back() const
651  {
652  assert(*m_arr != NULL);
653  assert(*m_size > 0 );
654  return (*m_arr)[(*m_size)-1];
655  }
656  __INLINE element & front()
657  {
658  assert(*m_arr != NULL);
659  assert(*m_size > 0 );
660  return (*m_arr)[0];
661  }
662  __INLINE const element & front() const
663  {
664  assert(*m_arr != NULL);
665  assert(*m_size > 0 );
666  return (*m_arr)[0];
667  }
668  __INLINE size_type capacity() { return array<element>::growth_formula(*m_size); }
669  __INLINE bool empty() const { if( *m_size ) return false; return true; }
670  void resize(size_type n, element c = element() )
671  {
672  assert( !fixed ); // array size is fixed
673  size_type oldsize = *m_size;
674  *m_size = n;
675  if( *m_size > 0 )
676  {
677  *m_arr = array<element>::realloc(*m_arr,oldsize,*m_size);
678  if( oldsize < *m_size ) std::fill((*m_arr)+oldsize,(*m_arr)+(*m_size),c);
679  }
680  else clear();
681  }
682  __INLINE size_type size() const {return *m_size;}
683  void clear()
684  {
685  assert( !fixed ); // array size is fixed
686  if( *m_arr ) delete [] *m_arr;
687  *m_arr = NULL;
688  *m_size = 0;
689  }
690  void swap(shell<element> & other)
691  {
692  element * t_m_arr = *m_arr;
693  size_type t_m_size = *m_size;
694  *m_arr = *other.m_arr;
695  *m_size = *other.m_size;
696  *other.m_arr = t_m_arr;
697  *other.m_size = t_m_size;
698  }
699  __INLINE iterator begin() { return *m_arr; }
700  __INLINE iterator end() { return (*m_arr)+(*m_size); }
701  __INLINE const_iterator begin() const { return (*m_arr); }
702  __INLINE const_iterator end() const { return (*m_arr)+(*m_size); }
703  __INLINE reverse_iterator rbegin() { return reverse_iterator((*m_arr)+(*m_size)-1); }
704  __INLINE reverse_iterator rend() { return reverse_iterator((*m_arr)-1); }
705  __INLINE const_reverse_iterator rbegin() const { return const_reverse_iterator((*m_arr)+(*m_size)-1); }
706  __INLINE const_reverse_iterator rend() const { return const_reverse_iterator((*m_arr)-1); }
707  iterator erase(iterator pos)
708  {
709  assert( !fixed ); // array size is fixed
710  ptrdiff_t d = pos-begin();
711  ptrdiff_t s = iterator((*m_arr)+(*m_size)-1)-pos;
712  (*m_size)--;
713  if( *m_size > 0 )
714  {
715  if( s ) array<element>::copy((*m_arr)+d+1, (*m_arr)+d+1+s, (*m_arr)+d);
716  *m_arr = array<element>::realloc(*m_arr, (*m_size)+1, *m_size);
717  }
718  else clear();
719  return (*m_arr)+d;
720  }
721  iterator erase(iterator b, iterator e)
722  {
723  assert( !fixed ); // array size is fixed
724  ptrdiff_t d = b-begin();
725  ptrdiff_t s = end()-e;
726  ptrdiff_t n = e-b;
727  (*m_size) -= n;
728  if( *m_size > 0 )
729  {
730  if( s ) array<element>::copy((*m_arr)+d+1,(*m_arr)+d+1+s,(*m_arr)+d);
731  *m_arr = array<element>::realloc(*m_arr,(*m_size)+n,*m_size);
732 
733  }
734  else clear();
735  return (*m_arr)+d;
736  }
737  iterator insert(iterator pos, const element & x)
738  {
739  assert( !fixed ); // array size is fixed
740  if( static_cast<void *>(pos) == NULL )
741  {
742  assert((*m_arr) == NULL);
743  *m_size = 1;
744  *m_arr = array<element>::alloc(*m_size);
745  (*m_arr)[0] = x;
746  return *m_arr;
747  }
748  else
749  {
750  ptrdiff_t d = pos-begin();
751  ptrdiff_t s = end()-pos;
752  *m_arr = array<element>::realloc(*m_arr,*m_size,(*m_size)+1);
753  (*m_size)++;
754  if( s ) array<element>::copy((*m_arr)+d,(*m_arr)+d+s,(*m_arr)+d+1);
755  (*m_arr)[d] = x;
756  return (*m_arr)+d;
757  }
758  }
759  void insert(iterator pos, size_type n, const element & x)
760  {
761  assert( !fixed ); // array size is fixed
762  if( n )
763  {
764  if( static_cast<void *>(pos) == NULL)
765  {
766  assert((*m_arr) == NULL);
767  *m_arr = array<element>::alloc(n);
768  *m_size = n;
769  std::fill(*m_arr,(*m_arr)+(*m_size),x);
770  }
771  else
772  {
773  ptrdiff_t d = pos-iterator(*m_arr);
774  ptrdiff_t s = iterator((*m_arr)+(*m_size))-pos;
775  *m_arr = array<element>::realloc(*m_arr,*m_size,(*m_size)+n);
776  *m_size += n;
777  if( s ) array<element>::copy((*m_arr)+d,(*m_arr)+d+s,(*m_arr)+d+n);
778  std::fill((*m_arr)+d,(*m_arr)+d+n,x);
779  }
780  }
781  }
782  template <class InputIterator>
783  void insert(iterator pos, InputIterator first, InputIterator last)
784  {
785  assert( !fixed ); // array size is fixed
786  size_type n = static_cast<size_type>(std::distance(first,last));
787  if( n )
788  {
789  if( static_cast<void *>(pos) == NULL)
790  {
791  assert((*m_arr) == NULL);
792  *m_arr = array<element>::alloc(n);
793  *m_size = n;
794  std::copy(first,last,*m_arr);
795  }
796  else
797  {
798  ptrdiff_t d = pos-iterator(*m_arr);
799  ptrdiff_t s = iterator((*m_arr)+(*m_size))-pos;
800  *m_arr = array<element>::realloc(*m_arr,*m_size,(*m_size)+n);
801  *m_size += n;
802  if( s ) array<element>::copy((*m_arr)+d,(*m_arr)+d+s,(*m_arr)+d+n);
803  std::copy(first,last,(*m_arr)+d);
804  }
805  }
806  }
807  template <class InputIterator>
808  void replace(iterator m_first, iterator m_last, InputIterator first, InputIterator last)
809  {
810  size_type n = static_cast<size_type>(std::distance(first,last));
811  if( static_cast<void *>(m_first) == NULL)
812  {
813  assert((*m_arr)==NULL);
814  *m_arr = array<element>::alloc(n);
815  *m_size = n;
816  std::copy(first,last,*m_arr);
817  }
818  else
819  {
820  ptrdiff_t q = m_last-m_first;
821  ptrdiff_t d = m_first-iterator(*m_arr);
822  ptrdiff_t s = iterator((*m_arr)+(*m_size))-m_last;
823  if( n-q != 0 )
824  {
825  *m_arr = array<element>::realloc(*m_arr,*m_size,(*m_size)+static_cast<size_type>(n-q));
826  (*m_size)+=static_cast<size_type>(n-q);
827  if( s ) array<element>::copy((*m_arr)+d+q,(*m_arr)+d+q+s,(*m_arr)+d+n);
828  }
829  std::copy(first,last,(*m_arr)+d);
830  }
831  }
832  template <class InputIterator>
833  void assign(InputIterator first, InputIterator last)
834  {
835  replace(begin(),end(),first,last);
836  }
837  };
838 
839  template<typename IndType,typename ValType>
840  class interval
841  {
842  public:
843  typedef ValType * iterator;
844  typedef ValType const * const_iterator;
845  private:
846  ValType * parray;
847  IndType beg_index, end_index;
848  public:
849  void clear()
850  {
851  if (!empty()) delete [] (parray + beg_index);
852  parray = NULL;
853  end_index = beg_index;
854  }
855  void swap(interval<IndType, ValType> & other)
856  {
857  {
858  IndType tmp = beg_index;
859  beg_index = other.beg_index;
860  other.beg_index = tmp;
861  tmp = end_index;
862  end_index = other.end_index;
863  other.end_index = tmp;
864  }
865  {
866  ValType * tmp = parray;
867  parray = other.parray;
868  other.parray = tmp;
869  }
870  }
871  interval()
872  {
873  beg_index = 0;
874  end_index = 0;
875  parray = NULL;
876  }
877  interval(IndType beg)
878  {
879  beg_index = beg;
880  end_index = beg_index;
881  parray = NULL;
882  }
883  interval(IndType beg, IndType end, ValType c = ValType())
884  {
885  beg_index = beg;
886  end_index = end;
887  if (beg != end)
888  {
889  ValType * tmp = new ValType[end_index-beg_index];
890 #if defined(DEBUGMEM)
891  if( tmp == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
892 #endif
893  parray = tmp;
894  assert(parray != NULL);
895  parray = parray - beg_index;
896  std::fill(parray+beg_index,parray+end_index,c);
897  }
898  else parray = NULL;
899  }
900  interval(const interval & other)
901  {
902  beg_index = other.beg_index;
903  end_index = other.end_index;
904  if( beg_index != end_index )
905  {
906  ValType * tmp = new ValType[end_index-beg_index];
907 #if defined(DEBUGMEM)
908  if( tmp == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
909 #endif
910  parray = static_cast<ValType *>(tmp);
911  assert(parray != NULL);
912  parray = parray - beg_index;
913  std::copy(other.parray+beg_index,other.parray+end_index,parray+beg_index);
914  }
915  else parray = NULL;
916  }
917  ~interval()
918  {
919  clear();
920  }
921  interval & operator =(interval const & other)
922  {
923  if( &other != this )
924  {
925  clear();
926  beg_index = other.beg_index;
927  end_index = other.end_index;
928  if( beg_index != end_index )
929  {
930  ValType * tmp = new ValType[end_index-beg_index];
931 #if defined(DEBUGMEM)
932  if( tmp == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
933 #endif
934  parray = static_cast<ValType *>(tmp);
935  assert(parray != NULL);
936  parray = parray - beg_index;
937  std::copy(other.parray+beg_index,other.parray+end_index,parray+beg_index);
938  }
939  }
940  return *this;
941  }
942  ValType & at(IndType row)
943  {
944  assert(row >= beg_index);
945  assert(row < end_index);
946  return parray[row];
947  }
948  const ValType & at(IndType row) const
949  {
950  assert(row >= beg_index);
951  assert(row < end_index);
952  return parray[row];
953  }
954  ValType & operator [](IndType row)
955  {
956  assert(row >= beg_index );
957  assert(row < end_index );
958  return parray[row];
959  }
960  const ValType & operator [](IndType row) const
961  {
962  assert(row >= beg_index );
963  assert(row < end_index );
964  return parray[row];
965  }
966  void set_interval_beg(IndType beg)
967  {
968  IndType shift = beg-beg_index;
969  shift_interval(shift);
970  }
971  void set_interval_end(IndType end, const ValType & c = ValType())
972  {
973  if( end == end_index ) return;
974  if( beg_index != end )
975  {
976  ValType * parray_new = new ValType[end-beg_index];
977 #if defined(DEBUGMEM)
978  if( parray_new == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
979 #endif
980  assert(parray_new != NULL);
981  parray_new = parray_new - beg_index;
982  //IndType mbeg = beg_index;
983  IndType mend = std::min(end,end_index);
984  if( !empty() )
985  {
986  //~ std::cout << beg_index << ":" << end_index << " new end " << end << " old ptr " << (void*)parray << " new ptr " << (void *)parray_new << std::endl;
987  std::copy(parray+beg_index,parray+mend,parray_new+beg_index);
988  clear();
989  }
990  if( mend < end ) std::fill(parray_new+mend,parray_new+end,c);
991  parray = parray_new;
992  }
993  else clear();
994  end_index = end;
995  }
996 
997  void shift_interval(IndType shift)
998  {
999  parray = parray + beg_index;
1000  beg_index += shift;
1001  end_index += shift;
1002  parray = parray - beg_index;
1003  }
1004  iterator begin() {return parray+beg_index;}
1005  const_iterator begin() const {return parray+beg_index;}
1006  iterator end() {return parray + end_index;}
1007  const_iterator end() const {return parray + end_index;}
1008  IndType get_interval_beg() const { return beg_index; }
1009  IndType get_interval_end() const { return end_index; }
1010  int size() const {return end_index - beg_index;}
1011  bool empty() const {return beg_index == end_index;}
1012  };
1013  //this is supposed to provide thread-safe storage type for chunks in chunk_array
1014  //the idea is that pointer to block is never moved
1015  //so that access to any entry before size() is correct on resize
1016  //critical section is required on resize()
1017  template<typename element, size_t base = 512>
1019  {
1020  element e[base]; //storage of current node
1021  size_t ne; //number of elements in array
1022  linked_array * next; //link to next node
1023  linked_array(const linked_array & b) {} //don't copy me
1024  linked_array & operator = (linked_array const & b) { return *this; } //don't copy me
1025  public:
1026  linked_array() : ne(0), next(NULL) {}
1027  void clear()
1028  {
1029  if (next)
1030  {
1031  next->clear();
1032  delete next;
1033  next = NULL;
1034  }
1035  ne = 0;
1036  }
1037  element & operator [](size_t n)
1038  {
1039  if (n < base)
1040  {
1041  assert(n < ne);
1042  return e[n];
1043  }
1044  else
1045  {
1046  assert(next);
1047  return next->operator [](n-base);
1048  }
1049  }
1050  const element & operator [](size_t n) const
1051  {
1052  if (n < base)
1053  {
1054  assert(n < ne);
1055  return e[n];
1056  }
1057  else
1058  {
1059  assert(next);
1060  return next->operator [](n - base);
1061  }
1062  }
1063  size_t size() const
1064  {
1065  if( ne == base && next )
1066  return base+next()->size();
1067  else
1068  return ne;
1069  }
1070  void resize(size_t new_n, const element & c = element())
1071  {
1072  if (new_n <= base)
1073  {
1074  for (size_t k = ne; k < new_n; ++k)
1075  e[k] = c;
1076  ne = new_n;
1077  if (next)
1078  {
1079  next->clear();
1080  delete next;
1081  next = NULL;
1082  }
1083  }
1084  else
1085  {
1086  if( !next )
1087  next = new linked_array;
1088  if (ne < base)
1089  {
1090  for (size_t k = ne; k < base; ++k)
1091  e[k] = c;
1092  ne = base;
1093  }
1094  next->resize(new_n-base,c);
1095  }
1096  }
1097  ~linked_array() {clear();}
1098  };
1099 
1100  template<typename element, int block_bits>
1102  {
1103  public:
1104  typedef size_t size_type; //need signed type for reverse iterator? (reverse iterators commented)
1105  typedef make_unsigned<size_type>::type uenum; //this is required for right bit shifts not to create leading 1s
1106  private:
1107  static size_type const block_bits_mask = (1 << (block_bits)) - 1;
1108  static size_type const block_val = 1 << block_bits;
1109  static size_type const block_size = sizeof(element)*block_val;
1110  static size_type const fwd_alloc_chunk_bits = 6;
1111  static size_type const fwd_alloc_chunk_bits_mask = (1 << (fwd_alloc_chunk_bits))-1;
1112  static size_type const fwd_alloc_chunk_val = 1 << fwd_alloc_chunk_bits;
1113  static size_type const fwd_alloc_chunk_size = sizeof(element *)*fwd_alloc_chunk_val;
1114 
1115  linked_array<element *> chunks;
1116 
1117 
1118  size_type m_size;
1119  //This needs static_cast to unsigned to
1120  __INLINE size_type GetChunkNumber(size_type k) const {return static_cast<uenum>(k) >> block_bits;}
1121  __INLINE size_type GetElementNumber(size_type k) const {return (k & block_bits_mask);}
1122  __INLINE element * access_block(size_type k) {return chunks[GetChunkNumber(k)];}
1123  __INLINE const element * access_block(size_type k) const {return chunks[GetChunkNumber(k)];}
1124  __INLINE element & access_element(size_type k) {return access_block(k)[GetElementNumber(k)];}
1125  __INLINE const element & access_element(size_type k) const {return access_block(k)[GetElementNumber(k)];}
1126  public:
1127  __INLINE element & operator [] (size_type i)
1128  {
1129  assert(i < size());
1130  return access_element(i);
1131  }
1132  __INLINE const element & operator [] (size_type i) const
1133  {
1134  assert(i < size());
1135  return access_element(i);
1136  }
1137  __INLINE element & at(size_type i)
1138  {
1139  assert(i < size());
1140  return access_element(i);
1141  }
1142  __INLINE const element & at(size_type i) const
1143  {
1144  assert(i < size());
1145  return access_element(i);
1146  }
1147 
1148 
1149 
1150 
1151  class iterator
1152  {
1153  private:
1155  size_type pos;
1156  public:
1157  typedef element * pointer;
1158  typedef element & reference;
1159  typedef element value_type;
1160  typedef ptrdiff_t difference_type;
1161  typedef std::random_access_iterator_tag iterator_category;
1162  iterator(){pos = 0; link = NULL;}
1163  iterator(chunk_array<element,block_bits> * c, size_type pos):link(c),pos(pos){}
1164  iterator(const iterator & other){link = other.link; pos = other.pos;}
1165  ~iterator() {};
1166  iterator operator -(size_type n) const { return iterator(link,pos-n); }
1167  iterator & operator -=(size_type n) { pos-=n; return *this; }
1168  iterator operator +(size_type n) const { return iterator(link,pos+n); }
1169  iterator & operator +=(size_type n) { pos+=n; return *this; }
1170  iterator & operator ++(){ ++pos; return *this;}
1171  iterator operator ++(int) { return iterator(link,pos++); }
1172  iterator & operator --(){ --pos; return *this; }
1173  iterator operator --(int) { return iterator(link,pos--); }
1174  ptrdiff_t operator -(const iterator & other) const {return pos-other.pos;}
1175  element & operator *() const { return link->at(pos); }
1176  element * operator ->() const { return &link->at(pos); }
1177  iterator & operator =(iterator const & other) { link = other.link; pos = other.pos; return *this; }
1178  bool operator ==(const iterator & other) const { assert(link == other.link); return pos == other.pos;}
1179  bool operator !=(const iterator & other) const { assert(link == other.link); return pos != other.pos;}
1180  bool operator <(const iterator & other) const { assert(link == other.link); return pos < other.pos;}
1181  bool operator >(const iterator & other) const { assert(link == other.link); return pos > other.pos;}
1182  bool operator <=(const iterator & other) const { assert(link == other.link); return pos <= other.pos;}
1183  bool operator >=(const iterator & other) const { assert(link == other.link); return pos >= other.pos;}
1184  };
1185 
1187  {
1188  private:
1189  const chunk_array<element,block_bits> * const link;
1190  size_type pos;
1191  public:
1192  typedef element * pointer;
1193  typedef element & reference;
1194  typedef element value_type;
1195  typedef ptrdiff_t difference_type;
1196  typedef std::random_access_iterator_tag iterator_category;
1197  const_iterator(){pos = 0; link = NULL;}
1198  const_iterator(const chunk_array<element,block_bits> * c, size_type pos):link(c),pos(pos){}
1199  const_iterator(const const_iterator & other) :link(other.link) {pos = other.pos;}
1200  ~const_iterator() {};
1201  const_iterator operator -(size_type n) const { return const_iterator(link,pos-n); }
1202  const_iterator & operator -=(size_type n) { pos-=n; return *this; }
1203  const_iterator operator +(size_type n) const { return const_iterator(link,pos+n); }
1204  const_iterator & operator +=(size_type n) { pos+=n; return *this; }
1205  const_iterator & operator ++(){ ++pos; return *this;}
1206  const_iterator operator ++(int) { return const_iterator(link,pos++); }
1207  const_iterator & operator --(){ --pos; return *this; }
1208  const_iterator operator --(int) { return const_iterator(link,pos--); }
1209  ptrdiff_t operator -(const const_iterator & other) const {return pos-other.pos;}
1210  const element & operator *() const { return link->at(pos); }
1211  const element * operator ->() const { return &link->at(pos); }
1212  const_iterator & operator =(const_iterator const & other) { link = other.link; pos = other.pos; return *this; }
1213  bool operator ==(const const_iterator & other) const { assert(link == other.link); return pos == other.pos;}
1214  bool operator !=(const const_iterator & other) const { assert(link == other.link); return pos != other.pos;}
1215  bool operator <(const const_iterator & other) const { assert(link == other.link); return pos < other.pos;}
1216  bool operator >(const const_iterator & other) const { assert(link == other.link); return pos > other.pos;}
1217  bool operator <=(const const_iterator & other) const { assert(link == other.link); return pos <= other.pos;}
1218  bool operator >=(const const_iterator & other) const { assert(link == other.link); return pos >= other.pos;}
1219  };
1220 
1221  void inner_resize(size_type new_size)
1222  {
1223  size_type oldnchunks2 = (static_cast<uenum>(m_size) >> block_bits) + ( (m_size & block_bits_mask) ? 1 : 0);
1224  size_type oldn = (static_cast<uenum>(oldnchunks2) >> fwd_alloc_chunk_bits) + ( (oldnchunks2 & fwd_alloc_chunk_bits_mask) ? 1 : 0);
1225  size_type newnchunks2 = (static_cast<uenum>(new_size) >> block_bits) + ( (new_size & block_bits_mask)? 1 : 0);
1226  size_type newn = (static_cast<uenum>(newnchunks2) >> fwd_alloc_chunk_bits) + ( (newnchunks2 & fwd_alloc_chunk_bits_mask) ? 1 : 0);
1227  for(size_type q = newnchunks2; q < oldnchunks2; q++)
1228  {
1229  assert(chunks[q] != NULL);
1230  delete [] chunks[q];
1231  chunks[q] = NULL;
1232  }
1233  if( newn != oldn )
1234  {
1235  if( newn > 0 )
1236  chunks.resize(fwd_alloc_chunk_size*newn);
1237  else
1238  chunks.clear();
1239  }
1240  for(size_type q = oldnchunks2; q < newnchunks2; q++)
1241  {
1242  assert(chunks[q] == NULL);
1243  chunks[q] = new element[block_size/sizeof(element)];//(element *)malloc(block_size);
1244 #if defined(DEBUGMEM)
1245  if( chunks[q] == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
1246 #endif
1247  assert(chunks[q] != NULL);
1248  }
1249  //for(size_type q = m_size; q < new_size; q++) new (&access_element(q)) element();
1250  }
1251  public:
1252 
1253  size_type capacity() const
1254  {
1255  size_type chunks = ((static_cast<uenum>(m_size)>>block_bits) + ((m_size & block_bits_mask)? 1 : 0));
1256  return chunks*block_val;
1257  }
1258  size_type size() const {return m_size;}
1259  bool empty() const {return size() == 0;}
1260  void clear()
1261  {
1262  size_type cend = (static_cast<uenum>(m_size) >> block_bits) + ((m_size & block_bits_mask)? 1 : 0);
1263  for(size_type q = 0; q < cend; q++)
1264  {
1265  //free(chunks[q]);
1266  delete [] chunks[q];
1267  chunks[q] = NULL;
1268  }
1269  chunks.clear();
1270  m_size = 0;
1271  }
1272  chunk_array()
1273  {
1274  m_size = 0;
1275  }
1276  chunk_array(const chunk_array & other)
1277  {
1278  m_size = 0;
1279  inner_resize(other.size());
1280  for(size_type k = 0; k < other.size(); k++)
1281  new(&access_element(k)) element(other.access_element(k));
1282  m_size = other.size();
1283  }
1284  chunk_array & operator =(chunk_array const & other)
1285  {
1286  if( this != &other )
1287  {
1288  clear();
1289  inner_resize(other.size());
1290  for(size_type k = 0; k < other.size(); k++)
1291  access_element(k) = other.access_element(k);
1292  m_size = other.size();
1293  }
1294  return *this;
1295  }
1296  ~chunk_array()
1297  {
1298  clear();
1299  }
1300 
1301  element & front() { assert(!empty()); return access_element(0);}
1302  element & back() { assert(!empty()); return access_element(size()-1);}
1303  const element & front() const { assert(!empty()); return access_element(0);}
1304  const element & back() const { assert(!empty()); return access_element(size()-1);}
1305  void pop_back()
1306  {
1307  assert(!empty());
1308  inner_resize(m_size-1);
1309  m_size--;
1310  }
1311  void push_back(const element & e)
1312  {
1313  inner_resize(m_size+1);
1314  access_element(m_size) = e;
1315  m_size++;
1316  }
1317  void resize(size_type n, const element & e = element())
1318  {
1319  inner_resize(n);
1320  for(size_type k = m_size; k < n; k++)
1321  access_element(k) = element(e);
1322  m_size = n;
1323  }
1324 
1325  iterator erase(iterator pos)
1326  {
1327  iterator it = pos, jt = it++;
1328  while(it != end()) (*jt++) = (*it++);
1329  inner_resize(m_size-1);
1330  m_size--;
1331  return pos;
1332  }
1333 
1334  iterator begin() {return iterator(this,0);}
1335  iterator end() {return iterator(this,m_size);}
1336 
1337  const_iterator begin() const {return const_iterator(this,0);}
1338  const_iterator end() const {return const_iterator(this,m_size);}
1339  };
1340 
1341 
1342  template<int block_bits>
1344  {
1345  public:
1346  typedef size_t size_type;
1347  typedef make_unsigned<size_type>::type uenum; //this is required for right shift not to create leading 1s
1348  private:
1349  static size_type const block_bits_mask = (1 << (block_bits)) - 1;
1350  static size_type const block_val = 1 << block_bits;
1351  static size_type const block_size = sizeof(char)*block_val;
1352  static size_type const fwd_alloc_chunk_bits = 6;
1353  static size_type const fwd_alloc_chunk_bits_mask = (1 << (fwd_alloc_chunk_bits))-1;
1354  static size_type const fwd_alloc_chunk_val = 1 << fwd_alloc_chunk_bits;
1355  static size_type const fwd_alloc_chunk_size = sizeof(char *)*fwd_alloc_chunk_val;
1356  linked_array<char *> chunks;
1357 
1358  size_type record_size;
1359  size_type m_size;
1360 
1361  __INLINE size_type GetChunkNumber(size_type k) const {return static_cast<uenum>(k) >> block_bits;}
1362  __INLINE size_type GetElementNumber(size_type k) const {return (k & block_bits_mask) * record_size;}
1363  __INLINE char * access_block(size_type k) {return chunks[GetChunkNumber(k)];}
1364  __INLINE const char * access_block(size_type k) const {return chunks[GetChunkNumber(k)];}
1365  __INLINE char & access_element(size_type k) {return access_block(k)[GetElementNumber(k)];}
1366  __INLINE const char & access_element(size_type k) const {return access_block(k)[GetElementNumber(k)];}
1367  public:
1368  __INLINE char & operator [] (size_type i)
1369  {
1370  assert(i < size());
1371  return access_element(i);
1372  }
1373  __INLINE const char & operator [] (size_type i) const
1374  {
1375  assert(i < size());
1376  return access_element(i);
1377  }
1378  __INLINE char & at(size_type i)
1379  {
1380  assert(i < size());
1381  return access_element(i);
1382  }
1383  __INLINE const char & at(size_type i) const
1384  {
1385  assert(i < size());
1386  return access_element(i);
1387  }
1388  void inner_resize(size_type new_size)
1389  {
1390  size_type oldnchunks2 = (static_cast<uenum>(m_size) >> block_bits) + ( (m_size & block_bits_mask) ? 1 : 0);
1391  size_type oldn = (static_cast<uenum>(oldnchunks2) >> fwd_alloc_chunk_bits) + ( (oldnchunks2 & fwd_alloc_chunk_bits_mask) ? 1 : 0);
1392  size_type newnchunks2 = (static_cast<uenum>(new_size) >> block_bits) + ( (new_size & block_bits_mask)? 1 : 0);
1393  size_type newn = (static_cast<uenum>(newnchunks2) >> fwd_alloc_chunk_bits) + ( (newnchunks2 & fwd_alloc_chunk_bits_mask) ? 1 : 0);
1394  for(size_type q = newnchunks2; q < oldnchunks2; q++)
1395  {
1396  assert(chunks[q] != NULL);
1397  //free(chunks[q]);
1398  delete [] chunks[q];
1399  chunks[q] = NULL;
1400  }
1401  if( newn != oldn )
1402  {
1403  if( newn > 0 )
1404  chunks.resize(fwd_alloc_chunk_size*newn);
1405  else
1406  chunks.clear();
1407  }
1408  for(size_type q = oldnchunks2; q < newnchunks2; q++)
1409  {
1410  assert(chunks[q] == NULL);
1411  chunks[q] = new char[block_size*record_size];//static_cast<char *>(malloc(block_size*record_size));
1412 #if defined(DEBUGMEM)
1413  if( chunks[q] == NULL ) {std::cout << __FILE__ << ":" << __LINE__ << "allocation returns NULL\n";}
1414 #endif
1415  assert(chunks[q] != NULL);
1416  std::fill(chunks[q],chunks[q]+block_size*record_size,char());
1417  //memset(chunks[q],0,block_size*record_size);
1418  }
1419  }
1420  public:
1421 
1422  size_type capacity() const
1423  {
1424  size_type nchunks = ((static_cast<uenum>(m_size)>>block_bits) + ((m_size & block_bits_mask)? 1 : 0));
1425  return nchunks*block_val*record_size;
1426  }
1427  size_type size() const {return m_size;}
1428  bool empty() const {return size() == 0;}
1429  void clear()
1430  {
1431  size_type nchunks = ((static_cast<uenum>(m_size)>>block_bits) + ((m_size & block_bits_mask)? 1 : 0));
1432  for(size_type q = 0; q < nchunks; q++)
1433  {
1434  //free(chunks[q]);
1435  delete [] chunks[q];
1436  chunks[q] = NULL;
1437  }
1438  chunks.clear();
1439  m_size = 0;
1440  }
1441  chunk_bulk_array(size_type set_record_size = 1)
1442  {
1443  record_size = set_record_size;
1444  m_size = 0;
1445  }
1446  chunk_bulk_array(const chunk_bulk_array & other)
1447  {
1448  record_size = other.record_size;
1449  m_size = 0;
1450  inner_resize(other.size());
1451  size_type nchunks = ((static_cast<uenum>(m_size)>>block_bits) + ((m_size & block_bits_mask)? 1 : 0));
1452  for(size_type k = 0; k < nchunks; k++) memcpy(chunks[k],other.chunks[k],block_size*record_size);
1453  m_size = other.size();
1454  }
1455  chunk_bulk_array & operator =(chunk_bulk_array const & other)
1456  {
1457  if( this != &other )
1458  {
1459  clear();
1460  record_size = other.record_size;
1461  inner_resize(other.size());
1462  size_type nchunks = ((static_cast<uenum>(m_size)>>block_bits) + ((m_size & block_bits_mask)? 1 : 0));
1463  for(size_type k = 0; k < nchunks; k++) memcpy(chunks[k],other.chunks[k],block_size*record_size);
1464  m_size = other.size();
1465  }
1466  return *this;
1467  }
1468  ~chunk_bulk_array() {clear();}
1469  void resize(size_type n)
1470  {
1471  inner_resize(n);
1472  m_size = n;
1473  }
1474  };
1475 
1476 
1477 #define PADDING_SIZE 4096
1478  template<typename T>
1480  {
1481  T item;
1482  char padding[PADDING_SIZE-sizeof(T)];
1483  thread_private_item() :item() {memset(padding, 0, PADDING_SIZE - sizeof(T));}
1484  thread_private_item(const thread_private_item & b) :item(b.item){}
1485  thread_private_item & operator =(thread_private_item const & b)
1486  {
1487  item = b.item;
1488  return *this;
1489  }
1490  };
1491 
1492 #if defined(_OPENMP)
1495  template<typename T>
1496  class thread_private
1497  {
1498  //std::vector< thread_private_item<T> > items;
1499  //T * items;
1500  thread_private_item<T> * items;
1501  public:
1502  thread_private()
1503  {
1504  //std::cout << "constructor " << this << std::endl;
1505  items = new thread_private_item<T>[omp_get_max_threads()];
1506  //for(int k = 0; k < omp_get_max_threads(); ++k)
1507  //{
1508  // std::cout << (void *)&items[k] << std::endl;
1509  //}
1510  }
1511  thread_private(const T & b)
1512  {
1513  //std::cout << "T copy constructor " << this << std::endl;
1514  items = new thread_private_item<T>[omp_get_max_threads()];
1515  for(int k = 0; k < omp_get_max_threads(); ++k)
1516  items[k].item = b;
1517  }
1518  thread_private(const thread_private & b)
1519  {
1520  //std::cout << "copy constructor " << this << std::endl;
1521  items = new thread_private_item<T>[omp_get_max_threads()];
1522  for(int k = 0; k < omp_get_max_threads(); ++k)
1523  items[k].item = b.get(k);
1524  }
1525  ~thread_private()
1526  {
1527  //std::cout << "destructor " << this << std::endl;
1528  delete[] items;
1529  }
1530  thread_private & operator =(thread_private const & b)
1531  {
1532  if( omp_in_parallel() )
1533  {
1534  items[omp_get_thread_num()].item = b.get();
1535  }
1536  else
1537  {
1538 #pragma omp parallel
1539  items[omp_get_thread_num()].item = b.get();
1540  }
1541  return *this;
1542  }
1543  T & operator *() {return items[omp_get_thread_num()].item;}
1544  const T & operator *() const {return items[omp_get_thread_num()].item;}
1545  //operator T & () {return items[omp_get_thread_num()].item;}
1546  //operator const T & () const {return items[omp_get_thread_num()].item;}
1547  //operator T () {return items[omp_get_thread_num()].item;}
1548  //operator T () const {return items[omp_get_thread_num()].item;}
1549  //template <typename B>
1550  //T & operator = (B const & b) {items[omp_get_thread_num()].item = b; return items[omp_get_thread_num()].item;}
1551  //template <typename B>
1552  //T & operator += (B const & b) {items[omp_get_thread_num()].item += b; return items[omp_get_thread_num()].item;}
1553  //template <typename B>
1554  //T & operator -= (B const & b) {items[omp_get_thread_num()].item -= b; return items[omp_get_thread_num()].item;}
1555  //template <typename B>
1556  //T & operator *= (B const & b) {items[omp_get_thread_num()].item *= b; return items[omp_get_thread_num()].item;}
1557  //template <typename B>
1558  //T & operator /= (B const & b) {items[omp_get_thread_num()].item /= b; return items[omp_get_thread_num()].item;}
1559  T & get() {return items[omp_get_thread_num()].item;}
1560  const T & get() const {return items[omp_get_thread_num()].item;}
1561  T & get(int k) {return items[k].item;}
1562  const T & get(int k) const {return items[k].item;}
1563  T * operator ->() {return &items[omp_get_thread_num()].item;}
1564  const T * operator ->() const {return &items[omp_get_thread_num()].item;}
1565  };
1566 #else //_OPENMP
1567  template<typename T>
1569  {
1570  //T* item;
1571  thread_private_item<T> * item;
1572  public:
1573  thread_private()
1574  {
1575  item = new thread_private_item<T>;
1576  }
1577  ~thread_private()
1578  {
1579  delete item;
1580  }
1581  thread_private(const T & b)
1582  {
1583  item = new thread_private_item<T>;
1584  item->item = b;
1585  }
1586  thread_private(const thread_private & b)
1587  {
1588  item = new thread_private_item<T>;
1589  item->item = b.get();
1590  }
1591  thread_private & operator = (thread_private const & b)
1592  {
1593  item = new thread_private_item<T>;
1594  item->item = b.get();
1595  return *this;
1596  }
1597  T & operator *() {return item->item;}
1598  const T & operator *() const {return item->item;}
1599  //operator T & () {return item->item;}
1600  //operator const T & () const {return item->item;}
1601  //operator T () {return item->item;}
1602  //operator T () const {return item->item;}
1603  //template <typename B>
1604  //T & operator = (B const & b) {item->item = b; return item->item;}
1605  //template <typename B>
1606  //T & operator += (B const & b) {item->item += b; return item->item;}
1607  //template <typename B>
1608  //T & operator -= (B const & b) {item->item -= b; return item->item;}
1609  //template <typename B>
1610  //T & operator *= (B const & b) {item->item *= b; return item->item;}
1611  //template <typename B>
1612  //T & operator /= (B const & b) {item->item /= b; return item->item;}
1613  T & get() {return item->item;}
1614  const T & get() const {return item->item;}
1615  T & get(int k) {return item->item;}
1616  const T & get(int k) const {return item->item;}
1617  T * operator ->() {return &(item->item);}
1618  const T * operator ->() const {return &(item->item);}
1619  };
1620 #endif //_OPENMP
1621 }
1622 
1623 #endif