cloudy
trunk
|
00001 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and 00002 * others. For conditions of distribution and use see copyright notice in license.txt */ 00003 00004 #ifndef _CONTAINER_CLASSES_H_ 00005 #define _CONTAINER_CLASSES_H_ 00006 00007 void do_dump_state(const void* buf, size_t nelem, size_t size, FILE* out, int32 magic); 00008 void do_restore_state(void* buf, size_t nelem, size_t size, FILE *in, int32 magic); 00009 00015 typedef enum { ARPA_TYPE, C_TYPE, FLX_TYPE, ML_TOP } mem_layout; 00016 00017 // magic numbers to identify each memory layout 00018 static const int32 MA_VERS[ML_TOP] = { 120070905, 220070803, 320071126 }; 00019 00020 #ifdef USE_C_TYPE 00021 #define MEM_LAYOUT_VAL C_TYPE 00022 #else 00023 #define MEM_LAYOUT_VAL ARPA_TYPE 00024 #endif 00025 00026 #ifdef BOUNDS_CHECK 00027 #define lgBOUNDSCHECKVAL true 00028 #else 00029 #define lgBOUNDSCHECKVAL false 00030 #endif 00031 00034 template<class T, int d, mem_layout ALLOC, bool lgBC> 00035 class basic_pntr 00036 { 00037 static const int p_nd = lgBC ? 3 : 1; 00038 T* p_p[p_nd]; // p[0] current pointer, p[1] lower bound, p[2] upper bound 00039 00040 T* p_index_checked ( const ptrdiff_t n ) const 00041 { 00042 T* t = p_p[0]+n; 00043 #ifdef _MSC_VER 00044 /* disable warning that conditional expression is constant, true or false in if */ 00045 # pragma warning( disable : 4127 ) 00046 #endif 00047 if( lgBC ) 00048 { 00049 if( t < p_p[1] || t >= p_p[2] ) 00050 OUT_OF_RANGE( "basic_pntr::p_index_checked()" ); 00051 } 00052 return t; 00053 } 00054 void p_set_vals( T* p0, T* p1, T* p2 ) 00055 { 00056 #ifdef _MSC_VER 00057 /* disable warning that conditional expression is constant, true or false in if */ 00058 # pragma warning( disable : 4127 ) 00059 #endif 00060 if( lgBC ) 00061 { 00062 p_p[0] = p0; p_p[1] = p1; p_p[2] = p2; 00063 } 00064 else 00065 p_p[0] = p0; 00066 } 00067 public: 00068 // constructors 00069 basic_pntr( T* p0, T* p1, T* p2 ) 00070 { 00071 p_set_vals( p0, p1, p2 ); 00072 } 00073 basic_pntr( T* p0 ) 00074 { 00075 p_set_vals( p0, NULL, NULL ); 00076 } 00077 basic_pntr() 00078 { 00079 p_set_vals( NULL, NULL, NULL ); 00080 } 00081 basic_pntr( const basic_pntr& t ) 00082 { 00083 *this = t; 00084 } 00085 // virtual destructor (in case of destruction via basic_pntr*, see Sutter EC++ p77) 00086 virtual ~basic_pntr() {} 00087 // pre-increment 00088 basic_pntr& operator++ () 00089 { 00090 ++p_p[0]; 00091 return *this; 00092 } 00093 // pre-decrement 00094 basic_pntr& operator-- () 00095 { 00096 --p_p[0]; 00097 return *this; 00098 } 00099 // define operators for += and -=, normal arithmetic is defined separately in 00100 // the derived classes; it cannot be done here since they would require implicit 00101 // conversion from basic_pntr -> pntr or const_pntr to work; this would also create 00102 // an implicit and silent conversion from const_pntr -> pntr, which is illegal... 00103 basic_pntr& operator+= ( const ptrdiff_t n ) { p_p[0] += n; return *this; } 00104 basic_pntr& operator-= ( const ptrdiff_t n ) { p_p[0] -= n; return *this; } 00105 // dereference 00106 T& operator* () const 00107 { 00108 return *(p_index_checked(0)); 00109 } 00110 T* operator-> () const 00111 { 00112 return p_index_checked(0); 00113 } 00114 T& operator[] ( const ptrdiff_t n ) const 00115 { 00116 return *(p_index_checked(n)); 00117 } 00118 // finally, define the boolean operators... 00119 bool operator== ( const basic_pntr& t ) const { return p_p[0] == t.p_p[0]; } 00120 bool operator!= ( const basic_pntr& t ) const { return p_p[0] != t.p_p[0]; } 00121 bool operator< ( const basic_pntr& t ) const { return p_p[0] < t.p_p[0]; } 00122 bool operator<= ( const basic_pntr& t ) const { return p_p[0] <= t.p_p[0]; } 00123 bool operator> ( const basic_pntr& t ) const { return p_p[0] > t.p_p[0]; } 00124 bool operator>= ( const basic_pntr& t ) const { return p_p[0] >= t.p_p[0]; } 00125 }; 00126 00128 template<class T, int d, mem_layout ALLOC, bool lgBC> 00129 class pntr : public basic_pntr<T,d,ALLOC,lgBC> 00130 { 00131 public: 00132 // constructors are not inherited, so define them again 00133 pntr( T* p0 ) : basic_pntr<T,d,ALLOC,lgBC>( p0 ) {} 00134 pntr( T* p0, T* p1, T* p2 ) : basic_pntr<T,d,ALLOC,lgBC>( p0, p1, p2 ) {} 00135 pntr() {} 00136 // the increment / decrement operators need to be recast... 00137 // otherwise expressions like p = ++q would be illegal for iterators... 00138 pntr& operator++ () { return static_cast<pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator++()); } 00139 const pntr operator++ (int) { pntr t = *this; ++(*this); return t; } 00140 pntr& operator-- () { return static_cast<pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator--()); } 00141 const pntr operator-- (int) { pntr t = *this; --(*this); return t; } 00142 // define p+n, p-n, p-q 00143 const pntr operator+ ( const ptrdiff_t n ) const { pntr s = *this; s += n; return s; } 00144 const pntr operator- ( const ptrdiff_t n ) const { pntr s = *this; s -= n; return s; } 00145 ptrdiff_t operator- ( const pntr& t ) const { return &(*this[0]) - &t[0]; } 00146 }; 00147 00148 // this defines n+p 00149 template<class T, int d, mem_layout ALLOC, bool lgBC> 00150 inline const pntr<T,d,ALLOC,lgBC> operator+ ( const ptrdiff_t n, const pntr<T,d,ALLOC,lgBC>& t ) 00151 { 00152 pntr<T,d,ALLOC,lgBC> s = t; 00153 s += n; 00154 return s; 00155 } 00156 00158 template<class T, int d, mem_layout ALLOC, bool lgBC> 00159 class const_pntr : public basic_pntr<T,d,ALLOC,lgBC> 00160 { 00161 public: 00162 // constructors are not inherited, so define them again 00163 const_pntr( T* p0 ) : basic_pntr<T,d,ALLOC,lgBC>( p0 ) {} 00164 const_pntr( T* p0, T* p1, T* p2 ) : basic_pntr<T,d,ALLOC,lgBC>( p0, p1, p2 ) {} 00165 const_pntr() {} 00166 // make sure we can assign a pntr to a const_pntr by creating an implicit conversion to const_pntr 00167 const_pntr( const pntr<T,d,ALLOC,lgBC>& t ) : basic_pntr<T,d,ALLOC,lgBC>( t ) {} 00168 // the increment / decrement operators need to be recast... 00169 // otherwise expressions like *p++ = 1. would be legal for const_iterators... 00170 const_pntr& operator++ () { return static_cast<const_pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator++()); } 00171 const const_pntr operator++ (int) { const_pntr t = *this; ++(*this); return t; } 00172 const_pntr& operator-- () { return static_cast<const_pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator--()); } 00173 const const_pntr operator-- (int) { const_pntr t = *this; --(*this); return t; } 00174 const_pntr& operator+= ( const ptrdiff_t n ) 00175 { 00176 return static_cast<const_pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator+=(n)); 00177 } 00178 const_pntr& operator-= ( const ptrdiff_t n ) 00179 { 00180 return static_cast<const_pntr&>(basic_pntr<T,d,ALLOC,lgBC>::operator-=(n)); 00181 } 00182 // the dereference operators need to be recast... 00183 const T& operator* () const { return static_cast<const T&>(basic_pntr<T,d,ALLOC,lgBC>::operator*()); } 00184 const T* operator-> () const { return static_cast<const T*>(basic_pntr<T,d,ALLOC,lgBC>::operator->()); } 00185 const T& operator[] ( const ptrdiff_t n ) const 00186 { 00187 return static_cast<const T&>(basic_pntr<T,d,ALLOC,lgBC>::operator[](n)); 00188 } 00189 // define p+n, p-n, p-q 00190 const const_pntr operator+ ( const ptrdiff_t n ) const { const_pntr s = *this; s += n; return s; } 00191 const const_pntr operator- ( const ptrdiff_t n ) const { const_pntr s = *this; s -= n; return s; } 00192 ptrdiff_t operator- ( const const_pntr& t ) const { return &(*this[0]) - &t[0]; } 00193 }; 00194 00195 // this defines n+p 00196 template<class T, int d, mem_layout ALLOC, bool lgBC> 00197 inline const const_pntr<T,d,ALLOC,lgBC> operator+ ( const ptrdiff_t n, const const_pntr<T,d,ALLOC,lgBC>& t ) 00198 { 00199 const_pntr<T,d,ALLOC,lgBC> s = t; 00200 s += n; 00201 return s; 00202 } 00203 00205 struct tree_vec 00206 { 00207 typedef size_t size_type; 00208 00209 size_type n; 00210 tree_vec *d; 00211 00212 private: 00213 void p_clear0() 00214 { 00215 if( d != NULL ) 00216 { 00217 for( size_type i = 0; i < n; ++i ) 00218 d[i].clear(); 00219 delete[] d; 00220 } 00221 } 00222 void p_clear1() 00223 { 00224 n = 0; 00225 d = NULL; 00226 } 00227 00228 public: 00229 tree_vec() 00230 { 00231 p_clear1(); 00232 } 00233 ~tree_vec() 00234 { 00235 p_clear0(); 00236 } 00237 void clear() 00238 { 00239 p_clear0(); 00240 p_clear1(); 00241 } 00242 const tree_vec& operator= ( const tree_vec& m ) 00243 { 00244 if( &m != this ) 00245 { 00246 clear(); 00247 n = m.n; 00248 if( m.d != NULL ) 00249 { 00250 d = new tree_vec[n]; 00251 tree_vec *p = d; 00252 const tree_vec *mp = m.d; 00253 for( size_type i = 0; i < n; ++i ) 00254 *p++ = *mp++; 00255 } 00256 } 00257 return *this; 00258 } 00259 tree_vec& getvec(const size_type i, const size_type index[]) 00260 { 00261 if( i == 0 ) 00262 return *this; 00263 else 00264 return getvec(i-1,index).d[index[i-1]]; 00265 } 00266 const tree_vec& getvec(const size_type i, const size_type index[]) const 00267 { 00268 if( i == 0 ) 00269 return *this; 00270 else 00271 return getvec(i-1,index).d[index[i-1]]; 00272 } 00273 }; 00274 00277 template<int d,mem_layout ALLOC=MEM_LAYOUT_VAL,bool lgBC=lgBOUNDSCHECKVAL> 00278 class multi_geom 00279 { 00280 public: 00281 typedef size_t size_type; 00282 00283 tree_vec v; 00284 00285 size_type size; 00286 size_type s[d]; 00287 size_type st[d]; 00288 size_type nsl[d]; 00289 00290 private: 00291 void p_clear0() 00292 { 00293 v.clear(); 00294 } 00295 void p_clear1() 00296 { 00297 size = 0; 00298 for( int i=0; i < d; ++i ) 00299 { 00300 s[i] = 0; 00301 st[i] = 0; 00302 nsl[i] = 0; 00303 } 00304 } 00305 00306 public: 00307 multi_geom() 00308 { 00309 p_clear1(); 00310 } 00311 ~multi_geom() 00312 { 00313 p_clear0(); 00314 } 00315 void clear() 00316 { 00317 p_clear0(); 00318 p_clear1(); 00319 } 00320 const multi_geom& operator= ( const multi_geom& m ) 00321 { 00322 if( &m != this ) 00323 { 00324 clear(); 00325 v = m.v; 00326 size = m.size; 00327 for( int i=0; i < d; ++i ) 00328 { 00329 s[i] = m.s[i]; 00330 st[i] = m.st[i]; 00331 nsl[i] = m.nsl[i]; 00332 } 00333 } 00334 return *this; 00335 } 00336 bool lgInbounds(const size_type n, const size_type index[]) const 00337 { 00338 if( n != 0 ) 00339 return ( lgInbounds(n-1,index) && index[n-1] < v.getvec(n-1,index).n ); 00340 else 00341 return true; 00342 } 00343 void reserve(const size_type n, const size_type index[]) 00344 { 00345 ASSERT( n <= d && index[n-1] > 0 && lgInbounds( n-1, index ) ); 00346 00347 tree_vec& w = v.getvec( n-1, index ); 00348 if( d > n ) 00349 { 00350 ASSERT( w.d == NULL ); 00351 w.d = new tree_vec[ index[n-1] ]; 00352 } 00353 w.n = index[n-1]; 00354 s[n-1] = max(s[n-1],index[n-1]); 00355 nsl[n-1] += index[n-1]; 00356 } 00357 void reserve_recursive(const size_type n, size_type index[]) 00358 { 00359 if( n == 0 ) 00360 { 00361 reserve( n+1, index ); 00362 if( n+1 < d ) 00363 reserve_recursive( n+1, index ); 00364 } 00365 else 00366 { 00367 size_type top = index[n-1]; 00368 for( size_type i=0; i < top; ++i ) 00369 { 00370 index[n-1] = i; 00371 reserve( n+1, index ); 00372 if( n+1 < d ) 00373 reserve_recursive( n+1, index ); 00374 } 00375 index[n-1] = top; 00376 } 00377 } 00378 void finalize(void) 00379 { 00380 #ifdef _MSC_VER 00381 /* disable warning that conditional expression is constant, true or false in if */ 00382 # pragma warning( disable : 4127 ) 00383 #endif 00384 if( ALLOC == ARPA_TYPE ) 00385 { 00386 size_type n1[d], n2[d]; 00387 for( int dim=0; dim < d; ++dim ) 00388 n1[dim] = n2[dim] = 0L; 00389 // sanity checks 00390 p_setupArray( n1, n2, &v, 0 ); 00391 for( int dim=0; dim < d-1; ++dim ) 00392 ASSERT( n1[dim] == nsl[dim] && n2[dim] == nsl[dim+1] ); 00393 size = nsl[d-1]; 00394 } 00395 else if( ALLOC == C_TYPE ) 00396 { 00397 st[d-1] = s[d-1]; 00398 for( int i = d-2; i >= 0; --i ) 00399 st[i] = st[i+1]*s[i]; 00400 size = st[0]; 00401 } 00402 else 00403 { 00404 TotalInsanity(); 00405 } 00406 } 00407 00408 private: 00409 void p_setupArray( size_type n1[], size_type n2[], const tree_vec* w, int l ) 00410 { 00411 for( size_type i=0; i < w->n; ++i ) 00412 { 00413 n1[l]++; 00414 if( l < d-2 ) 00415 { 00416 p_setupArray( n1, n2, &w->d[i], l+1 ); 00417 } 00418 n2[l] += w->d[i].n; 00419 } 00420 } 00421 }; 00422 00423 00424 // 00527 // 00528 00529 00530 // forward definitions 00531 template<class T, int N, mem_layout ALLOC, bool lgBC> class n_pointer; 00532 template<class T, int N, mem_layout ALLOC, bool lgBC> class const_n_pointer; 00533 00534 template<class T, int N> 00535 class n_pointer<T,N,ARPA_TYPE,false> 00536 { 00537 T* p_p; 00538 const size_t* p_st; 00539 const tree_vec* p_v; 00540 public: 00541 n_pointer(T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {} 00542 const n_pointer<T,N-1,ARPA_TYPE,false> operator[] (const size_t i) const 00543 { 00544 return n_pointer<T,N-1,ARPA_TYPE,false>( *((T**)p_p+i) ); 00545 } 00546 }; 00547 00548 template<class T, int N> 00549 class n_pointer<T,N,C_TYPE,false> 00550 { 00551 T* p_p; 00552 const size_t* p_st; 00553 const tree_vec* p_v; 00554 public: 00555 n_pointer(T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {} 00556 const n_pointer<T,N-1,C_TYPE,false> operator[] (const size_t i) const 00557 { 00558 return n_pointer<T,N-1,C_TYPE,false>( p_p+i*p_st[0], p_st+1 ); 00559 } 00560 }; 00561 00562 template<class T> 00563 class n_pointer<T,1,ARPA_TYPE,false> 00564 { 00565 T* p_p; 00566 const size_t* p_st; 00567 const tree_vec* p_v; 00568 public: 00569 n_pointer(T* p, const size_t* st=NULL, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {} 00570 T& operator[] (const size_t i) const 00571 { 00572 return *(p_p + i); 00573 } 00574 }; 00575 00576 template<class T> 00577 class n_pointer<T,1,C_TYPE,false> 00578 { 00579 T* p_p; 00580 const size_t* p_st; 00581 const tree_vec* p_v; 00582 public: 00583 n_pointer(T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {} 00584 T& operator[] (const size_t i) const 00585 { 00586 return *(p_p + i); 00587 } 00588 }; 00589 00590 template<class T, int N> 00591 class n_pointer<T,N,ARPA_TYPE,true> 00592 { 00593 T* p_p; 00594 const size_t* p_st; 00595 const tree_vec* p_v; 00596 public: 00597 n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00598 const n_pointer<T,N-1,ARPA_TYPE,true> operator[] (const size_t i) const 00599 { 00600 if( i >= p_v->n ) 00601 OUT_OF_RANGE( "n_pointer::operator[]" ); 00602 return n_pointer<T,N-1,ARPA_TYPE,true>( *((T**)p_p+i), NULL, &p_v->d[i] ); 00603 } 00604 }; 00605 00606 template<class T, int N> 00607 class n_pointer<T,N,C_TYPE,true> 00608 { 00609 T* p_p; 00610 const size_t* p_st; 00611 const tree_vec* p_v; 00612 public: 00613 n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00614 const n_pointer<T,N-1,C_TYPE,true> operator[] (const size_t i) const 00615 { 00616 if( i >= p_v->n ) 00617 OUT_OF_RANGE( "n_pointer::operator[]" ); 00618 return n_pointer<T,N-1,C_TYPE,true>( p_p+i*p_st[0], p_st+1, &p_v->d[i] ); 00619 } 00620 }; 00621 00622 template<class T> 00623 class n_pointer<T,1,ARPA_TYPE,true> 00624 { 00625 T* p_p; 00626 const size_t* p_st; 00627 const tree_vec* p_v; 00628 public: 00629 n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00630 T& operator[] (const size_t i) const 00631 { 00632 if( i >= p_v->n ) 00633 OUT_OF_RANGE( "n_pointer::operator[]" ); 00634 return *(p_p + i); 00635 } 00636 }; 00637 00638 template<class T> 00639 class n_pointer<T,1,C_TYPE,true> 00640 { 00641 T* p_p; 00642 const size_t* p_st; 00643 const tree_vec* p_v; 00644 public: 00645 n_pointer(T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00646 T& operator[] (const size_t i) const 00647 { 00648 if( i >= p_v->n ) 00649 OUT_OF_RANGE( "n_pointer::operator[]" ); 00650 return *(p_p + i); 00651 } 00652 }; 00653 00654 template<class T, int N> 00655 class const_n_pointer<T,N,ARPA_TYPE,false> 00656 { 00657 const T* p_p; 00658 const size_t* p_st; 00659 const tree_vec* p_v; 00660 public: 00661 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) {} 00662 const const_n_pointer<T,N-1,ARPA_TYPE,false> operator[] (const size_t i) const 00663 { 00664 return const_n_pointer<T,N-1,ARPA_TYPE,false>( *((T**)p_p+i) ); 00665 } 00666 }; 00667 00668 template<class T, int N> 00669 class const_n_pointer<T,N,C_TYPE,false> 00670 { 00671 const T* p_p; 00672 const size_t* p_st; 00673 const tree_vec* p_v; 00674 public: 00675 const_n_pointer(const T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {} 00676 const const_n_pointer<T,N-1,C_TYPE,false> operator[] (const size_t i) const 00677 { 00678 return const_n_pointer<T,N-1,C_TYPE,false>( p_p+i*p_st[0], p_st+1 ); 00679 } 00680 }; 00681 00682 template<class T> 00683 class const_n_pointer<T,1,ARPA_TYPE,false> 00684 { 00685 const T* p_p; 00686 const size_t* p_st; 00687 const tree_vec* p_v; 00688 public: 00689 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) {} 00690 const T& operator[] (const size_t i) const 00691 { 00692 return *(p_p + i); 00693 } 00694 }; 00695 00696 template<class T> 00697 class const_n_pointer<T,1,C_TYPE,false> 00698 { 00699 const T* p_p; 00700 const size_t* p_st; 00701 const tree_vec* p_v; 00702 public: 00703 const_n_pointer(const T* p, const size_t* st, const tree_vec* v=NULL) : p_p(p), p_st(st), p_v(v) {} 00704 const T& operator[] (const size_t i) const 00705 { 00706 return *(p_p + i); 00707 } 00708 }; 00709 00710 template<class T, int N> 00711 class const_n_pointer<T,N,ARPA_TYPE,true> 00712 { 00713 const T* p_p; 00714 const size_t* p_st; 00715 const tree_vec* p_v; 00716 public: 00717 const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00718 const const_n_pointer<T,N-1,ARPA_TYPE,true> operator[] (const size_t i) const 00719 { 00720 if( i >= p_v->n ) 00721 OUT_OF_RANGE( "const_n_pointer::operator[]" ); 00722 return const_n_pointer<T,N-1,ARPA_TYPE,true>( *((T**)p_p+i), NULL, &p_v->d[i] ); 00723 } 00724 }; 00725 00726 template<class T, int N> 00727 class const_n_pointer<T,N,C_TYPE,true> 00728 { 00729 const T* p_p; 00730 const size_t* p_st; 00731 const tree_vec* p_v; 00732 public: 00733 const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00734 const const_n_pointer<T,N-1,C_TYPE,true> operator[] (const size_t i) const 00735 { 00736 if( i >= p_v->n ) 00737 OUT_OF_RANGE( "const_n_pointer::operator[]" ); 00738 return const_n_pointer<T,N-1,C_TYPE,true>( p_p+i*p_st[0], p_st+1, &p_v->d[i] ); 00739 } 00740 }; 00741 00742 template<class T> 00743 class const_n_pointer<T,1,ARPA_TYPE,true> 00744 { 00745 const T* p_p; 00746 const size_t* p_st; 00747 const tree_vec* p_v; 00748 public: 00749 const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00750 const T& operator[] (const size_t i) const 00751 { 00752 if( i >= p_v->n ) 00753 OUT_OF_RANGE( "const_n_pointer::operator[]" ); 00754 return *(p_p + i); 00755 } 00756 }; 00757 00758 template<class T> 00759 class const_n_pointer<T,1,C_TYPE,true> 00760 { 00761 const T* p_p; 00762 const size_t* p_st; 00763 const tree_vec* p_v; 00764 public: 00765 const_n_pointer(const T* p, const size_t* st, const tree_vec* v) : p_p(p), p_st(st), p_v(v) {} 00766 const T& operator[] (const size_t i) const 00767 { 00768 if( i >= p_v->n ) 00769 OUT_OF_RANGE( "const_n_pointer::operator[]" ); 00770 return *(p_p + i); 00771 } 00772 }; 00773 00774 // 00898 // 00899 00900 template<class T, int d, mem_layout ALLOC=MEM_LAYOUT_VAL, bool lgBC=lgBOUNDSCHECKVAL> 00901 class multi_arr 00902 { 00903 // ancillary data describing the memory layout of the multi_arr 00904 multi_geom<d,ALLOC,lgBC> p_g; 00905 T** p_psl[d-1]; // pointer arrays for ARPA structure 00906 valarray<T> p_dsl; // this contains the actual data 00907 T* p_ptr; // main pointer to allocated structure 00908 T** p_ptr2; // used in debugger to get access to internal representation 00909 T*** p_ptr3; 00910 T**** p_ptr4; 00911 T***** p_ptr5; 00912 T****** p_ptr6; 00913 00914 public: 00915 typedef random_access_iterator_tag iterator_category; 00916 typedef T value_type; 00917 typedef T& reference; 00918 typedef const T& const_reference; 00919 typedef T* pointer; 00920 typedef const T* const_pointer; 00921 typedef size_t size_type; 00922 typedef ptrdiff_t difference_type; 00923 typedef pntr<T,d,ALLOC,lgBC> iterator; 00924 typedef const_pntr<T,d,ALLOC,lgBC> const_iterator; 00925 00926 private: 00927 static const size_type npos = static_cast<size_type>(-1); 00928 00929 void p_clear0() 00930 { 00931 p_g.clear(); 00932 for( int i=0; i < d-1; ++i ) 00933 delete[] p_psl[i]; 00934 p_dsl.resize(0); 00935 } 00936 void p_clear1() 00937 { 00938 for( int i=0; i < d-1; ++i ) 00939 p_psl[i] = NULL; 00940 p_ptr = NULL; 00941 p_ptr2 = NULL; 00942 p_ptr3 = NULL; 00943 p_ptr4 = NULL; 00944 p_ptr5 = NULL; 00945 p_ptr6 = NULL; 00946 } 00947 00948 public: 00949 multi_arr() 00950 { 00951 p_clear1(); 00952 } 00953 multi_arr(const multi_geom<d,ALLOC,lgBC>& g) 00954 { 00955 p_clear1(); 00956 alloc( g ); 00957 } 00958 multi_arr(size_type d1, size_type d2, size_type d3=0, size_type d4=0, size_type d5=0, size_type d6=0) 00959 { 00960 p_clear1(); 00961 size_type index[] = { d1, d2, d3, d4, d5, d6 }; 00962 alloc( index ); 00963 } 00964 ~multi_arr() 00965 { 00966 p_clear0(); 00967 } 00968 void clear() 00969 { 00970 p_clear0(); 00971 p_clear1(); 00972 } 00973 const multi_arr& operator= ( const multi_arr& m ) 00974 { 00975 if( &m != this ) 00976 { 00977 clear(); 00978 p_g = m.p_g; 00979 alloc(); 00980 vals() = m.vals(); 00981 } 00982 return *this; 00983 } 00984 void zero() 00985 { 00986 ASSERT( vals().size() == p_g.size ); 00987 memset( data(), 0, p_g.size*sizeof(T) ); 00988 } 00989 void invalidate() 00990 { 00991 ASSERT( vals().size() == p_g.size ); 00992 invalidate_array( data(), p_g.size*sizeof(T) ); 00993 } 00994 void state_do(FILE *io, bool lgGet) 00995 { 00996 if( lgGet ) 00997 restore_state(io); 00998 else 00999 dump_state(io); 01000 } 01001 // dump the array to a file in binary format 01002 void dump_state(FILE *out) const 01003 { 01004 do_dump_state( data(), p_g.size, sizeof(T), out, MA_VERS[ALLOC] ); 01005 } 01006 // restore the array from a file in binary format 01007 void restore_state(FILE *in) 01008 { 01009 do_restore_state( data(), p_g.size, sizeof(T), in, MA_VERS[ALLOC] ); 01010 } 01011 01012 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) 01013 { 01014 const size_type index[] = { i1, i2, i3, i4, i5, i6 }; 01015 size_type n = d; 01016 while( n > 1 && index[n-1] == 0 ) 01017 --n; 01018 p_g.reserve( n, index ); 01019 } 01020 void alloc() 01021 { 01022 ASSERT( p_ptr == NULL ); 01023 p_g.finalize(); 01024 #ifdef _MSC_VER 01025 /* disable warning that conditional expression is constant, true or false in if */ 01026 # pragma warning( disable : 4127 ) 01027 #endif 01028 if( ALLOC == ARPA_TYPE ) 01029 { 01030 size_type n1[d], n2[d]; 01031 // allocate the pointer arrays ( p_psl[0..d-2] ) and data ( p_dsl ) 01032 for( int dim=0; dim < d; ++dim ) 01033 { 01034 n1[dim] = n2[dim] = 0L; 01035 if( dim != d-1 ) 01036 { 01037 ASSERT( p_psl[dim] == NULL ); 01038 p_psl[dim] = new T*[ p_g.nsl[dim] ]; 01039 } 01040 else 01041 { 01042 ASSERT( p_dsl.size() == 0 ); 01043 p_dsl.resize( p_g.nsl[dim] ); 01044 } 01045 } 01046 // now initialize all the pointer arrays 01047 p_setupArray( n1, n2, &p_g.v, 0 ); 01048 p_ptr = (T*)p_psl[0]; 01049 } 01050 else if( ALLOC == C_TYPE ) 01051 { 01052 p_dsl.resize( p_g.st[0] ); 01053 p_ptr = &p_dsl[0]; 01054 } 01055 else 01056 { 01057 TotalInsanity(); 01058 } 01059 p_ptr2 = (T**)p_ptr; 01060 p_ptr3 = (T***)p_ptr; 01061 p_ptr4 = (T****)p_ptr; 01062 p_ptr5 = (T*****)p_ptr; 01063 p_ptr6 = (T******)p_ptr; 01064 } 01065 // clone the geometry from another multi_arr 01066 void alloc(const multi_geom<d,ALLOC,lgBC>& g) 01067 { 01068 if( &g != &p_g ) 01069 { 01070 clear(); 01071 p_g = g; 01072 alloc(); 01073 } 01074 } 01075 // set up a rectangular block of data with dimensions d1 x d2 x .... 01076 void alloc(size_type d1, size_type d2, size_type d3=0, size_type d4=0, size_type d5=0, size_type d6=0) 01077 { 01078 size_type index[] = { d1, d2, d3, d4, d5, d6 }; 01079 alloc( index ); 01080 } 01081 void alloc(size_type index[]) 01082 { 01083 for( int n=0; n < d; n++ ) 01084 ASSERT( index[n] > 0 ); 01085 clear(); 01086 p_g.reserve_recursive( 0, index ); 01087 alloc(); 01088 } 01089 01090 private: 01091 // helper routine for alloc(), this fills in the pointer arrays for the ARPA layout 01092 void p_setupArray( size_type n1[], size_type n2[], const tree_vec* g, int l ) 01093 { 01094 for( size_type i=0; i < g->n; ++i ) 01095 { 01096 if( l < d-2 ) 01097 { 01098 p_psl[l][n1[l]++] = (T*)(p_psl[l+1]+n2[l]); 01099 p_setupArray( n1, n2, &g->d[i], l+1 ); 01100 } 01101 else 01102 { 01103 p_psl[l][n1[l]++] = &p_dsl[0]+n2[l]; 01104 } 01105 n2[l] += g->d[i].n; 01106 } 01107 } 01108 01109 // in the p_iterator methods the bound-checking part is split off into a separate 01110 // routine p_iterator_bc in order to make it easier for compilers to inline the code 01111 iterator p_iterator(size_type i1, size_type i2) const 01112 { 01113 #ifdef _MSC_VER 01114 /* disable warning that conditional expression is constant, true or false in if */ 01115 # pragma warning( disable : 4127 ) 01116 #endif 01117 if( lgBC ) 01118 return p_iterator_bc( i1, i2 ); 01119 else 01120 { 01121 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01122 return iterator( &(*t)[i1][i2] ); 01123 } 01124 } 01125 iterator p_iterator_bc(size_type i1, size_type i2) const 01126 { 01127 size_type index[] = { i1 }; 01128 if( p_g.lgInbounds( 1, index ) ) 01129 { 01130 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01131 size_type n = p_g.v.getvec( 1, index ).n; 01132 T* s = ( n > 0 ) ? &(*t)[i1][0] : NULL; 01133 if( i2 == npos ) 01134 return iterator( s+n, s, s+n ); 01135 else 01136 return iterator( s+i2, s, s+n ); 01137 } 01138 else 01139 OUT_OF_RANGE( "multi_arr::p_iterator()" ); 01140 } 01141 iterator p_iterator(size_type i1, size_type i2, size_type i3) const 01142 { 01143 #ifdef _MSC_VER 01144 /* disable warning that conditional expression is constant, true or false in if */ 01145 # pragma warning( disable : 4127 ) 01146 #endif 01147 if( lgBC ) 01148 return p_iterator_bc( i1, i2, i3 ); 01149 else 01150 { 01151 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01152 return iterator( &(*t)[i1][i2][i3] ); 01153 } 01154 } 01155 iterator p_iterator_bc(size_type i1, size_type i2, size_type i3) const 01156 { 01157 size_type index[] = { i1, i2 }; 01158 if( p_g.lgInbounds( 2, index ) ) 01159 { 01160 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01161 size_type n = p_g.v.getvec( 2, index ).n; 01162 T* s = ( n > 0 ) ? &(*t)[i1][i2][0] : NULL; 01163 if( i3 == npos ) 01164 return iterator( s+n, s, s+n ); 01165 else 01166 return iterator( s+i3, s, s+n ); 01167 } 01168 else 01169 OUT_OF_RANGE( "multi_arr::p_iterator()" ); 01170 } 01171 iterator p_iterator(size_type i1, size_type i2, size_type i3, size_type i4) const 01172 { 01173 #ifdef _MSC_VER 01174 /* disable warning that conditional expression is constant, true or false in if */ 01175 # pragma warning( disable : 4127 ) 01176 #endif 01177 if( lgBC ) 01178 return p_iterator_bc(i1, i2, i3, i4); 01179 else 01180 { 01181 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01182 return iterator( &(*t)[i1][i2][i3][i4] ); 01183 } 01184 } 01185 iterator p_iterator_bc(size_type i1, size_type i2, size_type i3, size_type i4) const 01186 { 01187 size_type index[] = { i1, i2, i3 }; 01188 if( p_g.lgInbounds( 3, index ) ) 01189 { 01190 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01191 size_type n = p_g.v.getvec( 3, index ).n; 01192 T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][0] : NULL; 01193 if( i4 == npos ) 01194 return iterator( s+n, s, s+n ); 01195 else 01196 return iterator( s+i4, s, s+n ); 01197 } 01198 else 01199 OUT_OF_RANGE( "multi_arr::p_iterator()" ); 01200 } 01201 iterator p_iterator(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01202 { 01203 #ifdef _MSC_VER 01204 /* disable warning that conditional expression is constant, true or false in if */ 01205 # pragma warning( disable : 4127 ) 01206 #endif 01207 if( lgBC ) 01208 return p_iterator_bc(i1, i2, i3, i4, i5); 01209 else 01210 { 01211 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01212 return iterator( &(*t)[i1][i2][i3][i4][i5] ); 01213 } 01214 } 01215 iterator p_iterator_bc(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01216 { 01217 size_type index[] = { i1, i2, i3, i4 }; 01218 if( p_g.lgInbounds( 4, index ) ) 01219 { 01220 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01221 size_type n = p_g.v.getvec( 4, index ).n; 01222 T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][i4][0] : NULL; 01223 if( i5 == npos ) 01224 return iterator( s+n, s, s+n ); 01225 else 01226 return iterator( s+i5, s, s+n ); 01227 } 01228 else 01229 OUT_OF_RANGE( "multi_arr::p_iterator()" ); 01230 } 01231 iterator p_iterator(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const 01232 { 01233 #ifdef _MSC_VER 01234 /* disable warning that conditional expression is constant, true or false in if */ 01235 # pragma warning( disable : 4127 ) 01236 #endif 01237 if( lgBC ) 01238 return p_iterator_bc(i1, i2, i3, i4, i5, i6); 01239 else 01240 { 01241 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01242 return iterator( &(*t)[i1][i2][i3][i4][i5][i6] ); 01243 } 01244 } 01245 iterator p_iterator_bc(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const 01246 { 01247 size_type index[] = { i1, i2, i3, i4, i5 }; 01248 if( p_g.lgInbounds( 5, index ) ) 01249 { 01250 multi_arr<T,d,ALLOC,lgBC>* t = const_cast<multi_arr<T,d,ALLOC,lgBC>*>(this); 01251 size_type n = p_g.v.getvec( 5, index ).n; 01252 T* s = ( n > 0 ) ? &(*t)[i1][i2][i3][i4][i5][0] : NULL; 01253 if( i6 == npos ) 01254 return iterator( s+n, s, s+n ); 01255 else 01256 return iterator( s+i6, s, s+n ); 01257 } 01258 else 01259 OUT_OF_RANGE( "multi_arr::p_iterator()" ); 01260 } 01261 01262 public: 01263 const n_pointer<T,d,ALLOC,lgBC> n_ptr() 01264 { 01265 return n_pointer<T,d,ALLOC,lgBC>( p_ptr, p_g.st+1, &p_g.v ); 01266 } 01267 const const_n_pointer<T,d,ALLOC,lgBC> n_ptr() const 01268 { 01269 return const_n_pointer<T,d,ALLOC,lgBC>( p_ptr, p_g.st+1, &p_g.v ); 01270 } 01271 const n_pointer<T,d-1,ALLOC,lgBC> operator[] (size_type i) 01272 { 01273 return n_ptr()[i]; 01274 } 01275 const const_n_pointer<T,d-1,ALLOC,lgBC> operator[] (size_type i) const 01276 { 01277 return n_ptr()[i]; 01278 } 01279 01280 reference at(size_type i1, size_type i2) 01281 { 01282 size_type index[] = { i1, i2 }; 01283 if( !p_g.lgInbounds( 2, index ) ) 01284 OUT_OF_RANGE( "multi_arr::at()" ); 01285 return (*this)[i1][i2]; 01286 } 01287 const_reference at(size_type i1, size_type i2) const 01288 { 01289 size_type index[] = { i1, i2 }; 01290 if( !p_g.lgInbounds( 2, index ) ) 01291 OUT_OF_RANGE( "multi_arr::at()" ); 01292 return (*this)[i1][i2]; 01293 } 01294 reference at(size_type i1, size_type i2, size_type i3) 01295 { 01296 size_type index[] = { i1, i2, i3 }; 01297 if( !p_g.lgInbounds( 3, index ) ) 01298 OUT_OF_RANGE( "multi_arr::at()" ); 01299 return (*this)[i1][i2][i3]; 01300 } 01301 const_reference at(size_type i1, size_type i2, size_type i3) const 01302 { 01303 size_type index[] = { i1, i2, i3 }; 01304 if( !p_g.lgInbounds( 3, index ) ) 01305 OUT_OF_RANGE( "multi_arr::at()" ); 01306 return (*this)[i1][i2][i3]; 01307 } 01308 reference at(size_type i1, size_type i2, size_type i3, size_type i4) 01309 { 01310 size_type index[] = { i1, i2, i3, i4 }; 01311 if( !p_g.lgInbounds( 4, index ) ) 01312 OUT_OF_RANGE( "multi_arr::at()" ); 01313 return (*this)[i1][i2][i3][i4]; 01314 } 01315 const_reference at(size_type i1, size_type i2, size_type i3, size_type i4) const 01316 { 01317 size_type index[] = { i1, i2, i3, i4 }; 01318 if( !p_g.lgInbounds( 4, index ) ) 01319 OUT_OF_RANGE( "multi_arr::at()" ); 01320 return (*this)[i1][i2][i3][i4]; 01321 } 01322 reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) 01323 { 01324 size_type index[] = { i1, i2, i3, i4, i5 }; 01325 if( !p_g.lgInbounds( 5, index ) ) 01326 OUT_OF_RANGE( "multi_arr::at()" ); 01327 return (*this)[i1][i2][i3][i4][i5]; 01328 } 01329 const_reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01330 { 01331 size_type index[] = { i1, i2, i3, i4, i5 }; 01332 if( !p_g.lgInbounds( 5, index ) ) 01333 OUT_OF_RANGE( "multi_arr::at()" ); 01334 return (*this)[i1][i2][i3][i4][i5]; 01335 } 01336 reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) 01337 { 01338 size_type index[] = { i1, i2, i3, i4, i5, i6 }; 01339 if( !p_g.lgInbounds( 6, index ) ) 01340 OUT_OF_RANGE( "multi_arr::at()" ); 01341 return (*this)[i1][i2][i3][i4][i5][i6]; 01342 } 01343 const_reference at(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const 01344 { 01345 size_type index[] = { i1, i2, i3, i4, i5, i6 }; 01346 if( !p_g.lgInbounds( 6, index ) ) 01347 OUT_OF_RANGE( "multi_arr::at()" ); 01348 return (*this)[i1][i2][i3][i4][i5][i6]; 01349 } 01350 01351 iterator ptr(size_type i1, size_type i2) 01352 { 01353 return p_iterator(i1, i2); 01354 } 01355 const_iterator ptr(size_type i1, size_type i2) const 01356 { 01357 return p_iterator(i1, i2); 01358 } 01359 iterator ptr(size_type i1, size_type i2, size_type i3) 01360 { 01361 return p_iterator(i1, i2, i3); 01362 } 01363 const_iterator ptr(size_type i1, size_type i2, size_type i3) const 01364 { 01365 return p_iterator(i1, i2, i3); 01366 } 01367 iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4) 01368 { 01369 return p_iterator(i1, i2, i3, i4); 01370 } 01371 const_iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4) const 01372 { 01373 return p_iterator(i1, i2, i3, i4); 01374 } 01375 iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) 01376 { 01377 return p_iterator(i1, i2, i3, i4, i5); 01378 } 01379 const_iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01380 { 01381 return p_iterator(i1, i2, i3, i4, i5); 01382 } 01383 iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) 01384 { 01385 return p_iterator(i1, i2, i3, i4, i5, i6); 01386 } 01387 const_iterator ptr(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5, size_type i6) const 01388 { 01389 return p_iterator(i1, i2, i3, i4, i5, i6); 01390 } 01391 01392 iterator begin(size_type i1) 01393 { 01394 return p_iterator(i1, 0); 01395 } 01396 const_iterator begin(size_type i1) const 01397 { 01398 return p_iterator(i1, 0); 01399 } 01400 iterator begin(size_type i1, size_type i2) 01401 { 01402 return p_iterator(i1, i2, 0); 01403 } 01404 const_iterator begin(size_type i1, size_type i2) const 01405 { 01406 return p_iterator(i1, i2, 0); 01407 } 01408 iterator begin(size_type i1, size_type i2, size_type i3) 01409 { 01410 return p_iterator(i1, i2, i3, 0); 01411 } 01412 const_iterator begin(size_type i1, size_type i2, size_type i3) const 01413 { 01414 return p_iterator(i1, i2, i3, 0); 01415 } 01416 iterator begin(size_type i1, size_type i2, size_type i3, size_type i4) 01417 { 01418 return p_iterator(i1, i2, i3, i4, 0); 01419 } 01420 const_iterator begin(size_type i1, size_type i2, size_type i3, size_type i4) const 01421 { 01422 return p_iterator(i1, i2, i3, i4, 0); 01423 } 01424 iterator begin(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) 01425 { 01426 return p_iterator(i1, i2, i3, i4, i5, 0); 01427 } 01428 const_iterator begin(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01429 { 01430 return p_iterator(i1, i2, i3, i4, i5, 0); 01431 } 01432 01433 iterator end(size_type i1) 01434 { 01435 #ifdef _MSC_VER 01436 /* disable warning that conditional expression is constant, true or false in if */ 01437 # pragma warning( disable : 4127 ) 01438 #endif 01439 if( lgBC ) 01440 return p_iterator(i1, npos); 01441 else 01442 return p_iterator(i1, p_g.v.d[i1].n); 01443 } 01444 const_iterator end(size_type i1) const 01445 { 01446 #ifdef _MSC_VER 01447 /* disable warning that conditional expression is constant, true or false in if */ 01448 # pragma warning( disable : 4127 ) 01449 #endif 01450 if( lgBC ) 01451 return p_iterator(i1, npos); 01452 else 01453 return p_iterator(i1, p_g.v.d[i1].n); 01454 } 01455 iterator end(size_type i1, size_type i2) 01456 { 01457 #ifdef _MSC_VER 01458 /* disable warning that conditional expression is constant, true or false in if */ 01459 # pragma warning( disable : 4127 ) 01460 #endif 01461 if( lgBC ) 01462 return p_iterator(i1, i2, npos); 01463 else 01464 return p_iterator(i1, i2, p_g.v.d[i1].d[i2].n); 01465 } 01466 const_iterator end(size_type i1, size_type i2) const 01467 { 01468 #ifdef _MSC_VER 01469 /* disable warning that conditional expression is constant, true or false in if */ 01470 # pragma warning( disable : 4127 ) 01471 #endif 01472 if( lgBC ) 01473 return p_iterator(i1, i2, npos); 01474 else 01475 return p_iterator(i1, i2, p_g.v.d[i1].d[i2].n); 01476 } 01477 iterator end(size_type i1, size_type i2, size_type i3) 01478 { 01479 #ifdef _MSC_VER 01480 /* disable warning that conditional expression is constant, true or false in if */ 01481 # pragma warning( disable : 4127 ) 01482 #endif 01483 if( lgBC ) 01484 return p_iterator(i1, i2, i3, npos); 01485 else 01486 return p_iterator(i1, i2, i3, p_g.v.d[i1].d[i2].d[i3].n); 01487 } 01488 const_iterator end(size_type i1, size_type i2, size_type i3) const 01489 { 01490 #ifdef _MSC_VER 01491 /* disable warning that conditional expression is constant, true or false in if */ 01492 # pragma warning( disable : 4127 ) 01493 #endif 01494 if( lgBC ) 01495 return p_iterator(i1, i2, i3, npos); 01496 else 01497 return p_iterator(i1, i2, i3, p_g.v.d[i1].d[i2].d[i3].n); 01498 } 01499 iterator end(size_type i1, size_type i2, size_type i3, size_type i4) 01500 { 01501 #ifdef _MSC_VER 01502 /* disable warning that conditional expression is constant, true or false in if */ 01503 # pragma warning( disable : 4127 ) 01504 #endif 01505 if( lgBC ) 01506 return p_iterator(i1, i2, i3, i4, npos); 01507 else 01508 return p_iterator(i1, i2, i3, i4, p_g.v.d[i1].d[i2].d[i3].d[i4].n); 01509 } 01510 const_iterator end(size_type i1, size_type i2, size_type i3, size_type i4) const 01511 { 01512 #ifdef _MSC_VER 01513 /* disable warning that conditional expression is constant, true or false in if */ 01514 # pragma warning( disable : 4127 ) 01515 #endif 01516 if( lgBC ) 01517 return p_iterator(i1, i2, i3, i4, npos); 01518 else 01519 return p_iterator(i1, i2, i3, i4, p_g.v.d[i1].d[i2].d[i3].d[i4].n); 01520 } 01521 iterator end(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) 01522 { 01523 #ifdef _MSC_VER 01524 /* disable warning that conditional expression is constant, true or false in if */ 01525 # pragma warning( disable : 4127 ) 01526 #endif 01527 if( lgBC ) 01528 return p_iterator(i1, i2, i3, i4, i5, npos); 01529 else 01530 return p_iterator(i1, i2, i3, i4, i5, p_g.v.d[i1].d[i2].d[i3].d[i4].d[i5].n); 01531 } 01532 const_iterator end(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01533 { 01534 #ifdef _MSC_VER 01535 /* disable warning that conditional expression is constant, true or false in if */ 01536 # pragma warning( disable : 4127 ) 01537 #endif 01538 if( lgBC ) 01539 return p_iterator(i1, i2, i3, i4, i5, npos); 01540 else 01541 return p_iterator(i1, i2, i3, i4, i5, p_g.v.d[i1].d[i2].d[i3].d[i4].d[i5].n); 01542 } 01543 01544 reference front(size_type i1) 01545 { 01546 return *begin(i1); 01547 } 01548 const_reference front(size_type i1) const 01549 { 01550 return *begin(i1); 01551 } 01552 reference front(size_type i1, size_type i2) 01553 { 01554 return *begin(i1, i2); 01555 } 01556 const_reference front(size_type i1, size_type i2) const 01557 { 01558 return *begin(i1, i2); 01559 } 01560 reference front(size_type i1, size_type i2, size_type i3) 01561 { 01562 return *begin(i1, i2, i3); 01563 } 01564 const_reference front(size_type i1, size_type i2, size_type i3) const 01565 { 01566 return *begin(i1, i2, i3); 01567 } 01568 reference front(size_type i1, size_type i2, size_type i3, size_type i4) 01569 { 01570 return *begin(i1, i2, i3, i4); 01571 } 01572 const_reference front(size_type i1, size_type i2, size_type i3, size_type i4) const 01573 { 01574 return *begin(i1, i2, i3, i4); 01575 } 01576 reference front(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) 01577 { 01578 return *begin(i1, i2, i3, i4, i5); 01579 } 01580 const_reference front(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01581 { 01582 return *begin(i1, i2, i3, i4, i5); 01583 } 01584 01585 reference back(size_type i1) 01586 { 01587 return *(end(i1) - 1); 01588 } 01589 const_reference back(size_type i1) const 01590 { 01591 return *(end(i1) - 1); 01592 } 01593 reference back(size_type i1, size_type i2) 01594 { 01595 return *(end(i1, i2) - 1); 01596 } 01597 const_reference back(size_type i1, size_type i2) const 01598 { 01599 return *(end(i1, i2) - 1); 01600 } 01601 reference back(size_type i1, size_type i2, size_type i3) 01602 { 01603 return *(end(i1, i2, i3) - 1); 01604 } 01605 const_reference back(size_type i1, size_type i2, size_type i3) const 01606 { 01607 return *(end(i1, i2, i3) - 1); 01608 } 01609 reference back(size_type i1, size_type i2, size_type i3, size_type i4) 01610 { 01611 return *(end(i1, i2, i3, i4) - 1); 01612 } 01613 const_reference back(size_type i1, size_type i2, size_type i3, size_type i4) const 01614 { 01615 return *(end(i1, i2, i3, i4) - 1); 01616 } 01617 reference back(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) 01618 { 01619 return *(end(i1, i2, i3, i4, i5) - 1); 01620 } 01621 const_reference back(size_type i1, size_type i2, size_type i3, size_type i4, size_type i5) const 01622 { 01623 return *(end(i1, i2, i3, i4, i5) - 1); 01624 } 01625 01626 size_type size() const 01627 { 01628 return p_g.size; 01629 } 01630 size_type capacity() const 01631 { 01632 return p_g.size; 01633 } 01634 bool empty() const 01635 { 01636 return ( p_g.size == 0UL ); 01637 } 01638 01639 pointer data() 01640 { 01641 return &p_dsl[0]; 01642 } 01643 const_pointer data() const 01644 { 01645 // the Sun Studio compiler does not allow &p_dsl[0] for a const valarray... 01646 return &const_cast<valarray<T>&>(p_dsl)[0]; 01647 } 01648 01649 const multi_geom<d,ALLOC,lgBC>& clone() const 01650 { 01651 return p_g; 01652 } 01653 01654 valarray<T>& vals() 01655 { 01656 return p_dsl; 01657 } 01658 const valarray<T>& vals() const 01659 { 01660 return p_dsl; 01661 } 01662 }; 01663 01664 // predefine commonly used iterators 01665 typedef multi_arr<bool,2>::iterator mb2i; 01666 typedef multi_arr<bool,2>::const_iterator mb2ci; 01667 typedef multi_arr<bool,3>::iterator mb3i; 01668 typedef multi_arr<bool,3>::const_iterator mb3ci; 01669 typedef multi_arr<bool,4>::iterator mb4i; 01670 typedef multi_arr<bool,4>::const_iterator mb4ci; 01671 typedef multi_arr<bool,5>::iterator mb5i; 01672 typedef multi_arr<bool,5>::const_iterator mb5ci; 01673 typedef multi_arr<bool,6>::iterator mb6i; 01674 typedef multi_arr<bool,6>::const_iterator mb6ci; 01675 01676 typedef multi_arr<long,2>::iterator ml2i; 01677 typedef multi_arr<long,2>::const_iterator ml2ci; 01678 typedef multi_arr<long,3>::iterator ml3i; 01679 typedef multi_arr<long,3>::const_iterator ml3ci; 01680 typedef multi_arr<long,4>::iterator ml4i; 01681 typedef multi_arr<long,4>::const_iterator ml4ci; 01682 typedef multi_arr<long,5>::iterator ml5i; 01683 typedef multi_arr<long,5>::const_iterator ml5ci; 01684 typedef multi_arr<long,6>::iterator ml6i; 01685 typedef multi_arr<long,6>::const_iterator ml6ci; 01686 01687 typedef multi_arr<realnum,2>::iterator mr2i; 01688 typedef multi_arr<realnum,2>::const_iterator mr2ci; 01689 typedef multi_arr<realnum,3>::iterator mr3i; 01690 typedef multi_arr<realnum,3>::const_iterator mr3ci; 01691 typedef multi_arr<realnum,4>::iterator mr4i; 01692 typedef multi_arr<realnum,4>::const_iterator mr4ci; 01693 typedef multi_arr<realnum,5>::iterator mr5i; 01694 typedef multi_arr<realnum,5>::const_iterator mr5ci; 01695 typedef multi_arr<realnum,6>::iterator mr6i; 01696 typedef multi_arr<realnum,6>::const_iterator mr6ci; 01697 01698 typedef multi_arr<double,2>::iterator md2i; 01699 typedef multi_arr<double,2>::const_iterator md2ci; 01700 typedef multi_arr<double,3>::iterator md3i; 01701 typedef multi_arr<double,3>::const_iterator md3ci; 01702 typedef multi_arr<double,4>::iterator md4i; 01703 typedef multi_arr<double,4>::const_iterator md4ci; 01704 typedef multi_arr<double,5>::iterator md5i; 01705 typedef multi_arr<double,5>::const_iterator md5ci; 01706 typedef multi_arr<double,6>::iterator md6i; 01707 typedef multi_arr<double,6>::const_iterator md6ci; 01708 01709 #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(_MSC_VER) 01710 #define INST_EXTERN EXTERN 01711 #else 01712 #define INST_EXTERN 01713 #endif 01714 01715 #ifdef _MSC_VER 01716 /* disable "'extern' before template explicit instantiation" */ 01717 # pragma warning( disable : 4231 ) 01718 #endif 01719 01720 // on Mac systems these instantiations need to be extern in order to avoid duplicate symbols 01721 #define INSTANTIATE_MULTI_ARR( TYPE, LAYOUT, BC ) \ 01722 INST_EXTERN template class pntr<TYPE,2,LAYOUT,BC>; \ 01723 INST_EXTERN template class pntr<TYPE,3,LAYOUT,BC>; \ 01724 INST_EXTERN template class pntr<TYPE,4,LAYOUT,BC>; \ 01725 INST_EXTERN template class pntr<TYPE,5,LAYOUT,BC>; \ 01726 INST_EXTERN template class pntr<TYPE,6,LAYOUT,BC>; \ 01727 INST_EXTERN template class const_pntr<TYPE,2,LAYOUT,BC>; \ 01728 INST_EXTERN template class const_pntr<TYPE,3,LAYOUT,BC>; \ 01729 INST_EXTERN template class const_pntr<TYPE,4,LAYOUT,BC>; \ 01730 INST_EXTERN template class const_pntr<TYPE,5,LAYOUT,BC>; \ 01731 INST_EXTERN template class const_pntr<TYPE,6,LAYOUT,BC> 01732 01733 INSTANTIATE_MULTI_ARR( bool, MEM_LAYOUT_VAL, lgBOUNDSCHECKVAL ); 01734 INSTANTIATE_MULTI_ARR( long, MEM_LAYOUT_VAL, lgBOUNDSCHECKVAL ); 01735 INSTANTIATE_MULTI_ARR( realnum, MEM_LAYOUT_VAL, lgBOUNDSCHECKVAL ); 01736 INSTANTIATE_MULTI_ARR( double, MEM_LAYOUT_VAL, lgBOUNDSCHECKVAL ); 01737 INSTANTIATE_MULTI_ARR( double, C_TYPE, lgBOUNDSCHECKVAL ); 01738 01739 01740 template<class T, bool lgBC=lgBOUNDSCHECKVAL> 01741 class flex_arr 01742 { 01743 size_t p_size; // number of elements allocated 01744 long p_begin; // first valid array index 01745 long p_end; // one beyond last valid array index 01746 bool p_init; // set true when alloc() has been called 01747 01748 T* p_ptr_alloc; // pointer to start of allocated data 01749 T* p_ptr; // pointer used for calculating array indices 01750 01751 public: 01752 typedef random_access_iterator_tag iterator_category; 01753 typedef T value_type; 01754 typedef T& reference; 01755 typedef const T& const_reference; 01756 typedef T* pointer; 01757 typedef const T* const_pointer; 01758 typedef long size_type; 01759 typedef ptrdiff_t difference_type; 01760 typedef pntr<T,1,FLX_TYPE,lgBC> iterator; 01761 typedef const_pntr<T,1,FLX_TYPE,lgBC> const_iterator; 01762 01763 private: 01764 void p_clear0() 01765 { 01766 delete[] p_ptr_alloc; 01767 p_ptr_alloc = NULL; 01768 } 01769 void p_clear1() 01770 { 01771 p_size = 0; 01772 p_begin = 0; 01773 p_end = 0; 01774 p_init = false; 01775 p_ptr_alloc = NULL; 01776 p_ptr = NULL; 01777 } 01778 01779 public: 01780 flex_arr() 01781 { 01782 p_clear1(); 01783 } 01784 flex_arr(size_type begin, size_type end) 01785 { 01786 p_clear1(); 01787 alloc( begin, end ); 01788 } 01789 ~flex_arr() 01790 { 01791 p_clear0(); 01792 } 01793 const flex_arr& operator= ( const flex_arr& f ) 01794 { 01795 if( &f != this ) 01796 { 01797 clear(); 01798 p_size = f.p_size; 01799 p_begin = f.p_begin; 01800 p_end = f.p_end; 01801 p_init = f.p_init; 01802 if( f.p_ptr_alloc != NULL ) 01803 { 01804 p_ptr_alloc = new T[ p_size ]; 01805 pointer p = p_ptr_alloc; 01806 const_pointer fp = f.p_ptr_alloc; 01807 for( size_type i=0; i < p_end-p_begin; ++i ) 01808 *p++ = *fp++; 01809 p_ptr = p_ptr_alloc - p_begin; 01810 } 01811 } 01812 return *this; 01813 } 01814 void clear() 01815 { 01816 p_clear0(); 01817 p_clear1(); 01818 } 01819 void zero() 01820 { 01821 ASSERT( p_ptr_alloc != NULL ); 01822 memset( p_ptr_alloc, 0, p_size*sizeof(T) ); 01823 } 01824 void invalidate() 01825 { 01826 ASSERT( p_ptr_alloc != NULL ); 01827 invalidate_array( p_ptr_alloc, p_size*sizeof(T) ); 01828 } 01829 void state_do(FILE *out, bool lgGet) 01830 { 01831 if( lgGet ) 01832 restore_state(out); 01833 else 01834 dump_state(out); 01835 } 01836 // dump the array to a file in binary format 01837 void dump_state(FILE *out) const 01838 { 01839 do_dump_state( p_ptr_alloc, p_size, sizeof(T), out, MA_VERS[FLX_TYPE] ); 01840 } 01841 // restore the array from a file in binary format 01842 void restore_state(FILE *in) 01843 { 01844 do_restore_state( p_ptr_alloc, p_size, sizeof(T), in, MA_VERS[FLX_TYPE] ); 01845 } 01846 01847 // reserve memory for the array 01848 void reserve(size_type size) 01849 { 01850 // make sure we start with a clean slate... 01851 clear(); 01852 #ifdef _MSC_VER 01853 /* disable warning that conditional expression is constant, true or false in if */ 01854 # pragma warning( disable : 4127 ) 01855 #endif 01856 if( size > 0 ) 01857 { 01858 ASSERT( p_ptr_alloc == NULL ); 01859 p_ptr_alloc = new T[size]; 01860 p_size = (size_t)size; 01861 } 01862 } 01863 // allocate array with index between begin <= ind < end 01864 // memory is allocated here, if not already done with reserve() before 01865 void alloc(size_type begin, size_type end) 01866 { 01867 if( (size_t)max(end-begin,0) > p_size ) 01868 { 01869 clear(); 01870 01871 ASSERT( p_ptr_alloc == NULL ); 01872 p_ptr_alloc = new T[end-begin]; 01873 p_ptr = p_ptr_alloc - begin; 01874 p_size = (size_t)(end-begin); 01875 } 01876 else 01877 { 01878 // store was already allocated wit reserve() 01879 p_ptr = p_ptr_alloc - begin; 01880 } 01881 p_begin = begin; 01882 p_end = end; 01883 p_init = true; 01884 } 01885 // adjust upper limit of array, reallocate store if necessary 01886 void realloc(size_type end) 01887 { 01888 ASSERT( p_init ); 01889 if( (size_t)max(end-p_begin,0) > p_size ) 01890 { 01891 // reallocate the store 01892 T* nptr_alloc = new T[end-p_begin]; 01893 T* nptr = nptr_alloc - p_begin; 01894 // copy store over using operator= from T, using memcpy would be a bug! 01895 // this could trip valgrind / purify since we don't know if this is initialized 01896 // there is nothing safe we can do here, so the caller should take care of this 01897 // note that we ignore fields above p_end, we assume nothing of interest is there 01898 if( p_ptr_alloc != NULL && p_ptr != NULL ) 01899 { 01900 for( size_type i=p_begin; i < p_end; ++i ) 01901 nptr[i] = p_ptr[i]; 01902 delete[] p_ptr_alloc; 01903 } 01904 p_ptr_alloc = nptr_alloc; 01905 p_ptr = nptr; 01906 p_size = (size_t)(end-p_begin); 01907 } 01908 p_end = end; 01909 } 01910 01911 private: 01912 // the p_pointer() method below defines indexing into the flex_arr 01913 pointer p_pointer(size_type i) const 01914 { 01915 return p_ptr+i; 01916 } 01917 01918 iterator p_iterator(size_type i) const 01919 { 01920 #ifdef _MSC_VER 01921 /* disable warning that conditional expression is constant, true or false in if */ 01922 # pragma warning( disable : 4127 ) 01923 #endif 01924 if( lgBC ) 01925 return iterator( p_pointer(i), p_pointer(p_begin), p_pointer(p_end) ); 01926 else 01927 return iterator( p_pointer(i) ); 01928 } 01929 01930 bool p_lgInbounds(size_type i) const 01931 { 01932 return ( i >= p_begin && i < p_end ); 01933 } 01934 01935 reference p_index(size_type i) const 01936 { 01937 #ifdef _MSC_VER 01938 /* disable warning that conditional expression is constant, true or false in if */ 01939 # pragma warning( disable : 4127 ) 01940 #endif 01941 if( lgBC ) 01942 { 01943 if( ! p_lgInbounds( i ) ) 01944 OUT_OF_RANGE( "flex_arr::p_index()" ); 01945 } 01946 return *p_pointer(i); 01947 } 01948 01949 public: 01950 reference operator[] (size_type i) 01951 { 01952 return reference(p_index(i)); 01953 } 01954 const_reference operator[] (size_type i) const 01955 { 01956 return const_reference(p_index(i)); 01957 } 01958 01959 reference at(size_type i) 01960 { 01961 if( ! p_lgInbounds(i) ) 01962 OUT_OF_RANGE( "flex_arr::at()" ); 01963 return (*this)[i]; 01964 } 01965 const_reference at(size_type i) const 01966 { 01967 if( ! p_lgInbounds(i) ) 01968 OUT_OF_RANGE( "flex_arr::at()" ); 01969 return (*this)[i]; 01970 } 01971 01972 iterator ptr(size_type i) 01973 { 01974 return iterator(p_iterator(i)); 01975 } 01976 const_iterator ptr(size_type i) const 01977 { 01978 return const_iterator(p_iterator(i)); 01979 } 01980 01981 // \todo: add: assign, swap?, ... (go over stl_vector.h) 01982 01983 iterator begin() 01984 { 01985 return ptr(p_begin); 01986 } 01987 const_iterator begin() const 01988 { 01989 return ptr(p_begin); 01990 } 01991 01992 iterator end() 01993 { 01994 return ptr(p_end); 01995 } 01996 const_iterator end() const 01997 { 01998 return ptr(p_end); 01999 } 02000 02001 reference front() 02002 { 02003 return *begin(); 02004 } 02005 const_reference front() const 02006 { 02007 return *begin(); 02008 } 02009 02010 reference back() 02011 { 02012 return *(end()-1); 02013 } 02014 const_reference back() const 02015 { 02016 return *(end()-1); 02017 } 02018 02019 size_type size() const 02020 { 02021 return max(p_end-p_begin,0); 02022 } 02023 size_type capacity() const 02024 { 02025 return p_size; 02026 } 02027 bool empty() const 02028 { 02029 return ( size() == 0 ); 02030 } 02031 02032 pointer data() 02033 { 02034 return p_ptr_alloc; 02035 } 02036 const_pointer data() const 02037 { 02038 return p_ptr_alloc; 02039 } 02040 }; 02041 02042 // predefine commonly used iterators 02043 typedef flex_arr<bool>::iterator fabi; 02044 typedef flex_arr<bool>::const_iterator fabci; 02045 typedef flex_arr<long>::iterator fali; 02046 typedef flex_arr<long>::const_iterator falci; 02047 typedef flex_arr<realnum>::iterator fari; 02048 typedef flex_arr<realnum>::const_iterator farci; 02049 typedef flex_arr<double>::iterator fadi; 02050 typedef flex_arr<double>::const_iterator fadci; 02051 02052 #endif /* _CONTAINER_CLASSES_H_ */