Main Page | Class Hierarchy | Compound List | File List | Compound Members | File Members

hat.h

Go to the documentation of this file.
00001 
00002 #ifndef HAT_H
00003 #define HAT_H
00004 
00005 #include "sysinc.h"
00006 
00010 #define GetTopIndex(i) ((i)>>power)
00011 #define GetLeafIndex(i) ((i)&leafMask)
00012 
00015 typedef enum { min_hat_size = 32 };
00016 
00017 #ifndef NULL
00018 #define NULL 0
00019 #endif
00020 
00121 template <class T>
00122 class Hat
00123 {
00124 private:
00125     size_t leafSize() const { return 1<<power; /* return 2^power */ }
00126     size_t topSize() const { return 1<<power; /* return 2^power */ }
00127     size_t topIndex( const unsigned i ) const { return GetTopIndex(i); }
00128     size_t leafIndex( const unsigned i ) const { return GetLeafIndex(i); }
00129 
00134     void resize( const size_t newExpectedSize )
00135     {
00136         size_t  i, leaf_ix;
00137 
00138         Hat<T>  hatNew( newExpectedSize );
00139 
00140         /* if the new HAT is the same size (e.g., power) as "this"
00141            HAT, return */
00142         if( hatNew.power == power )
00143             return;
00144 
00145         /* copy the data from "this" hat into the new array */
00146         for( i = 0, leaf_ix = 0; i < numElements; i++ )
00147             {
00148                 hatNew.add_to_end( (*this)[i], 0 );     // append, but do not resize again
00149 
00150                 leaf_ix++;
00151                 // delete the leaves as we go - this decreases memory overhead.
00152                 if( leaf_ix == leafSize() )
00153                     {
00154                         delete [] top[topIndex(i)];
00155                         leaf_ix = 0;
00156                     }
00157             }
00158 
00159         // delete any unused leaves.
00160         for( i = topIndex(numElements); i < topUsed; i++ )
00161             delete [] top[i];
00162 
00163         // assign the new array to the old.
00164         delete top;
00165         top = hatNew.top;
00166         setPower( hatNew.power );
00167         topUsed = hatNew.topUsed;
00168         numAvail = hatNew.numAvail;
00169 
00170         // clean up so nothing gets corrupted.
00171         hatNew.numElements = 0;
00172         hatNew.topUsed = 0;
00173         hatNew.top = NULL;
00174     }  // resize
00175 
00176 
00182     void addLeaf( const T &aValue, const int doResize )
00183     {
00184         /* If the top array is either empty (topUsed == 0) or is full
00185            topUsed == topSize (no new leaves can be added), reallocate the
00186            array.  */
00187         if( topUsed % topSize() == 0 )
00188             {
00189                 int     growTop = TRUE;
00190 
00191                 if( doResize )
00192                     {
00193                         resize( numElements );
00194 
00195                         // Check if after the resize we have room.
00196                         if( topIndex(numElements) < topUsed )
00197                             {
00198                                 (*this)[numElements++] = aValue;
00199                                 return;
00200                             }
00201 
00202                         // Check if we have room for a new leaf.
00203                         if( topUsed % topSize() != 0 )
00204                             growTop = FALSE;
00205                     }
00206                 if( growTop )
00207                     {
00208                         // Increase the top array by topSize.
00209                         T       **topNew = new T * [ topUsed + topSize() ];
00210                         for( size_t i = 0; i < topUsed; i++ )
00211                             topNew[i] = top[i];
00212                         delete [] top;
00213                         top = topNew;
00214                     }
00215             }
00216         /* add a new leaf */
00217         top[topUsed] = new T [leafSize()];
00218         top[topUsed][0] = aValue;
00219         numAvail += leafSize();
00220         topUsed++;
00221         numElements++;
00222     } /* addLeaf */
00223 
00224 
00225     size_t recommendedPower( const size_t s ) const
00226     {
00227 
00228         const size_t powerMin = 1; // set a resonable minimum
00229         size_t p;
00230         for( p = powerMin; s > (1<<(p<<1)); p++ )
00231             ;
00232         return p;
00233     } // recommendedPower
00234 
00235     void setPower( const size_t p )
00236     {
00237         power = p;
00238         leafMask = leafSize()-1;
00239     }
00240 
00241 
00242     void add_to_end( const T &aValue, const int doResize = 1 )
00243     {
00244         if (numElements == numAvail) {
00245             addLeaf( aValue, doResize );
00246         }
00247         else {
00248             (*this)[numElements] = aValue;
00249             numElements++;
00250         }
00251     }
00252 
00253 
00255     T   **top;
00257     size_t      topUsed;     
00259     size_t      power;       
00261     size_t      leafMask;    
00264     size_t      numElements; 
00266     size_t      numAvail;    
00267 
00268 public:
00269     void init( const size_t aExpectedSize = min_hat_size )
00270     {
00271         size_t p;
00272 
00273         /* get the smallest power of two greater than aExpectedSize */
00274         p = recommendedPower(aExpectedSize);
00275         setPower( p );
00276         numElements = 0;
00277         numAvail = 0;
00278 
00279         top = NULL;
00280         topUsed = 0;
00281     } // init
00282 
00287     Hat( const size_t aExpectedSize = min_hat_size )
00288     {
00289         init( aExpectedSize );
00290     }
00291 
00292 
00293     Hat( const Hat<T> &hat )
00294     {
00295         init( 0 );
00296         (*this) = hat;
00297     }
00298 
00299     ~Hat()
00300     {
00301         if (top != NULL) {
00302             for( size_t i = 0; i < topUsed; i++ ) {
00303                 if (top[i] != NULL) {
00304                     delete [] top[i];
00305                     top[i] = NULL;
00306                 }
00307             }
00308             delete [] top;
00309             top = NULL;
00310         }
00311     }
00312     
00313 
00334     void insert( const T &a, const size_t i )
00335     {
00336         assert( i <= numElements );
00337 
00338         if (numElements == 0 || i == numElements) {
00339             append( a );
00340         }
00341         else {
00342             assert( length() > 0 );
00343 
00344             size_t last_ix = length() - 1;
00345 
00346             // Move all data elements from i+1 up by one index
00347             append( (*this)[last_ix] );  // append the last element to the end of the array
00348             assert( length() == last_ix + 2 );
00349 
00350             int ix;
00351 
00352             for (ix = last_ix; ix > i; ix--) {
00353                 (*this)[ix] = (*this)[ix-1];
00354             }
00355             (*this)[i] = a;
00356         }
00357     } // insert
00358 
00359 
00370     void remove( const size_t i )
00371     {
00372         assert( length() > 0 );
00373         assert( i < length() );
00374 
00375         if (i < length() - 1) {
00376             int ix;
00377 
00378             for (ix = i; ix < length()-1; ix++) {
00379                 (*this)[ix] = (*this)[ix+1];
00380             }
00381         }
00382 
00383         numElements--;
00384     }  // remove
00385 
00386 
00389     void remove_n( const size_t i, const size_t n)
00390     {
00391         assert( length() > 0 );
00392         assert( i + n <= length() );
00393 
00394         if (i + n < length()) {
00395             int ix;
00396 
00397             for (ix = i; ix < length()-n; ix++) {
00398                 (*this)[ix] = (*this)[ix+n];
00399             }
00400         }
00401 
00402         numElements -= n;;      
00403     }
00404 
00405 
00406     T &operator[](const size_t i)
00407     {
00408         assert( i < numAvail );
00409         return top[GetTopIndex(i)][GetLeafIndex(i)];
00410     }
00411 
00412     T operator[](const size_t i) const
00413     {
00414         assert( i < numAvail );
00415         return top[GetTopIndex(i)][GetLeafIndex(i)];
00416     }
00417 
00419     T &at(const size_t i) 
00420     { 
00421         return (*this)[i]; 
00422     }
00423 
00425     T at(const size_t i) const 
00426     { 
00427         return (*this)[i]; 
00428     }
00429 
00431     T first() const { 
00432         return (*this)[0]; 
00433     }
00434 
00436     T last() const { 
00437         return (*this)[numElements-1]; 
00438     }
00439 
00441     void append( const T& a ) { 
00442         add_to_end(a); 
00443     }
00444 
00447     int isEmpty() const { 
00448         return numElements == 0; 
00449     }
00450 
00457     void set_to_empty() {
00458         numElements = 0;
00459     }
00460 
00465     size_t length() const { 
00466         return numElements; 
00467     }
00468 
00469     void decrement_length( const unsigned int val ) {
00470         if (val <= numElements)
00471             numElements = numElements - val;
00472         else
00473             numElements = 0;
00474     } // decrement_length
00475 };
00476 
00477 #undef GetTopIndex
00478 #undef GetLeafIndex
00479 
00480 #endif

Generated on Wed Mar 31 21:15:55 2004 for Data Structures for a VHDL Compiler by doxygen 1.3.3