00001
00029 #ifndef ABA_HASH_INC
00030 #define ABA_HASH_INC
00031
00032 #ifdef ABACUS_PARALLEL
00033 #include "abacus/id.h"
00034
00035 #endif
00036 #include "abacus/string.h"
00037
00038 #include <math.h>
00039
00040 template <class KeyType, class ItemType>
00041 inline ABA_HASHITEM<KeyType, ItemType>::ABA_HASHITEM(
00042 const KeyType &key,
00043 const ItemType &item) :
00044 key_(key),
00045 item_(item),
00046 next_(0)
00047 { }
00048
00049 template <class KeyType, class ItemType>
00050 ostream &operator<<(ostream &out, const ABA_HASHITEM<KeyType, ItemType> &rhs)
00051 {
00052 return out << '(' << rhs.key_ << ',' << rhs.item_ << ')';
00053 }
00054
00055 template <class KeyType, class ItemType>
00056 inline ABA_HASHITEM<KeyType, ItemType> * ABA_HASHITEM<KeyType,
00057 ItemType>::next()
00058 {
00059 return next_;
00060 }
00061
00062 template <class KeyType, class ItemType>
00063 ABA_HASH<KeyType, ItemType>::ABA_HASH(ABA_GLOBAL *glob, int size)
00064 :
00065 glob_(glob),
00066 size_(size),
00067 nCollisions_(0),
00068 iter_(0)
00069 {
00070 #ifdef ABACUS_OLD_NEW
00071 typedef ABA_HASHITEM<KeyType, ItemType>* pABA_HASHITEM;
00072 table_ = new pABA_HASHITEM[size];
00073 #else
00074 table_ = new ABA_HASHITEM<KeyType, ItemType>* [size];
00075 #endif
00076
00077 for (int i = 0; i < size; i++) table_[i] = 0;
00078 }
00079
00080 template <class KeyType, class ItemType>
00081 ABA_HASH<KeyType, ItemType>::~ABA_HASH()
00082 {
00083 ABA_HASHITEM<KeyType, ItemType> *h1;
00084 ABA_HASHITEM<KeyType, ItemType> *h2;
00085 int i;
00086
00087 for (i = 0; i < size_; i++) {
00088 if((h1 = table_[i]))
00089 while (h1) {
00090 h2 = h1->next_;
00091 delete h1;
00092 h1 = h2;
00093 }
00094 }
00095 delete [] table_;
00096 }
00097
00098 template <class KeyType, class ItemType>
00099 ostream &operator<<(ostream &out, const ABA_HASH<KeyType, ItemType> &hash)
00100 {
00101
00102 ABA_HASHITEM<KeyType, ItemType> *h;
00103 const int s = hash.size();
00104
00105 for (int i = 0; i < s; i++) {
00106 h = hash.table_[i];
00107 if (h) {
00108 out << i << ':';
00109 while(h) {
00110 out << *h << ' ';
00111 h = h->next();
00112 }
00113 out << endl;
00114 }
00115 }
00116 return out;
00117 }
00118
00119 template <class KeyType, class ItemType>
00120 void ABA_HASH<KeyType, ItemType>::insert(const KeyType &key,
00121 const ItemType &item)
00122 {
00123 ABA_HASHITEM<KeyType, ItemType> *h = new ABA_HASHITEM<KeyType, ItemType>(key, item);
00124 int slotNum = hf(key);
00125
00126 if (table_[slotNum]) ++nCollisions_;
00127 h->next_ = table_[slotNum];
00128 table_[slotNum] = h;
00129
00130 }
00131
00132 template <class KeyType, class ItemType>
00133 void ABA_HASH<KeyType, ItemType>::overWrite(const KeyType &key,
00134 const ItemType &item)
00135 {
00137 int slotNum = hf(key);
00138 if (table_[slotNum]) ++nCollisions_;
00139
00140 ABA_HASHITEM<KeyType, ItemType> *h = table_[slotNum];
00141
00143
00145 while (h) {
00146 if (h->key_ == key) {
00147 h->item_ = item;
00148 return;
00149 }
00150 h = h->next_;
00151 }
00152
00154 h = new ABA_HASHITEM<KeyType, ItemType>(key, item);
00155 h->next_ = table_[slotNum];
00156 table_[slotNum] = h;
00157
00158 }
00159
00160 template <class KeyType, class ItemType>
00161 ItemType * ABA_HASH<KeyType, ItemType>::find(const KeyType &key)
00162 {
00163 ABA_HASHITEM<KeyType, ItemType> *slot;
00164
00165 slot = table_[hf(key)];
00166
00167 while (slot) {
00168 if (key == slot->key_) return &(slot->item_);
00169 slot = slot->next_;
00170 }
00171 return 0;
00172 }
00173
00174 template <class KeyType, class ItemType>
00175 bool ABA_HASH<KeyType, ItemType>::find (const KeyType &key, const ItemType &item)
00176 {
00177 ABA_HASHITEM<KeyType, ItemType> *slot;
00178
00179 slot = table_[hf(key)];
00180
00181 while (slot) {
00182 if (key == slot->key_ && slot->item_ == item) return true;
00183 slot = slot->next_;
00184 }
00185 return false;
00186 }
00187
00188 template <class KeyType, class ItemType>
00189 ItemType *ABA_HASH<KeyType, ItemType>::initializeIteration(const KeyType &key)
00190 {
00191 iter_ = table_[hf(key)];
00192 while (iter_) {
00193 if (key == iter_->key_) return &(iter_->item_);
00194 iter_ = iter_->next_;
00195 }
00196 return 0;
00197 }
00198
00199 template <class KeyType, class ItemType>
00200 ItemType *ABA_HASH<KeyType, ItemType>::next(const KeyType &key)
00201 {
00202 if (iter_ == 0) return 0;
00203 iter_ = iter_->next_;
00204
00205 while (iter_) {
00206 if (key == iter_->key_) return &(iter_->item_);
00207 iter_ = iter_->next();
00208 }
00209 return 0;
00210 }
00211
00212 template <class KeyType, class ItemType>
00213 int ABA_HASH<KeyType, ItemType>::remove(const KeyType &key)
00214 {
00215
00216 ABA_HASHITEM<KeyType, ItemType> *h1;
00217 ABA_HASHITEM<KeyType, ItemType> *h2;
00218 int slotNum = hf(key);
00219
00220 h1 = table_[slotNum];
00221 if (h1 == 0)
00222 return 1;
00223
00224
00225 if (h1->key_ == key) {
00226 table_[slotNum] = h1->next_;
00227 delete h1;
00228 return 0;
00229 }
00230
00231
00232 while ((h2 = h1->next_)) {
00233 if (h2->key_ == key) {
00234 h1->next_ = h2->next_;
00235 delete h2;
00236 return 0;
00237 }
00238 h1 = h2;
00239 }
00240 return 1;
00241 }
00242
00243 template <class KeyType, class ItemType>
00244 int ABA_HASH<KeyType, ItemType>::remove(const KeyType &key, const ItemType &item)
00245 {
00246
00247 ABA_HASHITEM<KeyType, ItemType> *h1;
00248 ABA_HASHITEM<KeyType, ItemType> *h2;
00249 int slotNum = hf(key);
00250
00251 h1 = table_[slotNum];
00252 if (h1 == 0)
00253 return 1;
00254
00255
00256 if (h1->key_ == key && h1->item_ == item) {
00257 table_[slotNum] = h1->next_;
00258 delete h1;
00259 return 0;
00260 }
00261
00262
00263 while ((h2 = h1->next_)) {
00264 if (h2->key_ == key && h2->item_ == item) {
00265 h1->next_ = h2->next_;
00266 delete h2;
00267 return 0;
00268 }
00269 h1 = h2;
00270 }
00271 return 1;
00272
00273 }
00274
00275 template <class KeyType, class ItemType>
00276 inline int ABA_HASH<KeyType, ItemType>::size() const
00277 {
00278 return size_;
00279 }
00280
00281 template <class KeyType, class ItemType>
00282 inline int ABA_HASH<KeyType, ItemType>::nCollisions() const
00283 {
00284 return nCollisions_;
00285 }
00286
00287 template <class KeyType, class ItemType>
00288 inline int ABA_HASH<KeyType, ItemType>::hf(int key)
00289 {
00290 if (key < 0) key = -key;
00291
00292 double x = key*0.6180339887;
00293
00294 return (int) (size()*(x-floor(x)));
00295 }
00296
00297 template <class KeyType, class ItemType>
00298 inline int ABA_HASH<KeyType, ItemType>::hf(unsigned key)
00299 {
00300 double x = key*0.6180339887;
00301
00302 return (int) (size()*fmod(x, 1.0));
00303 }
00304
00305 template <class KeyType, class ItemType>
00306 int ABA_HASH<KeyType, ItemType>::hf(const ABA_STRING &string)
00307 {
00308
00309 const int prime = 516595003;
00310 const int mult = 314159;
00311 const int s = string.size();
00312 int h = 0;
00313 for (int i = 0; i < s; i++) {
00314 h += (h ^ (h >> 1)) + mult * (unsigned char) string[i];
00315 while (h >= prime) h -= prime;
00316 }
00317
00318 return h % s;
00319 }
00320
00321 #ifdef ABACUS_PARALLEL
00322
00323 template <class KeyType, class ItemType>
00324 int ABA_HASH<KeyType, ItemType>::hf(const ABA_ID &id)
00325 {
00326 const int rand[64] = {
00327 0x08fa735c, 0x465969d0, 0x66a657f4, 0x144d2cf9,
00328 0x32b20675, 0x7d86036c, 0x3bcd2f61, 0x30421197,
00329 0x272d9013, 0x1d3bf099, 0x1bd38ed1, 0x57abc10e,
00330 0x7e62fbf6, 0x0b9bf7ad, 0x15bd99d9, 0x451a0198,
00331 0x73b3a879, 0x325eeb8a, 0x1dbb0b7c, 0x5bec0be6,
00332 0x2e78432e, 0x2e2ceea6, 0x55177a1a, 0x7b31a98f,
00333 0x54d04dd5, 0x547bd0d0, 0x1d12c33a, 0x16fb478f,
00334 0x687e3120, 0x4a047b2e, 0x649e29fb, 0x1c36b5ae,
00335 0x3a9e8db8, 0x6488c827, 0x5b6315fa, 0x60b4e7c1,
00336 0x5c116177, 0x336ead28, 0x7dcdd34c, 0x41b4bb6e,
00337 0x3f7aeaa3, 0x687cf590, 0x19469807, 0x56a508f0,
00338 0x179ed4c4, 0x06e73a00, 0x007da2a3, 0x41e5ac24,
00339 0x0585b479, 0x5b1cf529, 0x285b5b9a, 0x3bbaea37,
00340 0x7c84f882, 0x081c97ba, 0x6df23bc6, 0x1f655ecb,
00341 0x291ac2ac, 0x7598ef40, 0x5b8235b8, 0x25ccaa59,
00342 0x65a52132, 0x2cf89028, 0x1d05cf45, 0x32e86c2b
00343 };
00344
00345 return (rand[id.proc() & 63] ^ id.sequence()) % size_;
00346 }
00347
00348 #endif
00349
00350 template <class KeyType, class ItemType>
00351 void ABA_HASH<KeyType, ItemType>::resize(int newSize)
00352 {
00353
00354 if (newSize <= 0) {
00355 ABA_HASH<KeyType, ItemType>::glob_->err() << "ABA_HASH::resize(): new size of hash table must be ";
00356 ABA_HASH<KeyType, ItemType>::glob_->err() << "positive." << endl;
00357 exit(Fatal);
00358 }
00359
00360
00361
00362
00363
00364 ABA_HASHITEM<KeyType, ItemType> **newTable;
00365
00366 #ifdef ABACUS_OLD_NEW
00367 typedef ABA_HASHITEM<KeyType, ItemType>* pABA_HASHITEM;
00368 newTable = new pABA_HASHITEM[newSize];
00369 #else
00370 newTable = new ABA_HASHITEM<KeyType, ItemType>* [newSize];
00371 #endif
00372
00373 for (int i = 0; i < newSize; i++)
00374 newTable[i] = 0;
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 int oldSize = size_;
00385 size_ = newSize;
00386
00387 #ifdef ABACUS_NO_FOR_SCOPE
00388 for (i = 0; i < oldSize; i++)
00389 #else
00390 for (int i = 0; i < oldSize; i++)
00391 #endif
00392 if (table_[i]) {
00393
00394 ABA_HASHITEM<KeyType, ItemType> *current = table_[i];
00395 ABA_HASHITEM<KeyType, ItemType> *next;
00396
00397 while (current) {
00398 int slotNum = hf(current->key_);
00399 next = current->next_;
00400
00401 current->next_ = newTable[slotNum];
00402 newTable[slotNum] = current;
00403 current = next;
00404 }
00405
00406 }
00407
00408
00409 delete table_;
00410 table_ = newTable;
00411
00412 }
00413
00414 #endif // ABA_HASH_INC
00415