/home66/gary/public_html/cloudy/c08_branch/source/container_classes.h

Go to the documentation of this file.
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_ */

Generated on Mon Feb 16 12:01:13 2009 for cloudy by  doxygen 1.4.7