base_types_array.hh

Go to the documentation of this file.
00001 /*
00027  * LEGAL:   COPYRIGHT (C) 2007 JIM E. BROOKS
00028  *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
00029  *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
00030  *****************************************************************************/
00031 
00032 #ifndef BASE_TYPES_ARRAY_HH
00033 #define BASE_TYPES_ARRAY_HH 1
00034 
00035 #include "base_shared_ptr.hh"
00036 #include "base_types.hh"
00037 #include "base_types2.hh"
00038 #include "base_funcs2.hh"
00039 
00040 namespace base {
00041 
00042 //==============================================================================
00043 //==============================================================================
00044 //                    Virtual methods forbidden in this section
00045 //==============================================================================
00046 //==============================================================================
00047 
00048 // Basic types must be fast, prevent them having virtual functions.
00049 #define virtual VIRTUAL_METHODS_IN_BASIC_TYPES_IS_TOO_SLOW
00050 
00068 template<typename T>
00069 class Array : public Shared
00070 {
00071 
00072 public:
00073     typedef T Type;
00074     // Writing new elements is restricted to push_back().
00075     Array( void ) { }
00076     // Writing new elements can be done by operator[].
00077     explicit Array( uint cnt ) { ASSERT( cnt < MAX_ELEMS ); mVector.resize( cnt ); }
00078     ~Array() { }
00082     T*                PTR( void ) const { return const_cast<T*>( &mVector[0] ); }
00083     const T*    CONST_PTR( void ) const { return &mVector[0]; }
00084     T&          operator[]( uint i )       { ASSERT( i < mVector.size() ); return mVector[i]; }
00085     const T&    operator[]( uint i ) const { ASSERT( i < mVector.size() ); return mVector[i]; }
00086     void        push_back( const T& v ) { mVector.push_back( v ); }
00087     bool        empty( void ) const { return mVector.empty(); }
00088     void        clear( void ) { mVector.clear(); }
00089     uint        size( void ) const  { return mVector.size(); }
00090     void        resize( uint cnt )  { mVector.resize( cnt ); }  // immediate reallocation
00091     void        reserve( uint cnt ) { mVector.reserve( cnt ); }  // just a hint for allocator
00092     friend bool operator<( const Array& a, const Array& b ) { return a.mVector < b.mVector; }
00093 
00094 //  typedef STLIterator<T,vector<T> > Iterator;
00095 //  Iterator    GetIterator( void ) const { return Iterator( mVector ); }
00096 
00097 private:
00098     vector<T>           mVector;
00099     CLASS_CONST uint    MAX_ELEMS = 20 * MILLION;
00100 };
00101 
00111 template<uint CNT, typename T=int>
00112 class TinyArray
00113 {
00114 public:
00115     typedef T Type;  // type of element
00116 
00117 public:
00119     TinyArray( void )
00120     {
00121         // NOP
00122     }
00123 
00125     explicit TinyArray( const T val )
00126     {
00127         Fill( val );
00128     }
00129 
00131     TinyArray( const TinyArray<CNT,T>& src )
00132     {
00133         *this = src;  // invoke operator=()
00134     }
00135 
00136     // Copy constructor from a C array.
00137     // This syntax, which would be convenient, the compiler won't accept: TinyArray<> = { };
00138     TinyArray( const T src[] )
00139     {
00140         for ( uint i = 0; i < CNT; ++i )
00141             mArray[i] = src[i];         
00142     }
00143 
00145     uint GetCnt( void ) const
00146     {
00147         return CNT;
00148     }
00149 
00151     void Fill( T val )
00152     {
00153         for ( uint i = 0; i < CNT; ++i )
00154             mArray[i] = val;
00155     }
00156 
00160     T& operator[]( uint i )                 // compiled unless TinyArray is const
00161     {
00162         ASSERT( i < CNT );
00163         return mArray[i];
00164     }
00165 
00166     const T& operator[]( uint i ) const     // compiled if TinyArray is const
00167     {
00168         ASSERT( i < CNT );
00169         return mArray[i];
00170     }
00171 
00173     TinyArray<CNT,T>& operator=( const TinyArray<CNT,T>& src )
00174     {
00175         for ( uint i = 0; i < CNT; ++i )
00176             mArray[i] = src.mArray[i];  // assign
00177         return *this;
00178     }
00179 
00180     bool operator==( const TinyArray<CNT,T>& src ) const
00181     {
00182         for ( uint i = 0; i < CNT; ++i )
00183             if ( mArray[i] != src.mArray[i] ) return false; // different
00184         return true; // all elements equal
00185     }
00186 
00187     bool operator!=( const TinyArray<CNT,T>& src ) const
00188     {
00189         // Same as operator==() but retvals opposite.
00190         for ( uint i = 0; i < CNT; ++i )
00191             if ( mArray[i] != src.mArray[i] ) return true; // different
00192         return false; // all elements equal
00193     }
00194 
00195     bool operator<( const TinyArray<CNT,T>& src ) const
00196     {
00197         for ( uint i = 0; i < CNT; ++i )
00198         {
00199             if ( mArray[i] < src.mArray[i] )
00200                 return true;
00201             else if ( src.mArray[i] < mArray[i] )  // swapping operands substitutes greater than
00202                 return false;
00203             // continue, at this point, only know a subset is equal
00204         }
00205         return false; // all elements equal
00206     }
00207 
00208     // These are dangerous: overrunning TinyArray will corrupt call stack!
00209     T*             PTR( void ) const { return const_cast<T*>(mArray); }
00210     const T* CONST_PTR( void ) const { return mArray; }
00211 
00213     uint size( void ) const
00214     {
00215         return CNT;
00216     }
00217 
00218     bool empty( void ) const
00219     {
00220         return false;  // always has CNT elements
00221     }
00222 
00223 private:
00224     T   mArray[CNT];
00225 };
00226 
00227 template<uint CNT, typename T>
00228 bool operator<( const TinyArray<CNT,T>& a1,
00229                 const TinyArray<CNT,T>& a2 )
00230 {
00231     return a1.operator<( a2 );  // yuck
00232 }
00233 
00256 template<uint FIXED_SIZE, typename T=int>
00257 class SmallArray
00258 {
00259 public:
00260     typedef T Type;  // type of element
00261 
00262 public:
00263     SmallArray( const uint varSize = 0 )
00264     :   mVarSize(varSize)
00265     {
00266         // NOP
00267     }
00268 
00270     SmallArray( const SmallArray<FIXED_SIZE,T>& src )
00271     {
00272         *this = src;  // invoke operator=()
00273     }
00274 
00278     T& operator[]( uint i )                 // compiled unless const
00279     {
00280     ASSERT( (i < mVarSize) && (i < FIXED_SIZE) );
00281         return mArray[i];
00282     }
00283 
00284     const T& operator[]( uint i ) const     // compiled if const
00285     {
00286     ASSERT( (i < mVarSize) && (i < FIXED_SIZE) );
00287         return mArray[i];
00288     }
00289 
00291     SmallArray<FIXED_SIZE,T>& operator=( const SmallArray<FIXED_SIZE,T>& src )
00292     {
00293         mVarSize = src.mVarSize;                    // assign variable-size
00294         for ( uint i = 0; i < src.mVarSize; ++i )   // copying all elements isn't necessary
00295             mArray[i] = src.mArray[i];
00296         return *this;
00297     }
00298 
00299     bool operator==( const SmallArray<FIXED_SIZE,T>& src ) const
00300     {
00301         if ( mVarSize == src.mVarSize )
00302         {
00303             for ( uint i = 0; i < mVarSize; ++i )
00304                 if ( mArray[i] != src.mArray[i] ) return false;  // different
00305             return true;  // all elements equal
00306         }
00307         else
00308         {
00309             return false;  // different sizes
00310         }
00311     }
00312 
00313     bool operator!=( const SmallArray<FIXED_SIZE,T>& src ) const
00314     {
00315         return not (*this == src);
00316     }
00317 
00318     bool operator<( const SmallArray<FIXED_SIZE,T>& src ) const
00319     {
00320         if ( mVarSize < src.mVarSize )
00321         {
00322             return true;
00323         }
00324         else  // same size
00325         {
00326             for ( uint i = 0; i < mVarSize; ++i )
00327             {
00328                 if ( mArray[i] < src.mArray[i] )
00329                     return true;
00330                 else if ( src.mArray[i] < mArray[i] )  // swapping operands substitutes greater than
00331                     return false;
00332                 // continue, at this point, only know a subset is equal
00333             }
00334             return false;  // all elements equal
00335         }
00336     }
00337 
00338     // These are dangerous: overrunning SmallArray will corrupt call stack!
00339     T*             PTR( void ) const { return const_cast<T*>(mArray); }
00340     const T* CONST_PTR( void ) const { return mArray; }
00341 
00343     uint size( void ) const
00344     {
00345         return mVarSize;
00346     }
00347 
00348     void resize( const uint varSize )
00349     {
00350     ASSERT( varSize < FIXED_SIZE );
00351 
00352         mVarSize = varSize;
00353     }
00354 
00355     void clear( void )
00356     {
00357         mVarSize = 0;
00358     }
00359 
00360     bool empty( void ) const
00361     {
00362         return mVarSize == 0;
00363     }
00364 
00365     void push_back( T item )
00366     {
00367     ASSERT( mVarSize < FIXED_SIZE );
00368 
00369         mArray[mVarSize++] = item;
00370     }
00371 
00372 private:
00373     uint    mVarSize;
00374     T       mArray[FIXED_SIZE];
00375 };
00376 
00377 template<uint FIXED_SIZE, typename T>
00378 bool operator<( const SmallArray<FIXED_SIZE,T>& a1,
00379                 const SmallArray<FIXED_SIZE,T>& a2 )
00380 {
00381     return a1.operator<( a2 );  // phooey
00382 }
00383 
00398 template<typename T,typename CONTAINER=vector<T> >
00399 class SortedArray
00400 {
00401 
00402 public:
00403     typedef T Type;  // type of element
00404 
00405     // Non-const operator is omitted intentionally.
00406     SortedArray( const uint size_ = 0 )
00407     :   mArray(size_)
00408     {
00409         SET_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00410     }
00411 
00412     SortedArray( const SortedArray<T>& src )
00413     :   mArray(src.mArray)
00414     {
00415         SET_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00416     }
00417 
00418     ~SortedArray()
00419     {
00420         INVALIDATE_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00421     }
00422 
00423     const T& operator[]( uint i ) const
00424     {
00425     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00426     ASSERT( i < mArray.size() );
00427 
00428         return mArray[i];
00429     }
00430 
00431     SortedArray<T>& operator=( const SortedArray<T>& src )
00432     {
00433     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00434     CHECK_TYPESIG(&src,TYPESIG_SORTED_ARRAY);
00435 
00436         mArray = src.mArray; return *this;
00437     }
00438 
00439     bool operator==( const SortedArray<T>& src ) const
00440     {
00441     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00442     CHECK_TYPESIG(&src,TYPESIG_SORTED_ARRAY);
00443 
00444         return mArray == src.mArray;
00445     }
00446 
00447     bool operator!=( const SortedArray<T>& src ) const
00448     {
00449     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00450     CHECK_TYPESIG(&src,TYPESIG_SORTED_ARRAY);
00451 
00452         return mArray != src.mArray;
00453     }
00454 
00455     bool operator<( const SortedArray<T>& src ) const
00456     {
00457     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00458     CHECK_TYPESIG(&src,TYPESIG_SORTED_ARRAY);
00459 
00460         return mArray < src.mArray;
00461     }
00462 
00463     // Limited STL compatibility. push_back() make no sense for SortedArray.
00464     uint size( void ) const
00465     {
00466     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00467 
00468         return mArray.size();
00469     }
00470 
00471     void resize( const uint size_ )
00472     {
00473     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00474 
00475         mArray.resize( size_ );
00476     }
00477 
00478     void clear( void )
00479     {
00480     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00481 
00482         mArray.clear();
00483     }
00484 
00485     bool empty( void ) const
00486     {
00487     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00488 
00489         return mArray.empty();
00490     }
00491 
00502     pair<bool,uint> find( const T item ) const
00503     {
00504     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00505 
00506         if ( mArray.empty() )
00507         {
00508             return make_pair<bool,uint>( false, 0xb00bb00b );
00509         }
00510         else if ( mArray.front() == item )
00511         {
00512             return make_pair<bool,uint>( true, 0 );
00513         }
00514         else if ( mArray.back() == item )
00515         {
00516             return make_pair<bool,uint>( true, mArray.size()-1 );
00517         }
00518         else if ( (mArray.front() < item) && (item < mArray.back()) )
00519         {
00520             int a = 0;                   // idx of first
00521             int z = int(mArray.size());  // idx of end (in STL terms)
00522             while ( z - a > 1 )
00523             {
00524               //int m = a + ((z - a) >> 1);  // midpoint
00525                 int m = (a + z) >> 1;        // average is equivalent but faster
00526                 ASSERT( uint(m) < uint(mArray.size()) );
00527                 if ( item < mArray[m] )
00528                 {
00529                     z = m;
00530                 }
00531                 else if ( mArray[m] < item )  // item > mArray[m]
00532                 {
00533                     a = m;
00534                 }
00535                 else // item == mArray[m]
00536                 {
00537                     return make_pair<bool,uint>( true, m );
00538                 }
00539             }
00540             // not found
00541             return make_pair<bool,uint>( false, 0xb00bb00b );
00542         }
00543         else  // item is less than or greater than all others
00544         {
00545             return make_pair<bool,uint>( false, 0xb00bb00b );
00546         }
00547     }
00548 
00550     pair<bool,uint> find_first( const T item ) const
00551     {
00552     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00553 
00554         pair<bool,uint> match = find( item );
00555         if ( match.first )
00556         {
00557             // Scan BACKWARD for the FIRST equal element.
00558             // match.second was index of WHICHEVER equal match.
00559             while ( (int(match.second)-1 > 0) && (mArray[match.second-1] == item) )
00560                 --match.second;  // ^^ signed int in case match.second was 0
00561         }
00562         return match;
00563     }
00564 
00566     pair<bool,uint> find_last( const T item ) const
00567     {
00568     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00569 
00570         pair<bool,uint> match = find( item );
00571         if ( match.first )
00572         {
00573             // Scan FORWARD for the LAST equal element.
00574             // match.second was index of WHICHEVER equal match.
00575             while ( (match.second+1 < mArray.size()) && (mArray[match.second+1] == item) )
00576                 ++match.second;
00577         }
00578         return match;
00579     }
00580 
00584     uint insert_last( const T item )
00585     {
00586     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00587 
00588         // upper_bound() is used with insertion so that a new item will follow older equal items.
00589         // distance() is called before before insert() which invalidates iterators.
00590 
00591         typename CONTAINER::iterator iter = std::upper_bound( mArray.begin(), mArray.end(), item );
00592         const uint idx = std::distance( mArray.begin(), iter );
00593 
00594         mArray.insert( iter, item );  // invalidates iter!
00595 
00596         return idx;
00597     }
00598 
00600     void remove_idx( const uint idx )
00601     {
00602     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00603     ASSERT( idx < mArray.size() );
00604 
00605         mArray.erase( mArray.begin() + idx );  // iterator arithmetic
00606     }
00607 
00610     pair<bool,uint> remove_first( const T item )
00611     {
00612     CHECK_TYPESIG(this,TYPESIG_SORTED_ARRAY);
00613 
00614         const pair<bool,uint> match = find_first( item );
00615         if ( EX( match.first ) )
00616         {
00617         ASSERT( match.second < mArray.size() );  // check idx
00618             mArray.erase( mArray.begin() + match.second );  // iterator arithmetic
00619         }
00620         return match;
00621     }
00622 
00623 private:
00624     CONTAINER   mArray;
00625 public:
00626     
00627 };
00628 
00634 template<typename T,T* TEMP, uint TEMP_SIZE>  // amazing that a C++ compiler will accept this
00635 class TempArray : public NonThreadable, public Shared
00636 {
00637 public:
00638     typedef T Type;
00639                 TempArray( void ) : mSize(0) { }
00640     explicit    TempArray( uint cnt ) : mSize(cnt) { }
00641                 ~TempArray() { }  // leave allocated
00642     T*                PTR( void ) const     { ASSERT( mSize > 0 ); return const_cast<T*>(TEMP); }
00643     const T*    CONST_PTR( void ) const     { ASSERT( mSize > 0 ); return TEMP; }
00644     T&          operator[]( uint i )        { ASSERT( i < mSize ); return TEMP[i]; }
00645     const T&    operator[]( uint i ) const  { ASSERT( i < mSize ); return TEMP[i]; }
00646     void        push_back( const T& val )   { ASSERT( mSize < TEMP_SIZE ); TEMP[mSize++] = val; }
00647     uint        empty( void ) const         { return mSize == 0; }
00648     uint        size( void ) const          { return mSize; }
00649     void        resize( uint cnt )          { ASSERT( cnt < TEMP_SIZE ); mSize = cnt; }
00650     void        reserve( UNUSED uint cnt )  { }
00651 private:
00652     uint        mSize;  // current number of elements in this array
00653 };
00654 
00660 template<typename T,typename BASE=Void>  // optionally, BASE can be Shared
00661 class Array2D : public BASE
00662 {
00663 
00664 public:
00665     Array2D( void )
00666     :   mSx(0), mSy(0), mVec()
00667     {
00668     }
00669 
00671     Array2D( int sx, int sy )
00672     {
00673         resize( sx, sy );
00674     }
00675 
00676     ~Array2D()
00677     {
00678     }
00679 
00680     void clear( void )
00681     {
00682         mSx = mSy = 0;
00683         mVec.clear();
00684     }
00685 
00686     void resize( int sx, int sy )
00687     {
00688     ASSERT( (sx > 0) && (sy > 0) );  // prevent mSx-1 overflowing
00689 
00690         mSx = sx;
00691         mSy = sy;
00692         mVec.resize( sx * sy );
00693 
00694     ASSERT( mVec.size() < base::defs::MAX_ELEMS );
00695     }
00696 
00697     uint size( void ) const
00698     {
00699         return mVec.size();
00700     }
00701 
00703     uint GetIdx( int x, int y ) const
00704     {
00705         // Clamp the 2D indexs in range {0,..,size-1}.
00706         x = Clamp( x, mSx-1 );
00707         y = Clamp( y, mSy-1 );
00708 
00709         // Compute flat index into underlying array.
00710         // Formula follows from this order of "for" loops.
00711         // Each x has to fully iterate y, hence, (x * mSy).
00712         // for ( x = 0; x < mSx; ++x )
00713         // for ( y = 0; y < mSy; ++y )
00714 
00715         const uint idx = (x * mSy) + y;
00716         ASSERT( idx < mVec.size() );
00717         return idx;
00718     }
00719 
00720     // Access element by 2D coordinates.  Can be used to write to element.
00721     T& Get( int x, int y )
00722     {
00723         return mVec[GetIdx(x,y)];
00724     }
00725 
00726     const T& Get( int x, int y ) const
00727     {
00728         return mVec[GetIdx(x,y)];
00729     }
00730 
00731     // Access element by flat index.
00732     T& operator[]( uint i )
00733     {
00734     ASSERT( i < mVec.size() );
00735         return mVec[i];
00736     }
00737 
00738     const T& operator[]( uint i ) const
00739     {
00740     ASSERT( i < mVec.size() );
00741         return mVec[i];
00742     }
00743 
00744 public:
00745     int         mSx;    
00746     int         mSy;    
00747     vector<T>   mVec;
00748 };
00749 
00750 #undef virtual
00751 
00752 } // namespace base
00753 
00754 #endif // BASE_TYPES_ARRAY_HH
Palomino 3D Engine documents generated by doxygen 1.5.3 on Fri Nov 23 11:26:07 2007