cloudy  trunk
 All Data Structures 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-2008 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 
26 #ifdef BOUNDS_CHECK
27 #define lgBOUNDSCHECKVAL true
28 #else
29 #define lgBOUNDSCHECKVAL false
30 #endif
31 
34 template<class T, int d, mem_layout ALLOC, bool lgBC>
36 {
37  static const int p_nd = lgBC ? 3 : 1;
38  T* p_p[p_nd]; // p[0] current pointer, p[1] lower bound, p[2] upper bound
39 
40  T* p_index_checked ( const ptrdiff_t n ) const
41  {
42  T* t = p_p[0]+n;
43 #ifdef _MSC_VER
44  /* disable warning that conditional expression is constant, true or false in if */
45 # pragma warning( disable : 4127 )
46 #endif
47  if( lgBC )
48  {
49  if( t < p_p[1] || t >= p_p[2] )
50  OUT_OF_RANGE( "basic_pntr::p_index_checked()" );
51  }
52  return t;
53  }
54  void p_set_vals( T* p0, T* p1, T* p2 )
55  {
56 #ifdef _MSC_VER
57  /* disable warning that conditional expression is constant, true or false in if */
58 # pragma warning( disable : 4127 )
59 #endif
60  if( lgBC )
61  {
62  p_p[0] = p0; p_p[1] = p1; p_p[2] = p2;
63  }
64  else
65  p_p[0] = p0;
66  }
67 public:
68  // constructors
69  basic_pntr( T* p0, T* p1, T* p2 )
70  {
71  p_set_vals( p0, p1, p2 );
72  }
73  basic_pntr( T* p0 )
74  {
75  p_set_vals( p0, NULL, NULL );
76  }
78  {
79  p_set_vals( NULL, NULL, NULL );
80  }
81  basic_pntr( const basic_pntr& t )
82  {
83  *this = t;
84  }
85  // virtual destructor (in case of destruction via basic_pntr*, see Sutter EC++ p77)
86  virtual ~basic_pntr() {}
87  // pre-increment
89  {
90  ++p_p[0];
91  return *this;
92  }
93  // pre-decrement
95  {
96  --p_p[0];
97  return *this;
98  }
99  // define operators for += and -=, normal arithmetic is defined separately in
100  // the derived classes; it cannot be done here since they would require implicit
101  // conversion from basic_pntr -> pntr or const_pntr to work; this would also create
102  // an implicit and silent conversion from const_pntr -> pntr, which is illegal...
103  basic_pntr& operator+= ( const ptrdiff_t n ) { p_p[0] += n; return *this; }
104  basic_pntr& operator-= ( const ptrdiff_t n ) { p_p[0] -= n; return *this; }
105  // dereference
106  T& operator* () const
107  {
108  return *(p_index_checked(0));
109  }
110  T* operator-> () const
111  {
112  return p_index_checked(0);
113  }
114  T& operator[] ( const ptrdiff_t n ) const
115  {
116  return *(p_index_checked(n));
117  }
118  // finally, define the boolean operators...
119  bool operator== ( const basic_pntr& t ) const { return p_p[0] == t.p_p[0]; }
120  bool operator!= ( const basic_pntr& t ) const { return p_p[0] != t.p_p[0]; }
121  bool operator< ( const basic_pntr& t ) const { return p_p[0] < t.p_p[0]; }
122  bool operator<= ( const basic_pntr& t ) const { return p_p[0] <= t.p_p[0]; }
123  bool operator> ( const basic_pntr& t ) const { return p_p[0] > t.p_p[0]; }
124  bool operator>= ( const basic_pntr& t ) const { return p_p[0] >= t.p_p[0]; }
125 };
126 
128 template<class T, int d, mem_layout ALLOC, bool lgBC>
129 class pntr : public basic_pntr<T,d,ALLOC,lgBC>
130 {
131 public:
132  // constructors are not inherited, so define them again
133  pntr( T* p0 ) : basic_pntr<T,d,ALLOC,lgBC>( p0 ) {}
134  pntr( T* p0, T* p1, T* p2 ) : basic_pntr<T,d,ALLOC,lgBC>( p0, p1, p2 ) {}
135  pntr() {}
136  // the increment / decrement operators need to be recast...
137  // otherwise expressions like p = ++q would be illegal for iterators...
139  const pntr operator++ (int) { pntr t = *this; ++(*this); return t; }
141  const pntr operator-- (int) { pntr t = *this; --(*this); return t; }
142  // define p+n, p-n, p-q
143  const pntr operator+ ( const ptrdiff_t n ) const { pntr s = *this; s += n; return s; }
144  const pntr operator- ( const ptrdiff_t n ) const { pntr s = *this; s -= n; return s; }
145  ptrdiff_t operator- ( const pntr& t ) const { return &(*this[0]) - &t[0]; }
146 };
147 
148 // this defines n+p
149 template<class T, int d, mem_layout ALLOC, bool lgBC>
150 inline const pntr<T,d,ALLOC,lgBC> operator+ ( const ptrdiff_t n, const pntr<T,d,ALLOC,lgBC>& t )
151 {
152  pntr<T,d,ALLOC,lgBC> s = t;
153  s += n;
154  return s;
155 }
156 
158 template<class T, int d, mem_layout ALLOC, bool lgBC>
159 class const_pntr : public basic_pntr<T,d,ALLOC,lgBC>
160 {
161 public:
162  // constructors are not inherited, so define them again
163  const_pntr( T* p0 ) : basic_pntr<T,d,ALLOC,lgBC>( p0 ) {}
164  const_pntr( T* p0, T* p1, T* p2 ) : basic_pntr<T,d,ALLOC,lgBC>( p0, p1, p2 ) {}
166  // make sure we can assign a pntr to a const_pntr by creating an implicit conversion to const_pntr
167  const_pntr( const pntr<T,d,ALLOC,lgBC>& t ) : basic_pntr<T,d,ALLOC,lgBC>( t ) {}
168  // the increment / decrement operators need to be recast...
169  // otherwise expressions like *p++ = 1. would be legal for const_iterators...
171  const const_pntr operator++ (int) { const_pntr t = *this; ++(*this); return t; }
173  const const_pntr operator-- (int) { const_pntr t = *this; --(*this); return t; }
174  const_pntr& operator+= ( const ptrdiff_t n )
175  {
176  return static_cast<const_pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator+=(n));
177  }
178  const_pntr& operator-= ( const ptrdiff_t n )
179  {
180  return static_cast<const_pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator-=(n));
181  }
182  // the dereference operators need to be recast...
183  const T& operator* () const { return static_cast<const T&>(basic_pntr<T,d,ALLOC,lgBC>::operator*()); }
184  const T* operator-> () const { return static_cast<const T*>(basic_pntr<T,d,ALLOC,lgBC>::operator->()); }
185  const T& operator[] ( const ptrdiff_t n ) const
186  {
187  return static_cast<const T&>(basic_pntr<T,d,ALLOC,lgBC>::operator[](n));
188  }
189  // define p+n, p-n, p-q
190  const const_pntr operator+ ( const ptrdiff_t n ) const { const_pntr s = *this; s += n; return s; }
191  const const_pntr operator- ( const ptrdiff_t n ) const { const_pntr s = *this; s -= n; return s; }
192  ptrdiff_t operator- ( const const_pntr& t ) const { return &(*this[0]) - &t[0]; }
193 };
194 
195 // this defines n+p
196 template<class T, int d, mem_layout ALLOC, bool lgBC>
197 inline const const_pntr<T,d,ALLOC,lgBC> operator+ ( const ptrdiff_t n, const const_pntr<T,d,ALLOC,lgBC>& t )
198 {
200  s += n;
201  return s;
202 }
203 
205 struct tree_vec
206 {
207  typedef size_t size_type;
208 
211 
212 private:
213  void p_clear0()
214  {
215  if( d != NULL )
216  {
217  for( size_type i = 0; i < n; ++i )
218  d[i].clear();
219  delete[] d;
220  }
221  }
222  void p_clear1()
223  {
224  n = 0;
225  d = NULL;
226  }
227 
228 public:
230  {
231  p_clear1();
232  }
234  {
235  p_clear0();
236  }
237  void clear()
238  {
239  p_clear0();
240  p_clear1();
241  }
242  const tree_vec& operator= ( const tree_vec& m )
243  {
244  if( &m != this )
245  {
246  clear();
247  n = m.n;
248  if( m.d != NULL )
249  {
250  d = new tree_vec[n];
251  tree_vec *p = d;
252  const tree_vec *mp = m.d;
253  for( size_type i = 0; i < n; ++i )
254  *p++ = *mp++;
255  }
256  }
257  return *this;
258  }
259  tree_vec& getvec(const size_type i, const size_type index[])
260  {
261  if( i == 0 )
262  return *this;
263  else
264  return getvec(i-1,index).d[index[i-1]];
265  }
266  const tree_vec& getvec(const size_type i, const size_type index[]) const
267  {
268  if( i == 0 )
269  return *this;
270  else
271  return getvec(i-1,index).d[index[i-1]];
272  }
273 };
274 
277 template<int d,mem_layout ALLOC=MEM_LAYOUT_VAL,bool lgBC=lgBOUNDSCHECKVAL>
279 {
280 public:
281  typedef size_t size_type;
282 
284 
289 
290 private:
291  void p_clear0()
292  {
293  v.clear();
294  }
295  void p_clear1()
296  {
297  size = 0;
298  for( int i=0; i < d; ++i )
299  {
300  s[i] = 0;
301  st[i] = 0;
302  nsl[i] = 0;
303  }
304  }
305 
306 public:
308  {
309  p_clear1();
310  }
312  {
313  p_clear0();
314  }
315  void clear()
316  {
317  p_clear0();
318  p_clear1();
319  }
320  const multi_geom& operator= ( const multi_geom& m )
321  {
322  if( &m != this )
323  {
324  clear();
325  v = m.v;
326  size = m.size;
327  for( int i=0; i < d; ++i )
328  {
329  s[i] = m.s[i];
330  st[i] = m.st[i];
331  nsl[i] = m.nsl[i];
332  }
333  }
334  return *this;
335  }
336  bool lgInbounds(const size_type n, const size_type index[]) const
337  {
338  if( n != 0 )
339  return ( lgInbounds(n-1,index) && index[n-1] < v.getvec(n-1,index).n );
340  else
341  return true;
342  }
343  void reserve(const size_type n, const size_type index[])
344  {
345  ASSERT( n <= d && index[n-1] > 0 && lgInbounds( n-1, index ) );
346 
347  tree_vec& w = v.getvec( n-1, index );
348  if( d > n )
349  {
350  ASSERT( w.d == NULL );
351  w.d = new tree_vec[ index[n-1] ];
352  }
353  w.n = index[n-1];
354  s[n-1] = max(s[n-1],index[n-1]);
355  nsl[n-1] += index[n-1];
356  }
357  void reserve_recursive(const size_type n, size_type index[])
358  {
359  if( n == 0 )
360  {
361  reserve( n+1, index );
362  if( n+1 < d )
363  reserve_recursive( n+1, index );
364  }
365  else
366  {
367  size_type top = index[n-1];
368  for( size_type i=0; i < top; ++i )
369  {
370  index[n-1] = i;
371  reserve( n+1, index );
372  if( n+1 < d )
373  reserve_recursive( n+1, index );
374  }
375  index[n-1] = top;
376  }
377  }
378  void finalize(void)
379  {
380 #ifdef _MSC_VER
381  /* disable warning that conditional expression is constant, true or false in if */
382 # pragma warning( disable : 4127 )
383 #endif
384  if( ALLOC == ARPA_TYPE )
385  {
386  size_type n1[d], n2[d];
387  for( int dim=0; dim < d; ++dim )
388  n1[dim] = n2[dim] = 0L;
389  // sanity checks
390  p_setupArray( n1, n2, &v, 0 );
391  for( int dim=0; dim < d-1; ++dim )
392  ASSERT( n1[dim] == nsl[dim] && n2[dim] == nsl[dim+1] );
393  size = nsl[d-1];
394  }
395  else if( ALLOC == C_TYPE )
396  {
397  st[d-1] = s[d-1];
398  for( int i = d-2; i >= 0; --i )
399  st[i] = st[i+1]*s[i];
400  size = st[0];
401  }
402  else
403  {
404  TotalInsanity();
405  }
406  }
407 
408 private:
409  void p_setupArray( size_type n1[], size_type n2[], const tree_vec* w, int l )
410  {
411  for( size_type i=0; i < w->n; ++i )
412  {
413  n1[l]++;
414  if( l < d-2 )
415  {
416  p_setupArray( n1, n2, &w->d[i], l+1 );
417  }
418  n2[l] += w->d[i].n;
419  }
420  }
421 };
422 
423 
424 //
527 //
528 
529 
530 // forward definitions
531 template<class T, int N, mem_layout ALLOC, bool lgBC> class n_pointer;
532 template<class T, int N, mem_layout ALLOC, bool lgBC> class const_n_pointer;
533 
534 template<class T, int N>
535 class n_pointer<T,N,ARPA_TYPE,false>
536 {
537  T* p_p;
538  const size_t* p_st;
539  const tree_vec* p_v;
540 public:
541  n_pointer(T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
542  const n_pointer<T,N-1,ARPA_TYPE,false> operator[] (const size_t i) const
543  {
544  return n_pointer<T,N-1,ARPA_TYPE,false>( *((T**)p_p+i) );
545  }
546 };
547 
548 template<class T, int N>
549 class n_pointer<T,N,C_TYPE,false>
550 {
551  T* p_p;
552  const size_t* p_st;
553  const tree_vec* p_v;
554 public:
555  n_pointer(T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
556  const n_pointer<T,N-1,C_TYPE,false> operator[] (const size_t i) const
557  {
558  return n_pointer<T,N-1,C_TYPE,false>( p_p+i*p_st[0], p_st+1 );
559  }
560 };
561 
562 template<class T>
563 class n_pointer<T,1,ARPA_TYPE,false>
564 {
565  T* p_p;
566  const size_t* p_st;
567  const tree_vec* p_v;
568 public:
569  n_pointer(T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
570  T& operator[] (const size_t i) const
571  {
572  return *(p_p + i);
573  }
574 };
575 
576 template<class T>
577 class n_pointer<T,1,C_TYPE,false>
578 {
579  T* p_p;
580  const size_t* p_st;
581  const tree_vec* p_v;
582 public:
583  n_pointer(T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
584  T& operator[] (const size_t i) const
585  {
586  return *(p_p + i);
587  }
588 };
589 
590 template<class T, int N>
591 class n_pointer<T,N,ARPA_TYPE,true>
592 {
593  T* p_p;
594  const size_t* p_st;
595  const tree_vec* p_v;
596 public:
597  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
598  const n_pointer<T,N-1,ARPA_TYPE,true> operator[] (const size_t i) const
599  {
600  if( i >= p_v->n )
601  OUT_OF_RANGE( "n_pointer::operator[]" );
602  return n_pointer<T,N-1,ARPA_TYPE,true>( *((T**)p_p+i), NULL, &p_v->d[i] );
603  }
604 };
605 
606 template<class T, int N>
607 class n_pointer<T,N,C_TYPE,true>
608 {
609  T* p_p;
610  const size_t* p_st;
611  const tree_vec* p_v;
612 public:
613  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
614  const n_pointer<T,N-1,C_TYPE,true> operator[] (const size_t i) const
615  {
616  if( i >= p_v->n )
617  OUT_OF_RANGE( "n_pointer::operator[]" );
618  return n_pointer<T,N-1,C_TYPE,true>( p_p+i*p_st[0], p_st+1, &p_v->d[i] );
619  }
620 };
621 
622 template<class T>
623 class n_pointer<T,1,ARPA_TYPE,true>
624 {
625  T* p_p;
626  const size_t* p_st;
627  const tree_vec* p_v;
628 public:
629  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
630  T& operator[] (const size_t i) const
631  {
632  if( i >= p_v->n )
633  OUT_OF_RANGE( "n_pointer::operator[]" );
634  return *(p_p + i);
635  }
636 };
637 
638 template<class T>
639 class n_pointer<T,1,C_TYPE,true>
640 {
641  T* p_p;
642  const size_t* p_st;
643  const tree_vec* p_v;
644 public:
645  n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
646  T& operator[] (const size_t i) const
647  {
648  if( i >= p_v->n )
649  OUT_OF_RANGE( "n_pointer::operator[]" );
650  return *(p_p + i);
651  }
652 };
653 
654 template<class T, int N>
656 {
657  const T* p_p;
658  const size_t* p_st;
659  const tree_vec* p_v;
660 public:
661  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) {}
662  const const_n_pointer<T,N-1,ARPA_TYPE,false> operator[] (const size_t i) const
663  {
664  return const_n_pointer<T,N-1,ARPA_TYPE,false>( *((T**)p_p+i) );
665  }
666 };
667 
668 template<class T, int N>
669 class const_n_pointer<T,N,C_TYPE,false>
670 {
671  const T* p_p;
672  const size_t* p_st;
673  const tree_vec* p_v;
674 public:
675  const_n_pointer(const T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
676  const const_n_pointer<T,N-1,C_TYPE,false> operator[] (const size_t i) const
677  {
678  return const_n_pointer<T,N-1,C_TYPE,false>( p_p+i*p_st[0], p_st+1 );
679  }
680 };
681 
682 template<class T>
683 class const_n_pointer<T,1,ARPA_TYPE,false>
684 {
685  const T* p_p;
686  const size_t* p_st;
687  const tree_vec* p_v;
688 public:
689  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) {}
690  const T& operator[] (const size_t i) const
691  {
692  return *(p_p + i);
693  }
694 };
695 
696 template<class T>
697 class const_n_pointer<T,1,C_TYPE,false>
698 {
699  const T* p_p;
700  const size_t* p_st;
701  const tree_vec* p_v;
702 public:
703  const_n_pointer(const T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {}
704  const T& operator[] (const size_t i) const
705  {
706  return *(p_p + i);
707  }
708 };
709 
710 template<class T, int N>
712 {
713  const T* p_p;
714  const size_t* p_st;
715  const tree_vec* p_v;
716 public:
717  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
718  const const_n_pointer<T,N-1,ARPA_TYPE,true> operator[] (const size_t i) const
719  {
720  if( i >= p_v->n )
721  OUT_OF_RANGE( "const_n_pointer::operator[]" );
722  return const_n_pointer<T,N-1,ARPA_TYPE,true>( *((T**)p_p+i), NULL, &p_v->d[i] );
723  }
724 };
725 
726 template<class T, int N>
727 class const_n_pointer<T,N,C_TYPE,true>
728 {
729  const T* p_p;
730  const size_t* p_st;
731  const tree_vec* p_v;
732 public:
733  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
734  const const_n_pointer<T,N-1,C_TYPE,true> operator[] (const size_t i) const
735  {
736  if( i >= p_v->n )
737  OUT_OF_RANGE( "const_n_pointer::operator[]" );
738  return const_n_pointer<T,N-1,C_TYPE,true>( p_p+i*p_st[0], p_st+1, &p_v->d[i] );
739  }
740 };
741 
742 template<class T>
743 class const_n_pointer<T,1,ARPA_TYPE,true>
744 {
745  const T* p_p;
746  const size_t* p_st;
747  const tree_vec* p_v;
748 public:
749  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
750  const T& operator[] (const size_t i) const
751  {
752  if( i >= p_v->n )
753  OUT_OF_RANGE( "const_n_pointer::operator[]" );
754  return *(p_p + i);
755  }
756 };
757 
758 template<class T>
759 class const_n_pointer<T,1,C_TYPE,true>
760 {
761  const T* p_p;
762  const size_t* p_st;
763  const tree_vec* p_v;
764 public:
765  const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {}
766  const T& operator[] (const size_t i) const
767  {
768  if( i >= p_v->n )
769  OUT_OF_RANGE( "const_n_pointer::operator[]" );
770  return *(p_p + i);
771  }
772 };
773 
774 //
898 //
899 
900 template<class T, int d, mem_layout ALLOC=MEM_LAYOUT_VAL, bool lgBC=lgBOUNDSCHECKVAL>
902 {
903  // ancillary data describing the memory layout of the multi_arr
905  T** p_psl[d-1]; // pointer arrays for ARPA structure
906  valarray<T> p_dsl; // this contains the actual data
907  T* p_ptr; // main pointer to allocated structure
908  T** p_ptr2; // used in debugger to get access to internal representation
909  T*** p_ptr3;
910  T**** p_ptr4;
911  T***** p_ptr5;
912  T****** p_ptr6;
913 
914 public:
915  typedef random_access_iterator_tag iterator_category;
916  typedef T value_type;
917  typedef T& reference;
918  typedef const T& const_reference;
919  typedef T* pointer;
920  typedef const T* const_pointer;
921  typedef size_t size_type;
922  typedef ptrdiff_t difference_type;
925 
926 private:
927  static const size_type npos = static_cast<size_type>(-1);
928 
929  void p_clear0()
930  {
931  p_g.clear();
932  for( int i=0; i < d-1; ++i )
933  delete[] p_psl[i];
934  p_dsl.resize(0);
935  }
936  void p_clear1()
937  {
938  for( int i=0; i < d-1; ++i )
939  p_psl[i] = NULL;
940  p_ptr = NULL;
941  p_ptr2 = NULL;
942  p_ptr3 = NULL;
943  p_ptr4 = NULL;
944  p_ptr5 = NULL;
945  p_ptr6 = NULL;
946  }
947 
948 public:
950  {
951  p_clear1();
952  }
954  {
955  p_clear1();
956  alloc( g );
957  }
959  {
960  p_clear1();
961  size_type index[] = { d1, d2, d3, d4, d5, d6 };
962  alloc( index );
963  }
965  {
966  p_clear0();
967  }
968  void clear()
969  {
970  p_clear0();
971  p_clear1();
972  }
973  const multi_arr& operator= ( const multi_arr& m )
974  {
975  if( &m != this )
976  {
977  clear();
978  p_g = m.p_g;
979  alloc();
980  vals() = m.vals();
981  }
982  return *this;
983  }
984  void zero()
985  {
986  ASSERT( vals().size() == p_g.size );
987  memset( data(), 0, p_g.size*sizeof(T) );
988  }
989  void invalidate()
990  {
991  ASSERT( vals().size() == p_g.size );
992  invalidate_array( data(), p_g.size*sizeof(T) );
993  }
994  void state_do(FILE *io, bool lgGet)
995  {
996  if( lgGet )
997  restore_state(io);
998  else
999  dump_state(io);
1000  }
1001  // dump the array to a file in binary format
1002  void dump_state(FILE *out) const
1003  {
1004  do_dump_state( data(), p_g.size, sizeof(T), out, MA_VERS[ALLOC] );
1005  }
1006  // restore the array from a file in binary format
1007  void restore_state(FILE *in)
1008  {
1009  do_restore_state( data(), p_g.size, sizeof(T), in, MA_VERS[ALLOC] );
1010  }
1011 
1012  void reserve(size_type i1, size_type i2=0, size_type i3=0, size_type i4=0, size_type i5=0, size_type i6=0)
1013  {
1014  const size_type index[] = { i1, i2, i3, i4, i5, i6 };
1015  size_type n = d;
1016  while( n > 1 && index[n-1] == 0 )
1017  --n;
1018  p_g.reserve( n, index );
1019  }
1020  void alloc()
1021  {
1022  ASSERT( p_ptr == NULL );
1023  p_g.finalize();
1024 #ifdef _MSC_VER
1025  /* disable warning that conditional expression is constant, true or false in if */
1026 # pragma warning( disable : 4127 )
1027 #endif
1028  if( ALLOC == ARPA_TYPE )
1029  {
1030  size_type n1[d], n2[d];
1031  // allocate the pointer arrays ( p_psl[0..d-2] ) and data ( p_dsl )
1032  for( int dim=0; dim < d; ++dim )
1033  {
1034  n1[dim] = n2[dim] = 0L;
1035  if( dim != d-1 )
1036  {
1037  ASSERT( p_psl[dim] == NULL );
1038  p_psl[dim] = new T*[ p_g.nsl[dim] ];
1039  }
1040  else
1041  {
1042  ASSERT( p_dsl.size() == 0 );
1043  p_dsl.resize( p_g.nsl[dim] );
1044  }
1045  }
1046  // now initialize all the pointer arrays
1047  p_setupArray( n1, n2, &p_g.v, 0 );
1048  p_ptr = (T*)p_psl[0];
1049  }
1050  else if( ALLOC == C_TYPE )
1051  {
1052  p_dsl.resize( p_g.st[0] );
1053  p_ptr = &p_dsl[0];
1054  }
1055  else
1056  {
1057  TotalInsanity();
1058  }
1059  p_ptr2 = (T**)p_ptr;
1060  p_ptr3 = (T***)p_ptr;
1061  p_ptr4 = (T****)p_ptr;
1062  p_ptr5 = (T*****)p_ptr;
1063  p_ptr6 = (T******)p_ptr;
1064  }
1065  // clone the geometry from another multi_arr
1067  {
1068  if( &g != &p_g )
1069  {
1070  clear();
1071  p_g = g;
1072  alloc();
1073  }
1074  }
1075  // set up a rectangular block of data with dimensions d1 x d2 x ....
1076  void alloc(size_type d1, size_type d2, size_type d3=0, size_type d4=0, size_type d5=0, size_type d6=0)
1077  {
1078  size_type index[] = { d1, d2, d3, d4, d5, d6 };
1079  alloc( index );
1080  }
1081  void alloc(size_type index[])
1082  {
1083  for( int n=0; n < d; n++ )
1084  ASSERT( index[n] > 0 );
1085  clear();
1086  p_g.reserve_recursive( 0, index );
1087  alloc();
1088  }
1089 
1090 private:
1091  // helper routine for alloc(), this fills in the pointer arrays for the ARPA layout
1092  void p_setupArray( size_type n1[], size_type n2[], const tree_vec* g, int l )
1093  {
1094  for( size_type i=0; i < g->n; ++i )
1095  {
1096  if( l < d-2 )
1097  {
1098  p_psl[l][n1[l]++] = (T*)(p_psl[l+1]+n2[l]);
1099  p_setupArray( n1, n2, &g->d[i], l+1 );
1100  }
1101  else
1102  {
1103  p_psl[l][n1[l]++] = &p_dsl[0]+n2[l];
1104  }
1105  n2[l] += g->d[i].n;
1106  }
1107  }
1108 
1109  // in the p_iterator methods the bound-checking part is split off into a separate
1110  // routine p_iterator_bc in order to make it easier for compilers to inline the code
1112  {
1113 #ifdef _MSC_VER
1114  /* disable warning that conditional expression is constant, true or false in if */
1115 # pragma warning( disable : 4127 )
1116 #endif
1117  if( lgBC )
1118  return p_iterator_bc( i1, i2 );
1119  else
1120  {
1121  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1122  return iterator( &(*t)[i1][i2] );
1123  }
1124  }
1126  {
1127  size_type index[] = { i1 };
1128  if( p_g.lgInbounds( 1, index ) )
1129  {
1130  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1131  size_type n = p_g.v.getvec( 1, index ).n;
1132  T* s = ( n > 0 ) ? &(*t)[i1][0] : NULL;
1133  if( i2 == npos )
1134  return iterator( s+n, s, s+n );
1135  else
1136  return iterator( s+i2, s, s+n );
1137  }
1138  else
1139  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1140  }
1142  {
1143 #ifdef _MSC_VER
1144  /* disable warning that conditional expression is constant, true or false in if */
1145 # pragma warning( disable : 4127 )
1146 #endif
1147  if( lgBC )
1148  return p_iterator_bc( i1, i2, i3 );
1149  else
1150  {
1151  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1152  return iterator( &(*t)[i1][i2][i3] );
1153  }
1154  }
1156  {
1157  size_type index[] = { i1, i2 };
1158  if( p_g.lgInbounds( 2, index ) )
1159  {
1160  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1161  size_type n = p_g.v.getvec( 2, index ).n;
1162  T* s = ( n > 0 ) ? &(*t)[i1][i2][0] : NULL;
1163  if( i3 == npos )
1164  return iterator( s+n, s, s+n );
1165  else
1166  return iterator( s+i3, s, s+n );
1167  }
1168  else
1169  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1170  }
1172  {
1173 #ifdef _MSC_VER
1174  /* disable warning that conditional expression is constant, true or false in if */
1175 # pragma warning( disable : 4127 )
1176 #endif
1177  if( lgBC )
1178  return p_iterator_bc(i1, i2, i3, i4);
1179  else
1180  {
1181  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1182  return iterator( &(*t)[i1][i2][i3][i4] );
1183  }
1184  }
1186  {
1187  size_type index[] = { i1, i2, i3 };
1188  if( p_g.lgInbounds( 3, index ) )
1189  {
1190  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1191  size_type n = p_g.v.getvec( 3, index ).n;
1192  T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][0] : NULL;
1193  if( i4 == npos )
1194  return iterator( s+n, s, s+n );
1195  else
1196  return iterator( s+i4, s, s+n );
1197  }
1198  else
1199  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1200  }
1202  {
1203 #ifdef _MSC_VER
1204  /* disable warning that conditional expression is constant, true or false in if */
1205 # pragma warning( disable : 4127 )
1206 #endif
1207  if( lgBC )
1208  return p_iterator_bc(i1, i2, i3, i4, i5);
1209  else
1210  {
1211  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1212  return iterator( &(*t)[i1][i2][i3][i4][i5] );
1213  }
1214  }
1216  {
1217  size_type index[] = { i1, i2, i3, i4 };
1218  if( p_g.lgInbounds( 4, index ) )
1219  {
1220  multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this);
1221  size_type n = p_g.v.getvec( 4, index ).n;
1222  T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][i4][0] : NULL;
1223  if( i5 == npos )
1224  return iterator( s+n, s, s+n );
1225  else
1226  return iterator( s+i5, s, s+n );
1227  }
1228  else
1229  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1230  }
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, i3, i4, i5, i6);
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][i3][i4][i5][i6] );
1243  }
1244  }
1246  {
1247  size_type index[] = { i1, i2, i3, i4, i5 };
1248  if( p_g.lgInbounds( 5, 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( 5, index ).n;
1252  T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][i4][i5][0] : NULL;
1253  if( i6 == npos )
1254  return iterator( s+n, s, s+n );
1255  else
1256  return iterator( s+i6, s, s+n );
1257  }
1258  else
1259  OUT_OF_RANGE( "multi_arr::p_iterator()" );
1260  }
1261 
1262 public:
1264  {
1265  return n_pointer<T,d,ALLOC,lgBC>( p_ptr, p_g.st+1, &p_g.v );
1266  }
1268  {
1269  return const_n_pointer<T,d,ALLOC,lgBC>( p_ptr, p_g.st+1, &p_g.v );
1270  }
1271  const n_pointer<T,d-1,ALLOC,lgBC> operator[] (size_type i)
1272  {
1273  return n_ptr()[i];
1274  }
1275  const const_n_pointer<T,d-1,ALLOC,lgBC> operator[] (size_type i) const
1276  {
1277  return n_ptr()[i];
1278  }
1279 
1281  {
1282  size_type index[] = { i1, i2 };
1283  if( !p_g.lgInbounds( 2, index ) )
1284  OUT_OF_RANGE( "multi_arr::at()" );
1285  return (*this)[i1][i2];
1286  }
1288  {
1289  size_type index[] = { i1, i2 };
1290  if( !p_g.lgInbounds( 2, index ) )
1291  OUT_OF_RANGE( "multi_arr::at()" );
1292  return (*this)[i1][i2];
1293  }
1295  {
1296  size_type index[] = { i1, i2, i3 };
1297  if( !p_g.lgInbounds( 3, index ) )
1298  OUT_OF_RANGE( "multi_arr::at()" );
1299  return (*this)[i1][i2][i3];
1300  }
1302  {
1303  size_type index[] = { i1, i2, i3 };
1304  if( !p_g.lgInbounds( 3, index ) )
1305  OUT_OF_RANGE( "multi_arr::at()" );
1306  return (*this)[i1][i2][i3];
1307  }
1309  {
1310  size_type index[] = { i1, i2, i3, i4 };
1311  if( !p_g.lgInbounds( 4, index ) )
1312  OUT_OF_RANGE( "multi_arr::at()" );
1313  return (*this)[i1][i2][i3][i4];
1314  }
1316  {
1317  size_type index[] = { i1, i2, i3, i4 };
1318  if( !p_g.lgInbounds( 4, index ) )
1319  OUT_OF_RANGE( "multi_arr::at()" );
1320  return (*this)[i1][i2][i3][i4];
1321  }
1323  {
1324  size_type index[] = { i1, i2, i3, i4, i5 };
1325  if( !p_g.lgInbounds( 5, index ) )
1326  OUT_OF_RANGE( "multi_arr::at()" );
1327  return (*this)[i1][i2][i3][i4][i5];
1328  }
1330  {
1331  size_type index[] = { i1, i2, i3, i4, i5 };
1332  if( !p_g.lgInbounds( 5, index ) )
1333  OUT_OF_RANGE( "multi_arr::at()" );
1334  return (*this)[i1][i2][i3][i4][i5];
1335  }
1337  {
1338  size_type index[] = { i1, i2, i3, i4, i5, i6 };
1339  if( !p_g.lgInbounds( 6, index ) )
1340  OUT_OF_RANGE( "multi_arr::at()" );
1341  return (*this)[i1][i2][i3][i4][i5][i6];
1342  }
1344  {
1345  size_type index[] = { i1, i2, i3, i4, i5, i6 };
1346  if( !p_g.lgInbounds( 6, index ) )
1347  OUT_OF_RANGE( "multi_arr::at()" );
1348  return (*this)[i1][i2][i3][i4][i5][i6];
1349  }
1350 
1352  {
1353  return p_iterator(i1, i2);
1354  }
1356  {
1357  return p_iterator(i1, i2);
1358  }
1360  {
1361  return p_iterator(i1, i2, i3);
1362  }
1364  {
1365  return p_iterator(i1, i2, i3);
1366  }
1368  {
1369  return p_iterator(i1, i2, i3, i4);
1370  }
1372  {
1373  return p_iterator(i1, i2, i3, i4);
1374  }
1376  {
1377  return p_iterator(i1, i2, i3, i4, i5);
1378  }
1380  {
1381  return p_iterator(i1, i2, i3, i4, i5);
1382  }
1384  {
1385  return p_iterator(i1, i2, i3, i4, i5, i6);
1386  }
1388  {
1389  return p_iterator(i1, i2, i3, i4, i5, i6);
1390  }
1391 
1393  {
1394  return p_iterator(i1, 0);
1395  }
1397  {
1398  return p_iterator(i1, 0);
1399  }
1401  {
1402  return p_iterator(i1, i2, 0);
1403  }
1405  {
1406  return p_iterator(i1, i2, 0);
1407  }
1409  {
1410  return p_iterator(i1, i2, i3, 0);
1411  }
1413  {
1414  return p_iterator(i1, i2, i3, 0);
1415  }
1417  {
1418  return p_iterator(i1, i2, i3, i4, 0);
1419  }
1421  {
1422  return p_iterator(i1, i2, i3, i4, 0);
1423  }
1425  {
1426  return p_iterator(i1, i2, i3, i4, i5, 0);
1427  }
1429  {
1430  return p_iterator(i1, i2, i3, i4, i5, 0);
1431  }
1432 
1434  {
1435 #ifdef _MSC_VER
1436  /* disable warning that conditional expression is constant, true or false in if */
1437 # pragma warning( disable : 4127 )
1438 #endif
1439  if( lgBC )
1440  return p_iterator(i1, npos);
1441  else
1442  return p_iterator(i1, p_g.v.d[i1].n);
1443  }
1445  {
1446 #ifdef _MSC_VER
1447  /* disable warning that conditional expression is constant, true or false in if */
1448 # pragma warning( disable : 4127 )
1449 #endif
1450  if( lgBC )
1451  return p_iterator(i1, npos);
1452  else
1453  return p_iterator(i1, p_g.v.d[i1].n);
1454  }
1456  {
1457 #ifdef _MSC_VER
1458  /* disable warning that conditional expression is constant, true or false in if */
1459 # pragma warning( disable : 4127 )
1460 #endif
1461  if( lgBC )
1462  return p_iterator(i1, i2, npos);
1463  else
1464  return p_iterator(i1, i2, p_g.v.d[i1].d[i2].n);
1465  }
1467  {
1468 #ifdef _MSC_VER
1469  /* disable warning that conditional expression is constant, true or false in if */
1470 # pragma warning( disable : 4127 )
1471 #endif
1472  if( lgBC )
1473  return p_iterator(i1, i2, npos);
1474  else
1475  return p_iterator(i1, i2, p_g.v.d[i1].d[i2].n);
1476  }
1478  {
1479 #ifdef _MSC_VER
1480  /* disable warning that conditional expression is constant, true or false in if */
1481 # pragma warning( disable : 4127 )
1482 #endif
1483  if( lgBC )
1484  return p_iterator(i1, i2, i3, npos);
1485  else
1486  return p_iterator(i1, i2, i3, p_g.v.d[i1].d[i2].d[i3].n);
1487  }
1489  {
1490 #ifdef _MSC_VER
1491  /* disable warning that conditional expression is constant, true or false in if */
1492 # pragma warning( disable : 4127 )
1493 #endif
1494  if( lgBC )
1495  return p_iterator(i1, i2, i3, npos);
1496  else
1497  return p_iterator(i1, i2, i3, p_g.v.d[i1].d[i2].d[i3].n);
1498  }
1500  {
1501 #ifdef _MSC_VER
1502  /* disable warning that conditional expression is constant, true or false in if */
1503 # pragma warning( disable : 4127 )
1504 #endif
1505  if( lgBC )
1506  return p_iterator(i1, i2, i3, i4, npos);
1507  else
1508  return p_iterator(i1, i2, i3, i4, p_g.v.d[i1].d[i2].d[i3].d[i4].n);
1509  }
1511  {
1512 #ifdef _MSC_VER
1513  /* disable warning that conditional expression is constant, true or false in if */
1514 # pragma warning( disable : 4127 )
1515 #endif
1516  if( lgBC )
1517  return p_iterator(i1, i2, i3, i4, npos);
1518  else
1519  return p_iterator(i1, i2, i3, i4, p_g.v.d[i1].d[i2].d[i3].d[i4].n);
1520  }
1522  {
1523 #ifdef _MSC_VER
1524  /* disable warning that conditional expression is constant, true or false in if */
1525 # pragma warning( disable : 4127 )
1526 #endif
1527  if( lgBC )
1528  return p_iterator(i1, i2, i3, i4, i5, npos);
1529  else
1530  return p_iterator(i1, i2, i3, i4, i5, p_g.v.d[i1].d[i2].d[i3].d[i4].d[i5].n);
1531  }
1533  {
1534 #ifdef _MSC_VER
1535  /* disable warning that conditional expression is constant, true or false in if */
1536 # pragma warning( disable : 4127 )
1537 #endif
1538  if( lgBC )
1539  return p_iterator(i1, i2, i3, i4, i5, npos);
1540  else
1541  return p_iterator(i1, i2, i3, i4, i5, p_g.v.d[i1].d[i2].d[i3].d[i4].d[i5].n);
1542  }
1543 
1545  {
1546  return *begin(i1);
1547  }
1549  {
1550  return *begin(i1);
1551  }
1553  {
1554  return *begin(i1, i2);
1555  }
1557  {
1558  return *begin(i1, i2);
1559  }
1561  {
1562  return *begin(i1, i2, i3);
1563  }
1565  {
1566  return *begin(i1, i2, i3);
1567  }
1569  {
1570  return *begin(i1, i2, i3, i4);
1571  }
1573  {
1574  return *begin(i1, i2, i3, i4);
1575  }
1577  {
1578  return *begin(i1, i2, i3, i4, i5);
1579  }
1581  {
1582  return *begin(i1, i2, i3, i4, i5);
1583  }
1584 
1586  {
1587  return *(end(i1) - 1);
1588  }
1590  {
1591  return *(end(i1) - 1);
1592  }
1594  {
1595  return *(end(i1, i2) - 1);
1596  }
1598  {
1599  return *(end(i1, i2) - 1);
1600  }
1602  {
1603  return *(end(i1, i2, i3) - 1);
1604  }
1606  {
1607  return *(end(i1, i2, i3) - 1);
1608  }
1610  {
1611  return *(end(i1, i2, i3, i4) - 1);
1612  }
1614  {
1615  return *(end(i1, i2, i3, i4) - 1);
1616  }
1618  {
1619  return *(end(i1, i2, i3, i4, i5) - 1);
1620  }
1622  {
1623  return *(end(i1, i2, i3, i4, i5) - 1);
1624  }
1625 
1626  size_type size() const
1627  {
1628  return p_g.size;
1629  }
1631  {
1632  return p_g.size;
1633  }
1634  bool empty() const
1635  {
1636  return ( p_g.size == 0UL );
1637  }
1638 
1640  {
1641  return &p_dsl[0];
1642  }
1644  {
1645  // the Sun Studio compiler does not allow &p_dsl[0] for a const valarray...
1646  return &const_cast<valarray<T>&>(p_dsl)[0];
1647  }
1648 
1650  {
1651  return p_g;
1652  }
1653 
1654  valarray<T>& vals()
1655  {
1656  return p_dsl;
1657  }
1658  const valarray<T>& vals() const
1659  {
1660  return p_dsl;
1661  }
1662 };
1663 
1664 // predefine commonly used iterators
1675 
1686 
1697 
1708 
1709 #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(_MSC_VER)
1710 #define INST_EXTERN EXTERN
1711 #else
1712 #define INST_EXTERN
1713 #endif
1714 
1715 #ifdef _MSC_VER
1716 /* disable "'extern' before template explicit instantiation" */
1717 # pragma warning( disable : 4231 )
1718 #endif
1719 
1720 // on Mac systems these instantiations need to be extern in order to avoid duplicate symbols
1721 #define INSTANTIATE_MULTI_ARR( TYPE, LAYOUT, BC ) \
1722 INST_EXTERN template class pntr<TYPE,2,LAYOUT,BC>; \
1723 INST_EXTERN template class pntr<TYPE,3,LAYOUT,BC>; \
1724 INST_EXTERN template class pntr<TYPE,4,LAYOUT,BC>; \
1725 INST_EXTERN template class pntr<TYPE,5,LAYOUT,BC>; \
1726 INST_EXTERN template class pntr<TYPE,6,LAYOUT,BC>; \
1727 INST_EXTERN template class const_pntr<TYPE,2,LAYOUT,BC>; \
1728 INST_EXTERN template class const_pntr<TYPE,3,LAYOUT,BC>; \
1729 INST_EXTERN template class const_pntr<TYPE,4,LAYOUT,BC>; \
1730 INST_EXTERN template class const_pntr<TYPE,5,LAYOUT,BC>; \
1731 INST_EXTERN template class const_pntr<TYPE,6,LAYOUT,BC>
1732 
1738 
1739 
1740 template<class T, bool lgBC=lgBOUNDSCHECKVAL>
1742 {
1743  size_t p_size; // number of elements allocated
1744  long p_begin; // first valid array index
1745  long p_end; // one beyond last valid array index
1746  bool p_init; // set true when alloc() has been called
1747 
1748  T* p_ptr_alloc; // pointer to start of allocated data
1749  T* p_ptr; // pointer used for calculating array indices
1750 
1751 public:
1752  typedef random_access_iterator_tag iterator_category;
1753  typedef T value_type;
1754  typedef T& reference;
1755  typedef const T& const_reference;
1756  typedef T* pointer;
1757  typedef const T* const_pointer;
1758  typedef long size_type;
1759  typedef ptrdiff_t difference_type;
1762 
1763 private:
1764  void p_clear0()
1765  {
1766  delete[] p_ptr_alloc;
1767  p_ptr_alloc = NULL;
1768  }
1769  void p_clear1()
1770  {
1771  p_size = 0;
1772  p_begin = 0;
1773  p_end = 0;
1774  p_init = false;
1775  p_ptr_alloc = NULL;
1776  p_ptr = NULL;
1777  }
1778 
1779 public:
1781  {
1782  p_clear1();
1783  }
1785  {
1786  p_clear1();
1787  alloc( begin, end );
1788  }
1790  {
1791  p_clear0();
1792  }
1793  const flex_arr& operator= ( const flex_arr& f )
1794  {
1795  if( &f != this )
1796  {
1797  clear();
1798  p_size = f.p_size;
1799  p_begin = f.p_begin;
1800  p_end = f.p_end;
1801  p_init = f.p_init;
1802  if( f.p_ptr_alloc != NULL )
1803  {
1804  p_ptr_alloc = new T[ p_size ];
1805  pointer p = p_ptr_alloc;
1806  const_pointer fp = f.p_ptr_alloc;
1807  for( size_type i=0; i < p_end-p_begin; ++i )
1808  *p++ = *fp++;
1810  }
1811  }
1812  return *this;
1813  }
1814  void clear()
1815  {
1816  p_clear0();
1817  p_clear1();
1818  }
1819  void zero()
1820  {
1821  ASSERT( p_ptr_alloc != NULL );
1822  memset( p_ptr_alloc, 0, p_size*sizeof(T) );
1823  }
1824  void invalidate()
1825  {
1826  ASSERT( p_ptr_alloc != NULL );
1827  invalidate_array( p_ptr_alloc, p_size*sizeof(T) );
1828  }
1829  void state_do(FILE *out, bool lgGet)
1830  {
1831  if( lgGet )
1832  restore_state(out);
1833  else
1834  dump_state(out);
1835  }
1836  // dump the array to a file in binary format
1837  void dump_state(FILE *out) const
1838  {
1839  do_dump_state( p_ptr_alloc, p_size, sizeof(T), out, MA_VERS[FLX_TYPE] );
1840  }
1841  // restore the array from a file in binary format
1842  void restore_state(FILE *in)
1843  {
1844  do_restore_state( p_ptr_alloc, p_size, sizeof(T), in, MA_VERS[FLX_TYPE] );
1845  }
1846 
1847  // reserve memory for the array
1849  {
1850  // make sure we start with a clean slate...
1851  clear();
1852 #ifdef _MSC_VER
1853  /* disable warning that conditional expression is constant, true or false in if */
1854 # pragma warning( disable : 4127 )
1855 #endif
1856  if( size > 0 )
1857  {
1858  ASSERT( p_ptr_alloc == NULL );
1859  p_ptr_alloc = new T[size];
1860  p_size = (size_t)size;
1861  }
1862  }
1863  // allocate array with index between begin <= ind < end
1864  // memory is allocated here, if not already done with reserve() before
1866  {
1867  if( (size_t)max(end-begin,0) > p_size )
1868  {
1869  clear();
1870 
1871  ASSERT( p_ptr_alloc == NULL );
1872  p_ptr_alloc = new T[end-begin];
1873  p_ptr = p_ptr_alloc - begin;
1874  p_size = (size_t)(end-begin);
1875  }
1876  else
1877  {
1878  // store was already allocated wit reserve()
1879  p_ptr = p_ptr_alloc - begin;
1880  }
1881  p_begin = begin;
1882  p_end = end;
1883  p_init = true;
1884  }
1885  // adjust upper limit of array, reallocate store if necessary
1887  {
1888  ASSERT( p_init );
1889  if( (size_t)max(end-p_begin,0) > p_size )
1890  {
1891  // reallocate the store
1892  T* nptr_alloc = new T[end-p_begin];
1893  T* nptr = nptr_alloc - p_begin;
1894  // copy store over using operator= from T, using memcpy would be a bug!
1895  // this could trip valgrind / purify since we don't know if this is initialized
1896  // there is nothing safe we can do here, so the caller should take care of this
1897  // note that we ignore fields above p_end, we assume nothing of interest is there
1898  if( p_ptr_alloc != NULL && p_ptr != NULL )
1899  {
1900  for( size_type i=p_begin; i < p_end; ++i )
1901  nptr[i] = p_ptr[i];
1902  delete[] p_ptr_alloc;
1903  }
1904  p_ptr_alloc = nptr_alloc;
1905  p_ptr = nptr;
1906  p_size = (size_t)(end-p_begin);
1907  }
1908  p_end = end;
1909  }
1910 
1911 private:
1912  // the p_pointer() method below defines indexing into the flex_arr
1914  {
1915  return p_ptr+i;
1916  }
1917 
1919  {
1920 #ifdef _MSC_VER
1921  /* disable warning that conditional expression is constant, true or false in if */
1922 # pragma warning( disable : 4127 )
1923 #endif
1924  if( lgBC )
1926  else
1927  return iterator( p_pointer(i) );
1928  }
1929 
1930  bool p_lgInbounds(size_type i) const
1931  {
1932  return ( i >= p_begin && i < p_end );
1933  }
1934 
1936  {
1937 #ifdef _MSC_VER
1938  /* disable warning that conditional expression is constant, true or false in if */
1939 # pragma warning( disable : 4127 )
1940 #endif
1941  if( lgBC )
1942  {
1943  if( ! p_lgInbounds( i ) )
1944  OUT_OF_RANGE( "flex_arr::p_index()" );
1945  }
1946  return *p_pointer(i);
1947  }
1948 
1949 public:
1951  {
1952  return reference(p_index(i));
1953  }
1955  {
1956  return const_reference(p_index(i));
1957  }
1958 
1960  {
1961  if( ! p_lgInbounds(i) )
1962  OUT_OF_RANGE( "flex_arr::at()" );
1963  return (*this)[i];
1964  }
1966  {
1967  if( ! p_lgInbounds(i) )
1968  OUT_OF_RANGE( "flex_arr::at()" );
1969  return (*this)[i];
1970  }
1971 
1973  {
1974  return iterator(p_iterator(i));
1975  }
1977  {
1978  return const_iterator(p_iterator(i));
1979  }
1980 
1981  // \todo: add: assign, swap?, ... (go over stl_vector.h)
1982 
1984  {
1985  return ptr(p_begin);
1986  }
1988  {
1989  return ptr(p_begin);
1990  }
1991 
1993  {
1994  return ptr(p_end);
1995  }
1997  {
1998  return ptr(p_end);
1999  }
2000 
2002  {
2003  return *begin();
2004  }
2006  {
2007  return *begin();
2008  }
2009 
2011  {
2012  return *(end()-1);
2013  }
2015  {
2016  return *(end()-1);
2017  }
2018 
2019  size_type size() const
2020  {
2021  return max(p_end-p_begin,0);
2022  }
2024  {
2025  return p_size;
2026  }
2027  bool empty() const
2028  {
2029  return ( size() == 0 );
2030  }
2031 
2033  {
2034  return p_ptr_alloc;
2035  }
2037  {
2038  return p_ptr_alloc;
2039  }
2040 };
2041 
2042 // predefine commonly used iterators
2051 
2052 #endif /* _CONTAINER_CLASSES_H_ */

Generated for cloudy by doxygen 1.8.3.1