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