cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
container_classes.h
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2022 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 
4 #ifndef CONTAINER_CLASSES_H_
5 #define CONTAINER_CLASSES_H_
6 
7 void do_dump_state(const void* buf, size_t nelem, size_t size, FILE* out, int32 magic);
8 void do_restore_state(void* buf, size_t nelem, size_t size, FILE *in, int32 magic);
9 
16 
17 // magic numbers to identify each memory layout
18 static const int32 MA_VERS[ML_TOP] = { 120070905, 220070803, 320071126 };
19 
20 #ifdef USE_C_TYPE
21 #define MEM_LAYOUT_VAL C_TYPE
22 #else
23 #define MEM_LAYOUT_VAL ARPA_TYPE
24 #endif
25 
28 template<class T, bool lgBC>
30 {
31  static const int p_nd = lgBC ? 3 : 1;
32  T* p_p[p_nd]; // p[0] current pointer, p[1] lower bound, p[2] upper bound
33 
34  T* p_index_checked ( const ptrdiff_t n ) const
35  {
36  T* t = p_p[0]+n;
37 #ifdef _MSC_VER
38  /* disable warning that conditional expression is constant, true or false in if */
39 # pragma warning( disable : 4127 )
40 #endif
41  if( lgBC )
42  {
43  if( t < p_p[1] || t >= p_p[2] )
44  OUT_OF_RANGE( "basic_pntr::p_index_checked()" );
45  }
46  return t;
47  }
48  void p_set_vals( T* p0, T* p1, T* p2 )
49  {
50 #ifdef _MSC_VER
51  /* disable warning that conditional expression is constant, true or false in if */
52 # pragma warning( disable : 4127 )
53 #endif
54  if( lgBC )
55  {
56  p_p[0] = p0; p_p[1] = p1; p_p[2] = p2;
57  }
58  else
59  p_p[0] = p0;
60  }
61 public:
62  typedef random_access_iterator_tag iterator_category;
63  typedef T value_type;
64  typedef T& reference;
65  typedef const T& const_reference;
66  typedef T* pointer;
67  typedef const T* const_pointer;
68  typedef size_t size_type;
69  typedef ptrdiff_t difference_type;
70 
71  // constructors
72  basic_pntr( T* p0, T* p1, T* p2 )
73  {
74  p_set_vals( p0, p1, p2 );
75  }
76  basic_pntr( T* p0 )
77  {
78  p_set_vals( p0, NULL, NULL );
79  }
81  {
82  p_set_vals( NULL, NULL, NULL );
83  }
84  basic_pntr( const basic_pntr& t )
85  {
86  *this = t;
87  }
88  // protected destructor (to prevent direct instantiation or destruction via basic_pntr*, see Alexandrescu p13)
89 protected:
91 public:
92  // pre-increment
94  {
95  ++p_p[0];
96  return *this;
97  }
98  // pre-decrement
100  {
101  --p_p[0];
102  return *this;
103  }
104  // define operators for += and -=, normal arithmetic is defined separately in
105  // the derived classes; it cannot be done here since they would require implicit
106  // conversion from basic_pntr -> pntr or const_pntr to work; this would also create
107  // an implicit and silent conversion from const_pntr -> pntr, which is illegal...
108  basic_pntr& operator+= ( const ptrdiff_t n ) { p_p[0] += n; return *this; }
109  basic_pntr& operator-= ( const ptrdiff_t n ) { p_p[0] -= n; return *this; }
110  // dereference
111  T& operator* () const
112  {
113  return *(p_index_checked(0));
114  }
115  T* operator-> () const
116  {
117  return p_index_checked(0);
118  }
119  T& operator[] ( const ptrdiff_t n ) const
120  {
121  return *(p_index_checked(n));
122  }
123  // finally, define the boolean operators...
124  bool operator== ( const basic_pntr& t ) const { return p_p[0] == t.p_p[0]; }
125  bool operator!= ( const basic_pntr& t ) const { return p_p[0] != t.p_p[0]; }
126  bool operator< ( const basic_pntr& t ) const { return p_p[0] < t.p_p[0]; }
127  bool operator<= ( const basic_pntr& t ) const { return p_p[0] <= t.p_p[0]; }
128  bool operator> ( const basic_pntr& t ) const { return p_p[0] > t.p_p[0]; }
129  bool operator>= ( const basic_pntr& t ) const { return p_p[0] >= t.p_p[0]; }
130 };
131 
133 template<class T, bool lgBC>
134 class pntr : public basic_pntr<T,lgBC>
135 {
136 public:
137  // constructors are not inherited, so define them again
138  pntr( T* p0 ) : basic_pntr<T,lgBC>( p0 ) {}
139  pntr( T* p0, T* p1, T* p2 ) : basic_pntr<T,lgBC>( p0, p1, p2 ) {}
140  pntr() {}
141  // the increment / decrement operators need to be recast...
142  // otherwise expressions like p = ++q would be illegal for iterators...
143  pntr& operator++ () { return static_cast<pntr&>(basic_pntr<T,lgBC>::operator++()); }
144  const pntr operator++ (int) { pntr t = *this; ++(*this); return t; }
145  pntr& operator-- () { return static_cast<pntr&>(basic_pntr<T,lgBC>::operator--()); }
146  const pntr operator-- (int) { pntr t = *this; --(*this); return t; }
147  // define p+n, p-n, p-q
148  const pntr operator+ ( const ptrdiff_t n ) const { pntr s = *this; s += n; return s; }
149  const pntr operator- ( const ptrdiff_t n ) const { pntr s = *this; s -= n; return s; }
150  ptrdiff_t operator- ( const pntr& t ) const { return &(*this[0]) - &t[0]; }
151 };
152 
153 // this defines n+p
154 template<class T, bool lgBC>
155 inline const pntr<T,lgBC> operator+ ( const ptrdiff_t n, const pntr<T,lgBC>& t )
156 {
157  pntr<T,lgBC> s = t;
158  s += n;
159  return s;
160 }
161 
163 template<class T, bool lgBC>
164 class const_pntr : public basic_pntr<T,lgBC>
165 {
166 public:
167  // constructors are not inherited, so define them again
168  const_pntr( T* p0 ) : basic_pntr<T,lgBC>( p0 ) {}
169  const_pntr( T* p0, T* p1, T* p2 ) : basic_pntr<T,lgBC>( p0, p1, p2 ) {}
171  // make sure we can assign a pntr to a const_pntr by creating an implicit conversion to const_pntr
172  const_pntr( const pntr<T,lgBC>& t ) : basic_pntr<T,lgBC>( t ) {}
173  // the increment / decrement operators need to be recast...
174  // otherwise expressions like *p++ = 1. would be legal for const_iterators...
176  const const_pntr operator++ (int) { const_pntr t = *this; ++(*this); return t; }
178  const const_pntr operator-- (int) { const_pntr t = *this; --(*this); return t; }
179  const_pntr& operator+= ( const ptrdiff_t n )
180  {
181  return static_cast<const_pntr&>(basic_pntr<T,lgBC>::operator+=(n));
182  }
183  const_pntr& operator-= ( const ptrdiff_t n )
184  {
185  return static_cast<const_pntr&>(basic_pntr<T,lgBC>::operator-=(n));
186  }
187  // the dereference operators need to be recast...
188  const T& operator* () const { return static_cast<const T&>(basic_pntr<T,lgBC>::operator*()); }
189  const T* operator-> () const { return static_cast<const T*>(basic_pntr<T,lgBC>::operator->()); }
190  const T& operator[] ( const ptrdiff_t n ) const
191  {
192  return static_cast<const T&>(basic_pntr<T,lgBC>::operator[](n));
193  }
194  // define p+n, p-n, p-q
195  const const_pntr operator+ ( const ptrdiff_t n ) const { const_pntr s = *this; s += n; return s; }
196  const const_pntr operator- ( const ptrdiff_t n ) const { const_pntr s = *this; s -= n; return s; }
197  ptrdiff_t operator- ( const const_pntr& t ) const { return &(*this[0]) - &t[0]; }
198 };
199 
200 // this defines n+p
201 template<class T, bool lgBC>
202 inline const const_pntr<T,lgBC> operator+ ( const ptrdiff_t n, const const_pntr<T,lgBC>& t )
203 {
204  const_pntr<T,lgBC> s = t;
205  s += n;
206  return s;
207 }
208 
210 struct tree_vec
211 {
212  typedef size_t size_type;
213 
216 
217 private:
218  void p_clear0()
219  {
220  if( d != NULL )
221  {
222  for( size_type i = 0; i < n; ++i )
223  d[i].clear();
224  delete[] d;
225  }
226  }
227  void p_clear1()
228  {
229  n = 0;
230  d = NULL;
231  }
232 
233 public:
235  {
236  p_clear1();
237  }
238  tree_vec(const tree_vec& m)
239  {
240  p_clear1();
241  *this = m;
242  }
244  {
245  p_clear0();
246  }
247  void clear()
248  {
249  p_clear0();
250  p_clear1();
251  }
252  const tree_vec& operator= (const tree_vec& m)
253  {
254  if( &m != this )
255  {
256  clear();
257  n = m.n;
258  if( m.d != NULL )
259  {
260  d = new tree_vec[n];
261  tree_vec *p = d;
262  const tree_vec *mp = m.d;
263  for( size_type i = 0; i < n; ++i )
264  *p++ = *mp++;
265  }
266  }
267  return *this;
268  }
269  tree_vec& getvec(const size_type i, const size_type index[])
270  {
271  if( i == 0 )
272  return *this;
273  else
274  return getvec(i-1,index).d[index[i-1]];
275  }
276  const tree_vec& getvec(const size_type i, const size_type index[]) const
277  {
278  if( i == 0 )
279  return *this;
280  else
281  return getvec(i-1,index).d[index[i-1]];
282  }
283 };
284 
287 template<int d,mem_layout ALLOC=MEM_LAYOUT_VAL>
289 {
290 public:
291  typedef size_t size_type;
292 
294 
299 
300 private:
301  void p_clear0()
302  {
303  v.clear();
304  }
305  void p_clear1()
306  {
307  size = 0;
308  for( int i=0; i < d; ++i )
309  {
310  s[i] = 0;
311  st[i] = 0;
312  nsl[i] = 0;
313  }
314  }
315 
316 public:
318  {
319  p_clear1();
320  }
322  {
323  p_clear1();
324  *this = m;
325  }
327  {
328  p_clear0();
329  }
330  void clear()
331  {
332  p_clear0();
333  p_clear1();
334  }
336  {
337  if( &m != this )
338  {
339  clear();
340  v = m.v;
341  size = m.size;
342  for( int i=0; i < d; ++i )
343  {
344  s[i] = m.s[i];
345  st[i] = m.st[i];
346  nsl[i] = m.nsl[i];
347  }
348  }
349  return *this;
350  }
351  bool lgInbounds(const size_type n, const size_type index[]) const
352  {
353  if( n != 0 )
354  return ( lgInbounds(n-1,index) && index[n-1] < v.getvec(n-1,index).n );
355  else
356  return true;
357  }
358  void reserve(const size_type n, const size_type index[])
359  {
360  ASSERT( n <= d && index[n-1] > 0 && lgInbounds( n-1, index ) );
361 
362  tree_vec& w = v.getvec( n-1, index );
363  if( d > n )
364  {
365  ASSERT( w.d == NULL );
366  w.d = new tree_vec[ index[n-1] ];
367  }
368  w.n = index[n-1];
369  s[n-1] = max(s[n-1],index[n-1]);
370  nsl[n-1] += index[n-1];
371  }
372  void reserve_recursive(const size_type n, size_type index[])
373  {
374  if( n == 0 )
375  {
376  reserve( n+1, index );
377  if( n+1 < d )
378  reserve_recursive( n+1, index );
379  }
380  else
381  {
382  size_type top = index[n-1];
383  for( size_type i=0; i < top; ++i )
384  {
385  index[n-1] = i;
386  reserve( n+1, index );
387  if( n+1 < d )
388  reserve_recursive( n+1, index );
389  }
390  index[n-1] = top;
391  }
392  }
393  void finalize(void)
394  {
395 #ifdef _MSC_VER
396  /* disable warning that conditional expression is constant, true or false in if */
397 # pragma warning( disable : 4127 )
398 #endif
399 
400  STATIC_ASSERT ( ALLOC == C_TYPE || ALLOC == ARPA_TYPE );
401 
402  if( ALLOC == ARPA_TYPE )
403  {
404  size_type n1[d], n2[d];
405  for( int dim=0; dim < d; ++dim )
406  n1[dim] = n2[dim] = 0L;
407  // sanity checks
408  p_setupArray( n1, n2, &v, 0 );
409  for( int dim=0; dim < d-1; ++dim )
410  ASSERT( n1[dim] == nsl[dim] && n2[dim] == nsl[dim+1] );
411  size = nsl[d-1];
412  }
413  else if( ALLOC == C_TYPE )
414  {
415  st[d-1] = s[d-1];
416  for( int i = d-2; i >= 0; --i )
417  st[i] = st[i+1]*s[i];
418  size = st[0];
419  }
420  else
421  {
422  TotalInsanity();
423  }
424  }
425 
426 private:
427  void p_setupArray( size_type n1[], size_type n2[], const tree_vec* w, size_type l )
428  {
429  for( size_type i=0; i < w->n; ++i )
430  {
431  n1[l]++;
432  // using int(l) is always safe and avoids warnings about the test
433  // 'l < d-2' being always false when d == 2 (e.g. with g++ 4.6.0)
434  if( int(l) < d-2 )
435  {
436  p_setupArray( n1, n2, &w->d[i], l+1 );
437  }
438  n2[l] += w->d[i].n;
439  }
440  }
441 };
442 
443 
444 //
547 //
548 
549 
550 // forward definitions
551 template<class T, int N, mem_layout ALLOC, bool lgBC> class n_pointer;
552 template<class T, int N, mem_layout ALLOC, bool lgBC> class const_n_pointer;
553 
554 template<class T, int N>
555 class n_pointer<T,N,ARPA_TYPE,false>
556 {
557  T* p_p;
558  const size_t* p_st;
559  const tree_vec* p_v;
560 public:
561  typedef n_pointer<T,N-1,ARPA_TYPE,false> value_type;
562  n_pointer(T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
563  const value_type operator[] (const size_t i) const
564  {
565  return value_type( *((T**)p_p+i) );
566  }
567 };
568 
569 template<class T, int N>
570 class n_pointer<T,N,C_TYPE,false>
571 {
572  T* p_p;
573  const size_t* p_st;
574  const tree_vec* p_v;
575 public:
576  typedef n_pointer<T,N-1,C_TYPE,false> value_type;
577  n_pointer(T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
578  const value_type operator[] (const size_t i) const
579  {
580  return value_type( p_p+i*p_st[0], p_st+1 );
581  }
582 };
583 
584 template<class T>
585 class n_pointer<T,1,ARPA_TYPE,false>
586 {
587  T* p_p;
588  const size_t* p_st;
589  const tree_vec* p_v;
590 public:
591  typedef T value_type;
592  n_pointer(T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
593  value_type& operator[] (const size_t i) const
594  {
595  return *(p_p + i);
596  }
597 };
598 
599 template<class T>
600 class n_pointer<T,1,C_TYPE,false>
601 {
602  T* p_p;
603  const size_t* p_st;
604  const tree_vec* p_v;
605 public:
606  typedef T value_type;
607  n_pointer(T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
608  value_type& operator[] (const size_t i) const
609  {
610  return *(p_p + i);
611  }
612 };
613 
614 template<class T, int N>
615 class n_pointer<T,N,ARPA_TYPE,true>
616 {
617  T* p_p;
618  const size_t* p_st;
619  const tree_vec* p_v;
620 public:
621  typedef n_pointer<T,N-1,ARPA_TYPE,true> value_type;
622  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
623  const value_type operator[] (const size_t i) const
624  {
625  if( i >= p_v->n )
626  OUT_OF_RANGE( "n_pointer::operator[]" );
627  return value_type( *((T**)p_p+i), NULL, &p_v->d[i] );
628  }
629 };
630 
631 template<class T, int N>
632 class n_pointer<T,N,C_TYPE,true>
633 {
634  T* p_p;
635  const size_t* p_st;
636  const tree_vec* p_v;
637 public:
638  typedef n_pointer<T,N-1,C_TYPE,true> value_type;
639  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
640  const value_type operator[] (const size_t i) const
641  {
642  if( i >= p_v->n )
643  OUT_OF_RANGE( "n_pointer::operator[]" );
644  return value_type( p_p+i*p_st[0], p_st+1, &p_v->d[i] );
645  }
646 };
647 
648 template<class T>
649 class n_pointer<T,1,ARPA_TYPE,true>
650 {
651  T* p_p;
652  const size_t* p_st;
653  const tree_vec* p_v;
654 public:
655  typedef T value_type;
656  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
657  value_type& operator[] (const size_t i) const
658  {
659  if( i >= p_v->n )
660  OUT_OF_RANGE( "n_pointer::operator[]" );
661  return *(p_p + i);
662  }
663 };
664 
665 template<class T>
666 class n_pointer<T,1,C_TYPE,true>
667 {
668  T* p_p;
669  const size_t* p_st;
670  const tree_vec* p_v;
671 public:
672  typedef T value_type;
673  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
674  value_type& operator[] (const size_t i) const
675  {
676  if( i >= p_v->n )
677  OUT_OF_RANGE( "n_pointer::operator[]" );
678  return *(p_p + i);
679  }
680 };
681 
682 template<class T, int N>
684 {
685  const T* p_p;
686  const size_t* p_st;
687  const tree_vec* p_v;
688 public:
689  typedef const_n_pointer<T,N-1,ARPA_TYPE,false> value_type;
690  const_n_pointer(const T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
691  const value_type operator[] (const size_t i) const
692  {
693  return value_type( *((T**)p_p+i) );
694  }
695 };
696 
697 template<class T, int N>
698 class const_n_pointer<T,N,C_TYPE,false>
699 {
700  const T* p_p;
701  const size_t* p_st;
702  const tree_vec* p_v;
703 public:
704  typedef const_n_pointer<T,N-1,C_TYPE,false> value_type;
705  const_n_pointer(const T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
706  const value_type operator[] (const size_t i) const
707  {
708  return value_type( p_p+i*p_st[0], p_st+1 );
709  }
710 };
711 
712 template<class T>
713 class const_n_pointer<T,1,ARPA_TYPE,false>
714 {
715  const T* p_p;
716  const size_t* p_st;
717  const tree_vec* p_v;
718 public:
719  typedef const T value_type;
720  const_n_pointer(const T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
721  value_type& operator[] (const size_t i) const
722  {
723  return *(p_p + i);
724  }
725 };
726 
727 template<class T>
728 class const_n_pointer<T,1,C_TYPE,false>
729 {
730  const T* p_p;
731  const size_t* p_st;
732  const tree_vec* p_v;
733 public:
734  typedef const T value_type;
735  const_n_pointer(const T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
736  value_type& operator[] (const size_t i) const
737  {
738  return *(p_p + i);
739  }
740 };
741 
742 template<class T, int N>
744 {
745  const T* p_p;
746  const size_t* p_st;
747  const tree_vec* p_v;
748 public:
750  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
751  const value_type operator[] (const size_t i) const
752  {
753  if( i >= p_v->n )
754  OUT_OF_RANGE( "const_n_pointer::operator[]" );
755  return value_type( *((T**)p_p+i), NULL, &p_v->d[i] );
756  }
757 };
758 
759 template<class T, int N>
760 class const_n_pointer<T,N,C_TYPE,true>
761 {
762  const T* p_p;
763  const size_t* p_st;
764  const tree_vec* p_v;
765 public:
766  typedef const_n_pointer<T,N-1,C_TYPE,true> value_type;
767  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
768  const value_type operator[] (const size_t i) const
769  {
770  if( i >= p_v->n )
771  OUT_OF_RANGE( "const_n_pointer::operator[]" );
772  return value_type( p_p+i*p_st[0], p_st+1, &p_v->d[i] );
773  }
774 };
775 
776 template<class T>
777 class const_n_pointer<T,1,ARPA_TYPE,true>
778 {
779  const T* p_p;
780  const size_t* p_st;
781  const tree_vec* p_v;
782 public:
783  typedef const T value_type;
784  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
785  value_type& operator[] (const size_t i) const
786  {
787  if( i >= p_v->n )
788  OUT_OF_RANGE( "const_n_pointer::operator[]" );
789  return *(p_p + i);
790  }
791 };
792 
793 template<class T>
794 class const_n_pointer<T,1,C_TYPE,true>
795 {
796  const T* p_p;
797  const size_t* p_st;
798  const tree_vec* p_v;
799 public:
800  typedef const T value_type;
801  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
802  value_type& operator[] (const size_t i) const
803  {
804  if( i >= p_v->n )
805  OUT_OF_RANGE( "const_n_pointer::operator[]" );
806  return *(p_p + i);
807  }
808 };
809 
810 //
935 //
936 
937 template<class T, int d, mem_layout ALLOC=MEM_LAYOUT_VAL, bool lgBC=lgBOUNDSCHECKVAL>
939 {
940  // ancillary data describing the memory layout of the multi_arr
942  T** p_psl[d-1]; // pointer arrays for ARPA structure
943  valarray<T> p_dsl; // this contains the actual data
944  T* p_ptr; // main pointer to allocated structure
945  T** p_ptr2; // used in debugger to get access to internal representation
946  T*** p_ptr3;
947  T**** p_ptr4;
948  T***** p_ptr5;
949  T****** p_ptr6;
950 
951 public:
952  typedef random_access_iterator_tag iterator_category;
953  typedef T value_type;
954  typedef T& reference;
955  typedef const T& const_reference;
956  typedef T* pointer;
957  typedef const T* const_pointer;
958  typedef size_t size_type;
959  typedef ptrdiff_t difference_type;
962 
963 private:
964  static const size_type npos = static_cast<size_type>(-1);
965 
966  void p_clear0()
967  {
968  p_g.clear();
969  for( int i=0; i < d-1; ++i )
970  delete[] p_psl[i];
971  p_dsl.resize(0);
972  }
973  void p_clear1()
974  {
975  for( int i=0; i < d-1; ++i )
976  p_psl[i] = NULL;
977  p_ptr = NULL;
978  p_ptr2 = NULL;
979  p_ptr3 = NULL;
980  p_ptr4 = NULL;
981  p_ptr5 = NULL;
982  p_ptr6 = NULL;
983  }
984 
985 public:
987  {
988  p_clear1();
989  }
991  {
992  p_clear1();
993  alloc( g );
994  }
996  {
997  p_clear1();
998  size_type index[] = { d1, d2 };
999  alloc( index );
1000  }
1002  {
1003  p_clear1();
1004  size_type index[] = { d1, d2, d3 };
1005  alloc( index );
1006  }
1008  {
1009  p_clear1();
1010  size_type index[] = { d1, d2, d3, d4 };
1011  alloc( index );
1012  }
1014  {
1015  p_clear1();
1016  size_type index[] = { d1, d2, d3, d4, d5 };
1017  alloc( index );
1018  }
1020  {
1021  p_clear1();
1022  size_type index[] = { d1, d2, d3, d4, d5, d6 };
1023  alloc( index );
1024  }
1026  {
1027  p_clear1();
1028  *this = m;
1029  }
1031  {
1032  p_clear0();
1033  }
1034  void clear()
1035  {
1036  p_clear0();
1037  p_clear1();
1038  }
1039  const multi_arr& operator= (const multi_arr& m)
1040  {
1041  if( &m != this )
1042  {
1043  alloc( m.p_g );
1044  vals() = m.vals();
1045  }
1046  return *this;
1047  }
1048  void zero()
1049  {
1050  ASSERT( vals().size() == p_g.size );
1051  if( p_g.size > 0 )
1052  memset( data(), 0, p_g.size*sizeof(T) );
1053  }
1054  void invalidate()
1055  {
1056  ASSERT( vals().size() == p_g.size );
1057  invalidate_array( data(), p_g.size*sizeof(T) );
1058  }
1059  void state_do(FILE *io, bool lgGet)
1060  {
1061  if( lgGet )
1062  restore_state(io);
1063  else
1064  dump_state(io);
1065  }
1066  // dump the array to a file in binary format
1067  void dump_state(FILE *out) const
1068  {
1069  do_dump_state( data(), p_g.size, sizeof(T), out, MA_VERS[ALLOC] );
1070  }
1071  // restore the array from a file in binary format
1072  void restore_state(FILE *in)
1073  {
1074  do_restore_state( data(), p_g.size, sizeof(T), in, MA_VERS[ALLOC] );
1075  }
1076 
1078  {
1079  ASSERT( vals().size() == 0 );
1080  const size_type index[] = { i1 };
1081  p_g.reserve( 1, index );
1082  }
1084  {
1085  ASSERT( vals().size() == 0 );
1086  const size_type index[] = { i1, i2 };
1087  p_g.reserve( 2, index );
1088  }
1090  {
1091  ASSERT( vals().size() == 0 );
1092  const size_type index[] = { i1, i2, i3 };
1093  p_g.reserve( 3, index );
1094  }
1096  {
1097  ASSERT( vals().size() == 0 );
1098  const size_type index[] = { i1, i2, i3, i4 };
1099  p_g.reserve( 4, index );
1100  }
1102  {
1103  ASSERT( vals().size() == 0 );
1104  const size_type index[] = { i1, i2, i3, i4, i5 };
1105  p_g.reserve( 5, index );
1106  }
1108  {
1109  ASSERT( vals().size() == 0 );
1110  const size_type index[] = { i1, i2, i3, i4, i5, i6 };
1111  p_g.reserve( 6, index );
1112  }
1113  void alloc()
1114  {
1115  p_g.finalize();
1116 #ifdef _MSC_VER
1117  /* disable warning that conditional expression is constant, true or false in if */
1118 # pragma warning( disable : 4127 )
1119 #endif
1120  STATIC_ASSERT ( ALLOC == C_TYPE || ALLOC == ARPA_TYPE );
1121 
1122  if( ALLOC == ARPA_TYPE )
1123  {
1124  size_type n1[d], n2[d];
1125  // allocate the pointer arrays ( p_psl[0..d-2] ) and data ( p_dsl )
1126  for( int dim=0; dim < d; ++dim )
1127  {
1128  n1[dim] = n2[dim] = 0L;
1129  if( dim != d-1 )
1130  {
1131  ASSERT( p_psl[dim] == NULL );
1132  if( p_g.nsl[dim] > 0 )
1133  p_psl[dim] = new T*[ p_g.nsl[dim] ];
1134  }
1135  else
1136  {
1137  ASSERT( p_dsl.size() == 0 );
1138  p_dsl.resize( p_g.nsl[dim] );
1139  }
1140  }
1141  // now initialize all the pointer arrays
1142  p_setupArray( n1, n2, &p_g.v, 0 );
1143  p_ptr = (T*)p_psl[0];
1144  }
1145  else if( ALLOC == C_TYPE )
1146  {
1147  for( int i=0; i < d-1; ++i )
1148  p_psl[i] = NULL;
1149  ASSERT( p_dsl.size() == 0 );
1150  p_dsl.resize( p_g.st[0] );
1151  p_ptr = &p_dsl[0];
1152  }
1153  else
1154  {
1155  TotalInsanity();
1156  }
1157  p_ptr2 = (T**)p_ptr;
1158  p_ptr3 = (T***)p_ptr;
1159  p_ptr4 = (T****)p_ptr;
1160  p_ptr5 = (T*****)p_ptr;
1161  p_ptr6 = (T******)p_ptr;
1162  }
1163  // clone the geometry from another multi_arr
1165  {
1166  if( &g != &p_g )
1167  {
1168  clear();
1169  p_g = g;
1170  alloc();
1171  }
1172  }
1173  // set up a rectangular block of data with dimensions d1 x d2 x ....
1175  {
1176  size_type index[] = { d1, d2 };
1177  alloc( index );
1178  }
1180  {
1181  size_type index[] = { d1, d2, d3 };
1182  alloc( index );
1183  }
1185  {
1186  size_type index[] = { d1, d2, d3, d4 };
1187  alloc( index );
1188  }
1190  {
1191  size_type index[] = { d1, d2, d3, d4, d5 };
1192  alloc( index );
1193  }
1195  {
1196  size_type index[] = { d1, d2, d3, d4, d5, d6 };
1197  alloc( index );
1198  }
1199  void alloc(size_type index[])
1200  {
1201  for( int n=0; n < d; n++ )
1202  ASSERT( index[n] > 0 );
1203  clear();
1204  p_g.reserve_recursive( 0, index );
1205  alloc();
1206  }
1207 
1208 private:
1209  // helper routine for alloc(), this fills in the pointer arrays for the ARPA layout
1210  void p_setupArray( size_type n1[], size_type n2[], const tree_vec* g, size_type l )
1211  {
1212  for( size_type i=0; i < g->n; ++i )
1213  {
1214  // using int(l) is always safe and avoids warnings about the test
1215  // 'l < d-2' being always false when d == 2 (e.g. with g++ 4.6.0)
1216  if( int(l) < d-2 )
1217  {
1218  p_psl[l][n1[l]++] = (T*)(p_psl[l+1]+n2[l]);
1219  p_setupArray( n1, n2, &g->d[i], l+1 );
1220  }
1221  else
1222  {
1223  p_psl[l][n1[l]++] = &p_dsl[0]+n2[l];
1224  }
1225  n2[l] += g->d[i].n;
1226  }
1227  }
1228 
1229  // in the p_iterator methods the bound-checking part is split off into a separate
1230  // routine p_iterator_bc in order to make it easier for compilers to inline the code
1232  {
1233 #ifdef _MSC_VER
1234  /* disable warning that conditional expression is constant, true or false in if */
1235 # pragma warning( disable : 4127 )
1236 #endif
1237  if( lgBC )
1238  return p_iterator_bc( i1, i2 );
1239  else
1240  {
1241  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1242  return iterator( &(*t)[i1][i2] );
1243  }
1244  }
1246  {
1247  size_type index[] = { i1 };
1248  if( p_g.lgInbounds( 1, index ) )
1249  {
1250  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1251  size_type n = p_g.v.getvec( 1, index ).n;
1252  T* s = ( n > 0 ) ? &(*t)[i1][0] : NULL;
1253  if( i2 == npos )
1254  return iterator( s+n, s, s+n );
1255  else
1256  return iterator( s+i2, s, s+n );
1257  }
1258  else
1259  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1260  }
1262  {
1263 #ifdef _MSC_VER
1264  /* disable warning that conditional expression is constant, true or false in if */
1265 # pragma warning( disable : 4127 )
1266 #endif
1267  if( lgBC )
1268  return p_iterator_bc( i1, i2, i3 );
1269  else
1270  {
1271  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1272  return iterator( &(*t)[i1][i2][i3] );
1273  }
1274  }
1276  {
1277  size_type index[] = { i1, i2 };
1278  if( p_g.lgInbounds( 2, index ) )
1279  {
1280  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1281  size_type n = p_g.v.getvec( 2, index ).n;
1282  T* s = ( n > 0 ) ? &(*t)[i1][i2][0] : NULL;
1283  if( i3 == npos )
1284  return iterator( s+n, s, s+n );
1285  else
1286  return iterator( s+i3, s, s+n );
1287  }
1288  else
1289  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1290  }
1292  {
1293 #ifdef _MSC_VER
1294  /* disable warning that conditional expression is constant, true or false in if */
1295 # pragma warning( disable : 4127 )
1296 #endif
1297  if( lgBC )
1298  return p_iterator_bc(i1, i2, i3, i4);
1299  else
1300  {
1301  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1302  return iterator( &(*t)[i1][i2][i3][i4] );
1303  }
1304  }
1306  {
1307  size_type index[] = { i1, i2, i3 };
1308  if( p_g.lgInbounds( 3, index ) )
1309  {
1310  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1311  size_type n = p_g.v.getvec( 3, index ).n;
1312  T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][0] : NULL;
1313  if( i4 == npos )
1314  return iterator( s+n, s, s+n );
1315  else
1316  return iterator( s+i4, s, s+n );
1317  }
1318  else
1319  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1320  }
1322  {
1323 #ifdef _MSC_VER
1324  /* disable warning that conditional expression is constant, true or false in if */
1325 # pragma warning( disable : 4127 )
1326 #endif
1327  if( lgBC )
1328  return p_iterator_bc(i1, i2, i3, i4, i5);
1329  else
1330  {
1331  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1332  return iterator( &(*t)[i1][i2][i3][i4][i5] );
1333  }
1334  }
1336  {
1337  size_type index[] = { i1, i2, i3, i4 };
1338  if( p_g.lgInbounds( 4, index ) )
1339  {
1340  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1341  size_type n = p_g.v.getvec( 4, index ).n;
1342  T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][i4][0] : NULL;
1343  if( i5 == npos )
1344  return iterator( s+n, s, s+n );
1345  else
1346  return iterator( s+i5, s, s+n );
1347  }
1348  else
1349  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1350  }
1352  {
1353 #ifdef _MSC_VER
1354  /* disable warning that conditional expression is constant, true or false in if */
1355 # pragma warning( disable : 4127 )
1356 #endif
1357  if( lgBC )
1358  return p_iterator_bc(i1, i2, i3, i4, i5, i6);
1359  else
1360  {
1361  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1362  return iterator( &(*t)[i1][i2][i3][i4][i5][i6] );
1363  }
1364  }
1366  {
1367  size_type index[] = { i1, i2, i3, i4, i5 };
1368  if( p_g.lgInbounds( 5, index ) )
1369  {
1370  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1371  size_type n = p_g.v.getvec( 5, index ).n;
1372  T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][i4][i5][0] : NULL;
1373  if( i6 == npos )
1374  return iterator( s+n, s, s+n );
1375  else
1376  return iterator( s+i6, s, s+n );
1377  }
1378  else
1379  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1380  }
1381 
1382 public:
1384  {
1385  return n_pointer<T,d,ALLOC,lgBC>( p_ptr, p_g.st+1, &p_g.v );
1386  }
1388  {
1389  return const_n_pointer<T,d,ALLOC,lgBC>( p_ptr, p_g.st+1, &p_g.v );
1390  }
1391  typedef n_pointer<T,d-1,ALLOC,lgBC> indexed_type;
1393  {
1394  return n_ptr()[i];
1395  }
1396  typedef const_n_pointer<T,d-1,ALLOC,lgBC> const_indexed_type;
1398  {
1399  return n_ptr()[i];
1400  }
1401 
1403  {
1404  size_type index[] = { i1, i2 };
1405  if( !p_g.lgInbounds( 2, index ) )
1406  OUT_OF_RANGE( "multi_arr::at()" );
1407  return (*this)[i1][i2];
1408  }
1410  {
1411  size_type index[] = { i1, i2 };
1412  if( !p_g.lgInbounds( 2, index ) )
1413  OUT_OF_RANGE( "multi_arr::at()" );
1414  return (*this)[i1][i2];
1415  }
1417  {
1418  size_type index[] = { i1, i2, i3 };
1419  if( !p_g.lgInbounds( 3, index ) )
1420  OUT_OF_RANGE( "multi_arr::at()" );
1421  return (*this)[i1][i2][i3];
1422  }
1424  {
1425  size_type index[] = { i1, i2, i3 };
1426  if( !p_g.lgInbounds( 3, index ) )
1427  OUT_OF_RANGE( "multi_arr::at()" );
1428  return (*this)[i1][i2][i3];
1429  }
1431  {
1432  size_type index[] = { i1, i2, i3, i4 };
1433  if( !p_g.lgInbounds( 4, index ) )
1434  OUT_OF_RANGE( "multi_arr::at()" );
1435  return (*this)[i1][i2][i3][i4];
1436  }
1438  {
1439  size_type index[] = { i1, i2, i3, i4 };
1440  if( !p_g.lgInbounds( 4, index ) )
1441  OUT_OF_RANGE( "multi_arr::at()" );
1442  return (*this)[i1][i2][i3][i4];
1443  }
1445  {
1446  size_type index[] = { i1, i2, i3, i4, i5 };
1447  if( !p_g.lgInbounds( 5, index ) )
1448  OUT_OF_RANGE( "multi_arr::at()" );
1449  return (*this)[i1][i2][i3][i4][i5];
1450  }
1452  {
1453  size_type index[] = { i1, i2, i3, i4, i5 };
1454  if( !p_g.lgInbounds( 5, index ) )
1455  OUT_OF_RANGE( "multi_arr::at()" );
1456  return (*this)[i1][i2][i3][i4][i5];
1457  }
1459  {
1460  size_type index[] = { i1, i2, i3, i4, i5, i6 };
1461  if( !p_g.lgInbounds( 6, index ) )
1462  OUT_OF_RANGE( "multi_arr::at()" );
1463  return (*this)[i1][i2][i3][i4][i5][i6];
1464  }
1466  {
1467  size_type index[] = { i1, i2, i3, i4, i5, i6 };
1468  if( !p_g.lgInbounds( 6, index ) )
1469  OUT_OF_RANGE( "multi_arr::at()" );
1470  return (*this)[i1][i2][i3][i4][i5][i6];
1471  }
1472 
1474  {
1475  return p_iterator(i1, i2);
1476  }
1478  {
1479  return p_iterator(i1, i2);
1480  }
1482  {
1483  return p_iterator(i1, i2, i3);
1484  }
1486  {
1487  return p_iterator(i1, i2, i3);
1488  }
1490  {
1491  return p_iterator(i1, i2, i3, i4);
1492  }
1494  {
1495  return p_iterator(i1, i2, i3, i4);
1496  }
1498  {
1499  return p_iterator(i1, i2, i3, i4, i5);
1500  }
1502  {
1503  return p_iterator(i1, i2, i3, i4, i5);
1504  }
1506  {
1507  return p_iterator(i1, i2, i3, i4, i5, i6);
1508  }
1510  {
1511  return p_iterator(i1, i2, i3, i4, i5, i6);
1512  }
1513 
1515  {
1516  return p_iterator(i1, 0);
1517  }
1519  {
1520  return p_iterator(i1, 0);
1521  }
1523  {
1524  return p_iterator(i1, i2, 0);
1525  }
1527  {
1528  return p_iterator(i1, i2, 0);
1529  }
1531  {
1532  return p_iterator(i1, i2, i3, 0);
1533  }
1535  {
1536  return p_iterator(i1, i2, i3, 0);
1537  }
1539  {
1540  return p_iterator(i1, i2, i3, i4, 0);
1541  }
1543  {
1544  return p_iterator(i1, i2, i3, i4, 0);
1545  }
1547  {
1548  return p_iterator(i1, i2, i3, i4, i5, 0);
1549  }
1551  {
1552  return p_iterator(i1, i2, i3, i4, i5, 0);
1553  }
1554 
1556  {
1557 #ifdef _MSC_VER
1558  /* disable warning that conditional expression is constant, true or false in if */
1559 # pragma warning( disable : 4127 )
1560 #endif
1561  if( lgBC )
1562  return p_iterator(i1, npos);
1563  else
1564  return p_iterator(i1, p_g.v.d[i1].n);
1565  }
1567  {
1568 #ifdef _MSC_VER
1569  /* disable warning that conditional expression is constant, true or false in if */
1570 # pragma warning( disable : 4127 )
1571 #endif
1572  if( lgBC )
1573  return p_iterator(i1, npos);
1574  else
1575  return p_iterator(i1, p_g.v.d[i1].n);
1576  }
1578  {
1579 #ifdef _MSC_VER
1580  /* disable warning that conditional expression is constant, true or false in if */
1581 # pragma warning( disable : 4127 )
1582 #endif
1583  if( lgBC )
1584  return p_iterator(i1, i2, npos);
1585  else
1586  return p_iterator(i1, i2, p_g.v.d[i1].d[i2].n);
1587  }
1589  {
1590 #ifdef _MSC_VER
1591  /* disable warning that conditional expression is constant, true or false in if */
1592 # pragma warning( disable : 4127 )
1593 #endif
1594  if( lgBC )
1595  return p_iterator(i1, i2, npos);
1596  else
1597  return p_iterator(i1, i2, p_g.v.d[i1].d[i2].n);
1598  }
1600  {
1601 #ifdef _MSC_VER
1602  /* disable warning that conditional expression is constant, true or false in if */
1603 # pragma warning( disable : 4127 )
1604 #endif
1605  if( lgBC )
1606  return p_iterator(i1, i2, i3, npos);
1607  else
1608  return p_iterator(i1, i2, i3, p_g.v.d[i1].d[i2].d[i3].n);
1609  }
1611  {
1612 #ifdef _MSC_VER
1613  /* disable warning that conditional expression is constant, true or false in if */
1614 # pragma warning( disable : 4127 )
1615 #endif
1616  if( lgBC )
1617  return p_iterator(i1, i2, i3, npos);
1618  else
1619  return p_iterator(i1, i2, i3, p_g.v.d[i1].d[i2].d[i3].n);
1620  }
1622  {
1623 #ifdef _MSC_VER
1624  /* disable warning that conditional expression is constant, true or false in if */
1625 # pragma warning( disable : 4127 )
1626 #endif
1627  if( lgBC )
1628  return p_iterator(i1, i2, i3, i4, npos);
1629  else
1630  return p_iterator(i1, i2, i3, i4, p_g.v.d[i1].d[i2].d[i3].d[i4].n);
1631  }
1633  {
1634 #ifdef _MSC_VER
1635  /* disable warning that conditional expression is constant, true or false in if */
1636 # pragma warning( disable : 4127 )
1637 #endif
1638  if( lgBC )
1639  return p_iterator(i1, i2, i3, i4, npos);
1640  else
1641  return p_iterator(i1, i2, i3, i4, p_g.v.d[i1].d[i2].d[i3].d[i4].n);
1642  }
1644  {
1645 #ifdef _MSC_VER
1646  /* disable warning that conditional expression is constant, true or false in if */
1647 # pragma warning( disable : 4127 )
1648 #endif
1649  if( lgBC )
1650  return p_iterator(i1, i2, i3, i4, i5, npos);
1651  else
1652  return p_iterator(i1, i2, i3, i4, i5, p_g.v.d[i1].d[i2].d[i3].d[i4].d[i5].n);
1653  }
1655  {
1656 #ifdef _MSC_VER
1657  /* disable warning that conditional expression is constant, true or false in if */
1658 # pragma warning( disable : 4127 )
1659 #endif
1660  if( lgBC )
1661  return p_iterator(i1, i2, i3, i4, i5, npos);
1662  else
1663  return p_iterator(i1, i2, i3, i4, i5, p_g.v.d[i1].d[i2].d[i3].d[i4].d[i5].n);
1664  }
1665 
1667  {
1668  return *begin(i1);
1669  }
1671  {
1672  return *begin(i1);
1673  }
1675  {
1676  return *begin(i1, i2);
1677  }
1679  {
1680  return *begin(i1, i2);
1681  }
1683  {
1684  return *begin(i1, i2, i3);
1685  }
1687  {
1688  return *begin(i1, i2, i3);
1689  }
1691  {
1692  return *begin(i1, i2, i3, i4);
1693  }
1695  {
1696  return *begin(i1, i2, i3, i4);
1697  }
1699  {
1700  return *begin(i1, i2, i3, i4, i5);
1701  }
1703  {
1704  return *begin(i1, i2, i3, i4, i5);
1705  }
1706 
1708  {
1709  return *(end(i1) - 1);
1710  }
1712  {
1713  return *(end(i1) - 1);
1714  }
1716  {
1717  return *(end(i1, i2) - 1);
1718  }
1720  {
1721  return *(end(i1, i2) - 1);
1722  }
1724  {
1725  return *(end(i1, i2, i3) - 1);
1726  }
1728  {
1729  return *(end(i1, i2, i3) - 1);
1730  }
1732  {
1733  return *(end(i1, i2, i3, i4) - 1);
1734  }
1736  {
1737  return *(end(i1, i2, i3, i4) - 1);
1738  }
1740  {
1741  return *(end(i1, i2, i3, i4, i5) - 1);
1742  }
1744  {
1745  return *(end(i1, i2, i3, i4, i5) - 1);
1746  }
1747 
1748  size_type size() const
1749  {
1750  return p_g.size;
1751  }
1753  {
1754  return p_g.size;
1755  }
1756  bool empty() const
1757  {
1758  for( int i=0; i < d-1; ++i )
1759  if( p_psl[i] != NULL )
1760  return false;
1761  return ( p_g.size == 0UL && p_dsl.size() == 0 );
1762  }
1763 
1765  {
1766  if( p_g.size > 0 )
1767  return get_ptr( p_dsl );
1768  else
1769  return NULL;
1770  }
1772  {
1773  if( p_g.size > 0 )
1774  return get_ptr( p_dsl );
1775  else
1776  return NULL;
1777  }
1778 
1780  {
1781  return p_g;
1782  }
1783 
1784  valarray<T>& vals()
1785  {
1786  return p_dsl;
1787  }
1788  const valarray<T>& vals() const
1789  {
1790  return p_dsl;
1791  }
1792 };
1793 
1794 // predefine commonly used iterators
1805 
1816 
1827 
1838 
1839 // on Mac systems these instantiations need to be extern in order to avoid duplicate symbols
1840 #define INSTANTIATE_MULTI_ARR( TYPE, BC ) \
1841 template class pntr<TYPE,BC>; \
1842 template class const_pntr<TYPE,BC>;
1843 
1844 template<class T, bool lgBC=lgBOUNDSCHECKVAL>
1846 {
1847  size_t p_size; // number of elements allocated
1848  long p_begin; // first valid array index
1849  long p_end; // one beyond last valid array index
1850  bool p_init; // set true when alloc() has been called
1851 
1852  T* p_ptr_alloc; // pointer to start of allocated data
1853  T* p_ptr; // pointer used for calculating array indices
1854 
1855 public:
1856  typedef random_access_iterator_tag iterator_category;
1857  typedef T value_type;
1858  typedef T& reference;
1859  typedef const T& const_reference;
1860  typedef T* pointer;
1861  typedef const T* const_pointer;
1862  typedef long size_type;
1863  typedef ptrdiff_t difference_type;
1866 
1867 private:
1868  void p_clear0()
1869  {
1871  p_ptr_alloc = NULL;
1872  }
1873  void p_clear1()
1874  {
1875  p_size = 0;
1876  p_begin = 0;
1877  p_end = 0;
1878  p_init = false;
1879  p_ptr_alloc = NULL;
1880  p_ptr = NULL;
1881  }
1882  T* p_alloc(size_t size) const
1883  {
1884  return new T[size];
1885  }
1886  void p_free(T* p) const
1887  {
1888  delete[] p;
1889  }
1890 
1891 public:
1893  {
1894  p_clear1();
1895  }
1897  {
1898  p_clear1();
1899  alloc( begin, end );
1900  }
1901  flex_arr(const flex_arr& f)
1902  {
1903  p_clear1();
1904  *this = f;
1905  }
1907  {
1908  p_clear0();
1909  }
1910  const flex_arr& operator= (const flex_arr& f)
1911  {
1912  if( &f != this )
1913  {
1914  clear();
1915  p_size = f.p_size;
1916  p_begin = f.p_begin;
1917  p_end = f.p_end;
1918  p_init = f.p_init;
1919  if( f.p_ptr_alloc != NULL )
1920  {
1922  pointer p = p_ptr_alloc;
1923  const_pointer fp = f.p_ptr_alloc;
1924  for( size_type i=0; i < p_end-p_begin; ++i )
1925  *p++ = *fp++;
1927  }
1928  }
1929  return *this;
1930  }
1931  void clear()
1932  {
1933  p_clear0();
1934  p_clear1();
1935  }
1936  void zero()
1937  {
1938  if( p_size > 0 )
1939  memset( p_ptr_alloc, 0, p_size*sizeof(T) );
1940  }
1941  void invalidate()
1942  {
1943  invalidate_array( p_ptr_alloc, p_size*sizeof(T) );
1944  }
1945  void state_do(FILE *out, bool lgGet)
1946  {
1947  if( lgGet )
1948  restore_state(out);
1949  else
1950  dump_state(out);
1951  }
1952  // dump the array to a file in binary format
1953  void dump_state(FILE *out) const
1954  {
1955  do_dump_state( p_ptr_alloc, p_size, sizeof(T), out, MA_VERS[FLX_TYPE] );
1956  }
1957  // restore the array from a file in binary format
1958  void restore_state(FILE *in)
1959  {
1960  do_restore_state( p_ptr_alloc, p_size, sizeof(T), in, MA_VERS[FLX_TYPE] );
1961  }
1962 
1963  // reserve memory for the array
1965  {
1966  // make sure we start with a clean slate...
1967  clear();
1968 #ifdef _MSC_VER
1969  /* disable warning that conditional expression is constant, true or false in if */
1970 # pragma warning( disable : 4127 )
1971 #endif
1972  if( size > 0 )
1973  {
1974  ASSERT( p_ptr_alloc == NULL );
1975  p_ptr_alloc = p_alloc(size);
1976  p_size = (size_t)size;
1977  }
1978  }
1979  // allocate array with index between begin <= ind < end
1980  // memory is allocated here, if not already done with reserve() before
1982  {
1983  if( (size_t)max(end-begin,0) > p_size )
1984  {
1985  clear();
1986 
1987  ASSERT( p_ptr_alloc == NULL );
1988  p_ptr_alloc = p_alloc(end-begin);
1989  p_ptr = p_ptr_alloc - begin;
1990  p_size = (size_t)(end-begin);
1991  }
1992  else
1993  {
1994  // store was already allocated with reserve()
1995  p_ptr = p_ptr_alloc - begin;
1996  }
1997  p_begin = begin;
1998  p_end = end;
1999  p_init = true;
2000  }
2001  // adjust upper limit of array, reallocate store if necessary
2003  {
2004  ASSERT( p_init );
2005  if( (size_t)max(end-p_begin,0) > p_size )
2006  {
2007  // reallocate the store
2008  T* nptr_alloc = p_alloc(end-p_begin);
2009  T* nptr = nptr_alloc - p_begin;
2010  // copy store over using operator= from T, using memcpy would be a bug!
2011  // this could trip valgrind / purify since we don't know if this is initialized
2012  // there is nothing safe we can do here, so the caller should take care of this
2013  // note that we ignore fields above p_end, we assume nothing of interest is there
2014  if( p_ptr_alloc != NULL && p_ptr != NULL )
2015  {
2016  for( size_type i=p_begin; i < p_end; ++i )
2017  nptr[i] = p_ptr[i];
2019  }
2020  p_ptr_alloc = nptr_alloc;
2021  p_ptr = nptr;
2022  p_size = (size_t)(end-p_begin);
2023  }
2024  p_end = end;
2025  }
2026 
2027 private:
2028  // the p_pointer() method below defines indexing into the flex_arr
2030  {
2031  return p_ptr+i;
2032  }
2033 
2035  {
2036 #ifdef _MSC_VER
2037  /* disable warning that conditional expression is constant, true or false in if */
2038 # pragma warning( disable : 4127 )
2039 #endif
2040  if( lgBC )
2042  else
2043  return iterator( p_pointer(i) );
2044  }
2045 
2046  bool p_lgInbounds(size_type i) const
2047  {
2048  return ( i >= p_begin && i < p_end );
2049  }
2050 
2052  {
2053 #ifdef _MSC_VER
2054  /* disable warning that conditional expression is constant, true or false in if */
2055 # pragma warning( disable : 4127 )
2056 #endif
2057  if( lgBC )
2058  {
2059  if( ! p_lgInbounds( i ) )
2060  OUT_OF_RANGE( "flex_arr::p_index()" );
2061  }
2062  return *p_pointer(i);
2063  }
2064 
2065 public:
2067  {
2068  return reference(p_index(i));
2069  }
2071  {
2072  return const_reference(p_index(i));
2073  }
2074 
2076  {
2077  if( ! p_lgInbounds(i) )
2078  OUT_OF_RANGE( "flex_arr::at()" );
2079  return (*this)[i];
2080  }
2082  {
2083  if( ! p_lgInbounds(i) )
2084  OUT_OF_RANGE( "flex_arr::at()" );
2085  return (*this)[i];
2086  }
2087 
2089  {
2090  return iterator(p_iterator(i));
2091  }
2093  {
2094  return const_iterator(p_iterator(i));
2095  }
2096 
2097  // \todo add: assign, swap?, ... (go over stl_vector.h)
2098 
2100  {
2101  return ptr(p_begin);
2102  }
2104  {
2105  return ptr(p_begin);
2106  }
2107 
2109  {
2110  return ptr(p_end);
2111  }
2113  {
2114  return ptr(p_end);
2115  }
2116 
2118  {
2119  return *begin();
2120  }
2122  {
2123  return *begin();
2124  }
2125 
2127  {
2128  return *(end()-1);
2129  }
2131  {
2132  return *(end()-1);
2133  }
2134 
2135  size_type size() const
2136  {
2137  return max(p_end-p_begin,0);
2138  }
2140  {
2141  return p_size;
2142  }
2143  bool empty() const
2144  {
2145  return ( size() == 0 );
2146  }
2147 
2149  {
2150  return p_ptr_alloc;
2151  }
2153  {
2154  return p_ptr_alloc;
2155  }
2156 
2158  {
2159  return p_ptr;
2160  }
2162  {
2163  return p_ptr;
2164  }
2165 };
2166 
2167 // predefine commonly used iterators
2176 
2177 #endif /* CONTAINER_CLASSES_H_ */
const_pointer data() const
const_iterator end(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
multi_arr< realnum, 2 >::const_iterator mr2ci
T * operator->() const
iterator begin(size_type i1)
random_access_iterator_tag iterator_category
iterator p_iterator_bc(size_type i1, size_type i2, size_type i3) const
multi_arr< double, 2 >::const_iterator md2ci
void p_setupArray(size_type n1[], size_type n2[], const tree_vec *g, size_type l)
pntr< T, lgBC > iterator
void alloc(size_type d1, size_type d2, size_type d3, size_type d4, size_type d5)
const_n_pointer(const T *p, const size_t *st=NULL, const tree_vec *v=NULL)
iterator p_iterator(size_type i1, size_type i2) const
reference at(size_type i)
reference back(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
const T * const_pointer
multi_arr< long, 5 >::iterator ml5i
reference back(size_type i1, size_type i2, size_type i3)
size_type size
valarray< T > p_dsl
multi_arr< realnum, 6 >::iterator mr6i
const_reference back(size_type i1, size_type i2, size_type i3) const
n_pointer(T *p, const size_t *st, const tree_vec *v=NULL)
const_iterator ptr(size_type i1, size_type i2, size_type i3) const
const_reference at(size_type i1, size_type i2, size_type i3, size_type i4) const
pntr & operator++()
void state_do(FILE *io, bool lgGet)
const_pntr & operator--()
multi_geom(const multi_geom &m)
pntr - interface class to replace normal pointers
const_pntr(const pntr< T, lgBC > &t)
iterator begin(size_type i1, size_type i2)
iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6)
const_iterator begin(size_type i1, size_type i2, size_type i3) const
const_reference at(size_type i) const
T * get_ptr(T *v)
Definition: cddefines.h:1109
NORETURN void TotalInsanity(void)
Definition: service.cpp:971
T & operator[](const ptrdiff_t n) const
ptrdiff_t difference_type
flex_arr< realnum >::const_iterator farci
void p_set_vals(T *p0, T *p1, T *p2)
const T * const_pointer
static const size_type npos
const_iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4) const
multi_arr< bool, 5 >::const_iterator mb5ci
const_reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
iterator p_iterator(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const
const_reference back(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
bool operator!=(const basic_pntr &t) const
const_pointer data() const
multi_arr< long, 3 >::iterator ml3i
reference at(size_type i1, size_type i2)
reference front(size_type i1, size_type i2)
multi_arr< long, 2 >::const_iterator ml2ci
static const int N
multi_arr< long, 2 >::iterator ml2i
const_iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
const tree_vec & getvec(const size_type i, const size_type index[]) const
void invalidate_array(T *p, size_t size)
Definition: cddefines.h:1091
size_type size() const
const_pntr - same as pntr, except that it replaces const pointers rather than normal pointers ...
const_pntr< T, lgBC > const_iterator
void reserve(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6)
void reserve(const size_type n, const size_type index[])
bool operator<=(const basic_pntr &t) const
iterator end()
reference front(size_type i1)
basic_pntr & operator++()
void reserve(size_type i1, size_type i2)
size_type st[d]
size of each dimension (only used in C_TYPE layout)
iterator p_iterator(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
const_n_pointer(const T *p, const size_t *st, const tree_vec *v=NULL)
reference operator[](size_type i)
multi_arr< realnum, 3 >::const_iterator mr3ci
flex_arr< realnum >::iterator fari
void do_dump_state(const void *buf, size_t nelem, size_t size, FILE *out, int32 magic)
n_pointer(T *p, const size_t *st, const tree_vec *v)
const_n_pointer< T, d-1, ALLOC, lgBC > const_indexed_type
iterator ptr(size_type i1, size_type i2)
const_iterator begin(size_type i1) const
iterator end(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
void reserve(size_type size)
const T & operator[](const ptrdiff_t n) const
const_reference back(size_type i1) const
NORETURN void OUT_OF_RANGE(const char *str)
Definition: cddefines.h:643
random_access_iterator_tag iterator_category
tree_vec * d
reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6)
multi_arr< long, 4 >::const_iterator ml4ci
tree_vec & getvec(const size_type i, const size_type index[])
flex_arr(const flex_arr &f)
multi_arr< long, 3 >::const_iterator ml3ci
multi_arr< bool, 5 >::iterator mb5i
void p_free(T *p) const
const_pointer ptr0() const
n_pointer< T, N-1, C_TYPE, true > value_type
multi_arr< bool, 4 >::iterator mb4i
void reserve(size_type i1, size_type i2, size_type i3)
size_type n
multi_arr< bool, 2 >::const_iterator mb2ci
const_reference front(size_type i1, size_type i2, size_type i3) const
size_type capacity() const
pntr< T, lgBC > iterator
basic_pntr & operator+=(const ptrdiff_t n)
iterator end(size_type i1, size_type i2, size_type i3, size_type i4)
bool operator>=(const basic_pntr &t) const
const_n_pointer(const T *p, const size_t *st=NULL, const tree_vec *v=NULL)
const_reference front(size_type i1, size_type i2, size_type i3, size_type i4) const
const_reference front(size_type i1, size_type i2) const
reference back()
basic_pntr(T *p0, T *p1, T *p2)
const const_n_pointer< T, d, ALLOC, lgBC > n_ptr() const
n_pointer(T *p, const size_t *st=NULL, const tree_vec *v=NULL)
const_pntr(T *p0, T *p1, T *p2)
const_pntr & operator+=(const ptrdiff_t n)
flex_arr(size_type begin, size_type end)
void p_clear0()
sizes of each of the pointer arrays
const_reference back(size_type i1, size_type i2, size_type i3, size_type i4) const
const_iterator end(size_type i1) const
static const int p_nd
n_pointer< T, N-1, C_TYPE, false > value_type
bool empty() const
const_iterator end(size_type i1, size_type i2, size_type i3, size_type i4) const
const_iterator begin() const
random_access_iterator_tag iterator_category
size_type size() const
multi_arr(size_type d1, size_type d2, size_type d3, size_type d4)
multi_arr< bool, 2 >::iterator mb2i
const flex_arr & operator=(const flex_arr &f)
const multi_geom< d, ALLOC > & clone() const
basic_pntr & operator--()
void state_do(FILE *out, bool lgGet)
void finalize(void)
reference at(size_type i1, size_type i2, size_type i3, size_type i4)
const_reference at(size_type i1, size_type i2) const
size_type capacity() const
flex_arr< double >::iterator fadi
iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4)
const_n_pointer< T, N-1, C_TYPE, true > value_type
void p_setupArray(size_type n1[], size_type n2[], const tree_vec *w, size_type l)
pointer p_pointer(size_type i) const
n_pointer(T *p, const size_t *st, const tree_vec *v)
multi_arr(size_type d1, size_type d2, size_type d3, size_type d4, size_type d5, size_type d6)
const_iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const
multi_arr< long, 6 >::iterator ml6i
multi_geom< d, ALLOC > p_g
bool operator==(const basic_pntr &t) const
void alloc(size_type d1, size_type d2)
const_pntr< T, lgBC > const_iterator
iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
void do_restore_state(void *buf, size_t nelem, size_t size, FILE *in, int32 magic)
iterator end(size_type i1, size_type i2, size_type i3)
void alloc(size_type d1, size_type d2, size_type d3, size_type d4)
multi_arr< bool, 3 >::iterator mb3i
iterator p_iterator(size_type i1, size_type i2, size_type i3) const
const_iterator begin(size_type i1, size_type i2, size_type i3, size_type i4) const
const indexed_type operator[](size_type i)
ptrdiff_t difference_type
const_n_pointer< T, N-1, ARPA_TYPE, true > value_type
ptrdiff_t difference_type
const T * operator->() const
iterator p_iterator_bc(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const
multi_arr< double, 5 >::const_iterator md5ci
const pntr operator-(const ptrdiff_t n) const
pntr(T *p0)
multi_arr< double, 5 >::iterator md5i
const T & const_reference
iterator p_iterator(size_type i1, size_type i2, size_type i3, size_type i4) const
const tree_vec & operator=(const tree_vec &m)
const T & operator*() const
multi_arr(const multi_geom< d, ALLOC > &g)
T ** p_psl[d-1]
reference p_index(size_type i) const
flex_arr< double >::const_iterator fadci
pointer data()
const_iterator begin(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
const_reference front(size_type i1) const
const pntr< T, lgBC > operator+(const ptrdiff_t n, const pntr< T, lgBC > &t)
reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
const n_pointer< T, d, ALLOC, lgBC > n_ptr()
const_iterator end(size_type i1, size_type i2, size_type i3) const
const_iterator begin(size_type i1, size_type i2) const
flex_arr< long >::const_iterator falci
const_pntr & operator-=(const ptrdiff_t n)
long max(int a, long b)
Definition: cddefines.h:817
const_iterator end() const
void restore_state(FILE *in)
bool p_lgInbounds(size_type i) const
multi_arr< realnum, 3 >::iterator mr3i
reference front()
void dump_state(FILE *out) const
pntr & operator--()
multi_arr(const multi_arr &m)
size_type nsl[d]
stride for each dimension (only used in C_TYPE layout)
const_n_pointer(const T *p, const size_t *st, const tree_vec *v)
const multi_geom & operator=(const multi_geom &m)
reference back(size_type i1)
multi_arr(size_type d1, size_type d2, size_type d3, size_type d4, size_type d5)
const_n_pointer(const T *p, const size_t *st, const tree_vec *v)
basic_pntr & operator-=(const ptrdiff_t n)
bool lgInbounds(const size_type n, const size_type index[]) const
const_reference front() const
multi_arr< realnum, 4 >::iterator mr4i
tree_vec(const tree_vec &m)
reference back(size_type i1, size_type i2)
n_pointer(T *p, const size_t *st, const tree_vec *v)
reference front(size_type i1, size_type i2, size_type i3)
const_reference back() const
iterator p_iterator_bc(size_type i1, size_type i2, size_type i3, size_type i4) const
const_pntr & operator++()
reference at(size_type i1, size_type i2, size_type i3)
multi_arr< double, 4 >::iterator md4i
iterator p_iterator_bc(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
iterator begin(size_type i1, size_type i2, size_type i3)
void reserve_recursive(const size_type n, size_type index[])
bool operator>(const basic_pntr &t) const
valarray< T > & vals()
multi_arr(size_type d1, size_type d2, size_type d3)
#define ASSERT(exp)
Definition: cddefines.h:613
multi_arr< realnum, 2 >::iterator mr2i
T * p_alloc(size_t size) const
multi_arr< realnum, 4 >::const_iterator mr4ci
iterator end(size_type i1, size_type i2)
void reserve(size_type i1)
multi_arr< bool, 6 >::const_iterator mb6ci
void realloc(size_type end)
iterator begin(size_type i1, size_type i2, size_type i3, size_type i4)
mem_layout
n_pointer< T, N-1, ARPA_TYPE, true > value_type
const_iterator ptr(size_type i1, size_type i2) const
n_pointer(T *p, const size_t *st=NULL, const tree_vec *v=NULL)
iterator end(size_type i1)
pntr(T *p0, T *p1, T *p2)
iterator p_iterator_bc(size_type i1, size_type i2) const
multi_arr< double, 2 >::iterator md2i
n_pointer(T *p, const size_t *st, const tree_vec *v=NULL)
n_pointer(T *p, const size_t *st, const tree_vec *v)
bool empty() const
static const int32 MA_VERS[ML_TOP]
const_iterator end(size_type i1, size_type i2) const
multi_arr< long, 5 >::const_iterator ml5ci
void alloc(size_type d1, size_type d2, size_type d3, size_type d4, size_type d5, size_type d6)
const_n_pointer(const T *p, const size_t *st, const tree_vec *v)
T * p_p[p_nd]
multi_arr< double, 6 >::const_iterator md6ci
const_reference at(size_type i1, size_type i2, size_type i3) const
pointer data()
multi_arr< bool, 4 >::const_iterator mb4ci
const T & const_reference
const T * const_pointer
iterator begin(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
iterator begin()
size_t size_type
multi_arr< bool, 3 >::const_iterator mb3ci
multi_arr< double, 3 >::const_iterator md3ci
reference front(size_type i1, size_type i2, size_type i3, size_type i4)
T * p_index_checked(const ptrdiff_t n) const
multi_arr(size_type d1, size_type d2)
const valarray< T > & vals() const
void reserve(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
flex_arr< long >::iterator fali
const_iterator ptr(size_type i) const
multi_arr< long, 6 >::const_iterator ml6ci
reference front(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5)
n_pointer< T, N-1, ARPA_TYPE, false > value_type
const_reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const
const_n_pointer(const T *p, const size_t *st, const tree_vec *v=NULL)
multi_arr< double, 6 >::iterator md6i
n_pointer< T, d-1, ALLOC, lgBC > indexed_type
multi_arr< double, 4 >::const_iterator md4ci
void alloc(size_type begin, size_type end)
multi_arr< double, 3 >::iterator md3i
void alloc(size_type index[])
const const_pntr operator-(const ptrdiff_t n) const
const T & const_reference
void alloc(size_type d1, size_type d2, size_type d3)
void alloc(const multi_geom< d, ALLOC > &g)
void reserve(size_type i1, size_type i2, size_type i3, size_type i4)
const_reference back(size_type i1, size_type i2) const
tree_vec - a simple class to store the bounds checking information for multi_arr
reference back(size_type i1, size_type i2, size_type i3, size_type i4)
basic_pntr(const basic_pntr &t)
void restore_state(FILE *in)
flex_arr< bool >::const_iterator fabci
iterator ptr(size_type i1, size_type i2, size_type i3)
bool operator<(const basic_pntr &t) const
const_n_pointer< T, N-1, C_TYPE, false > value_type
const_reference front(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const
multi_arr< realnum, 6 >::const_iterator mr6ci
const_n_pointer(const T *p, const size_t *st, const tree_vec *v)
static bool lgGet
Definition: state.cpp:19
flex_arr< bool >::iterator fabi
multi_arr< realnum, 5 >::iterator mr5i
const_n_pointer< T, N-1, ARPA_TYPE, false > value_type
multi_arr< realnum, 5 >::const_iterator mr5ci
#define STATIC_ASSERT(x)
Definition: cddefines.h:140
void dump_state(FILE *out) const
multi_arr< bool, 6 >::iterator mb6i
iterator ptr(size_type i)
T ****** p_ptr6
const multi_arr & operator=(const multi_arr &m)
pointer ptr0()
multi_arr< long, 4 >::iterator ml4i
const const_pntr operator+(const ptrdiff_t n) const
iterator p_iterator(size_type i) const
size_type s[d]
allocated size (number of data elements, pointers are not counted)
const pntr operator+(const ptrdiff_t n) const
T & operator*() const