00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #if (!defined (__XLC__) && !defined(__xlC__)) || defined(DICT_C_IS_HEADER)
00034
00035 #include "common/h/std_namesp.h"
00036 #include "common/h/Dictionary.h"
00037
00038
00039
00040
00041
00042 #include <limits.h>
00043 #include <assert.h>
00044
00045 template<class K, class V>
00046 const unsigned dictionary_hash<K,V>::bin_grow_factor = 2;
00047
00048 template<class K, class V>
00049 dictionary_hash<K,V>::dictionary_hash(unsigned (*hf)(const K &),
00050 unsigned nbins,
00051 unsigned imax_bin_load) {
00052
00053 assert(imax_bin_load > 0);
00054 assert(imax_bin_load < 1000);
00055
00056 hasher = hf;
00057
00058
00059
00060
00061
00062 assert(nbins > 0);
00063 bins.resize(nbins);
00064 for (unsigned binlcv=0; binlcv < bins.size(); binlcv++)
00065 bins[binlcv] = UINT_MAX;
00066
00067 num_removed_elems = 0;
00068
00069 max_bin_load = imax_bin_load;
00070
00071 assert(enoughBins());
00072 }
00073
00074 template<class K, class V>
00075 dictionary_hash<K,V>::dictionary_hash(const dictionary_hash<K,V> &src) :
00076 all_elems(src.all_elems), bins(src.bins) {
00077
00078
00079 hasher = src.hasher;
00080 num_removed_elems = src.num_removed_elems;
00081 max_bin_load = src.max_bin_load;
00082
00083 assert(enoughBins());
00084 }
00085
00086 template<class K, class V>
00087 dictionary_hash<K,V> &
00088 dictionary_hash<K,V>::operator=(const dictionary_hash<K,V> &src) {
00089
00090
00091 if (&src == this) return *this;
00092
00093 hasher = src.hasher;
00094 all_elems = src.all_elems;
00095 bins = src.bins;
00096
00097 num_removed_elems = src.num_removed_elems;
00098 max_bin_load = src.max_bin_load;
00099
00100 assert(enoughBins());
00101
00102 return *this;
00103 }
00104
00105 template<class K, class V>
00106 unsigned dictionary_hash<K,V>::size() const {
00107 assert(num_removed_elems <= all_elems.size());
00108 return all_elems.size() - num_removed_elems;
00109 }
00110
00111 template<class K, class V>
00112 V& dictionary_hash<K,V>::operator[](const K& key) {
00113 const unsigned ndx = locate_addIfNotFound(key);
00114
00115
00116
00117 return all_elems[ndx].val;
00118 }
00119
00120 template<class K, class V>
00121 const V& dictionary_hash<K,V>::operator[](const K& key) const {
00122 const unsigned ndx = locate(key, false);
00123 assert(ndx != UINT_MAX);
00124
00125
00126 return all_elems[ndx].val;
00127 }
00128
00129 template<class K, class V>
00130 const V& dictionary_hash<K,V>::get(const K &key) const {
00131 const unsigned ndx = locate(key, false);
00132
00133
00134 if (ndx == UINT_MAX)
00135 assert(false && "dictionary_hash get() requires a hit");
00136
00137 return all_elems[ndx].val;
00138 }
00139
00140 template<class K, class V>
00141 V& dictionary_hash<K,V>::get(const K &key) {
00142 const unsigned ndx = locate(key, false);
00143
00144
00145 if (ndx == UINT_MAX)
00146 assert(false && "dictionary_hash get() requires a hit");
00147
00148 return all_elems[ndx].val;
00149 }
00150
00151 template<class K, class V>
00152 const V& dictionary_hash<K,V>::get_and_remove(const K &key) {
00153 const unsigned ndx = locate(key, false);
00154
00155
00156 if (ndx == UINT_MAX)
00157 assert(false && "dictionary_hash get_and_remove() requires a hit");
00158
00159 const unsigned oldsize = size();
00160
00161 entry &e = all_elems[ndx];
00162
00163 assert(!e.removed);
00164 e.removed = true;
00165 num_removed_elems++;
00166 assert(num_removed_elems <= all_elems.size());
00167
00168 assert(size() + 1 == oldsize);
00169
00170 return e.val;
00171 }
00172
00173 template<class K, class V>
00174 bool dictionary_hash<K,V>::find_and_remove(const K &key, V &val) {
00175 const unsigned ndx = locate(key, false);
00176
00177
00178 if (ndx == UINT_MAX)
00179 return false;
00180
00181 const unsigned oldsize = size();
00182
00183 entry &e = all_elems[ndx];
00184
00185 assert(!e.removed);
00186 e.removed = true;
00187 num_removed_elems++;
00188 assert(num_removed_elems <= all_elems.size());
00189
00190 assert(size() + 1 == oldsize);
00191
00192 val = e.val;
00193
00194 return true;
00195 }
00196
00197 template<class K, class V>
00198 void dictionary_hash<K,V>::set(const K &key, const V &val) {
00199 const unsigned ndx = locate(key, true);
00200
00201 if (ndx != UINT_MAX) {
00202
00203
00204 entry &theEntry = all_elems[ndx];
00205 if (theEntry.removed) {
00206 assert(num_removed_elems > 0);
00207 theEntry.val = val;
00208 theEntry.removed = false;
00209 num_removed_elems--;
00210
00211
00212
00213 }
00214 else
00215 assert(false && "dictionary set(): an entry with that key already exists");
00216 }
00217 else {
00218
00219 add(key, val);
00220
00221
00222 }
00223 }
00224
00225 template<class K, class V>
00226 TYPENAME dictionary_hash<K,V>::iterator
00227 dictionary_hash<K,V>::find(const K& key) {
00228 const unsigned ndx = locate(key, false);
00229 if (ndx == UINT_MAX) {
00230 return end();
00231 }
00232 else {
00233 TYPENAME dictionary_hash<K,V>::iterator dictIter(*this,
00234 GET_ITER(all_elems,ndx));
00235
00236 return dictIter;
00237 }
00238 }
00239
00240 template<class K, class V>
00241 TYPENAME dictionary_hash<K,V>::const_iterator
00242 dictionary_hash<K,V>::find(const K& key)
00243 const {
00244 const unsigned ndx = locate(key, false);
00245 if (ndx == UINT_MAX) {
00246 return end();
00247 }
00248 else {
00249 TYPENAME dictionary_hash<K,V>::const_iterator dictIter(*this,
00250 GET_ITER(all_elems,ndx));
00251
00252 #if 0
00253 TYPENAME dictionary_hash<K,V>::const_iterator dictIter(*this,
00254 all_elems.getIter(ndx));
00255 #endif
00256 return dictIter;
00257 }
00258 }
00259
00260 template<class K, class V>
00261 bool dictionary_hash<K,V>::find(const K& key, V& el) const {
00262 const unsigned ndx = locate(key, false);
00263 if (ndx == UINT_MAX)
00264 return false;
00265 else {
00266 el = all_elems[ndx].val;
00267 return true;
00268 }
00269 }
00270
00271 template<class K, class V>
00272 bool dictionary_hash<K,V>::find(const K& key, const V **el) const {
00273 const unsigned ndx = locate(key, false);
00274 if (ndx == UINT_MAX)
00275 return false;
00276 else {
00277 (*el) = &all_elems[ndx].val;
00278 return true;
00279 }
00280 }
00281
00282 template<class K, class V>
00283 bool dictionary_hash<K,V>::defines(const K& key) const {
00284 const unsigned ndx = locate(key, false);
00285 return (ndx != UINT_MAX);
00286 }
00287
00288 template<class K, class V>
00289 void dictionary_hash<K,V>::undef(const K& key) {
00290 unsigned ndx = locate(key, false);
00291 if (ndx == UINT_MAX)
00292 return;
00293
00294 #ifndef NDEBUG
00295 const unsigned oldsize = size();
00296 #endif
00297
00298 entry &e = all_elems[ndx];
00299 assert(!e.removed);
00300 e.removed = true;
00301 num_removed_elems++;
00302
00303 #ifndef NDEBUG
00304 assert(oldsize == size()+1);
00305 assert(num_removed_elems <= all_elems.size());
00306 #endif
00307 }
00308
00309 #ifndef _KERNEL
00310
00311
00312 template<class K, class V>
00313 pdvector<K>
00314 dictionary_hash<K,V>::keys() const {
00315
00316
00317
00318 pdvector<K> result;
00319 result.reserve(size());
00320
00321
00322 const_iterator finish = end();
00323 for (const_iterator iter=begin(); iter != finish; iter++)
00324 result.push_back(iter.currkey());
00325
00326 return result;
00327 }
00328
00329 template<class K, class V>
00330 pdvector<V>
00331 dictionary_hash<K,V>::values() const {
00332
00333
00334
00335 pdvector<V> result;
00336 result.reserve(size());
00337
00338
00339 const_iterator finish = end();
00340 for (const_iterator iter=begin(); iter != finish; ++iter)
00341 result.push_back(*iter);
00342
00343 return result;
00344 }
00345
00346 template<class K, class V>
00347 pdvector< pdpair<K, V> >
00348 dictionary_hash<K,V>::keysAndValues() const {
00349 pdvector< pdpair<K, V> > result;
00350 result.reserve(size());
00351
00352 const_iterator finish = end();
00353 for (const_iterator iter = begin(); iter != finish; ++iter)
00354 result.push_back( pdpair<K,V>(iter.currkey(), iter.currval()) );
00355
00356 return result;
00357 }
00358
00359 #endif //ifndef(_KERNEL)
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 template<class K, class V>
00392 void dictionary_hash<K,V>::clear() {
00393
00394
00395
00396
00397
00398
00399
00400 all_elems.clear();
00401
00402 for (unsigned lcv=0; lcv < bins.size(); lcv++)
00403 bins[lcv] = UINT_MAX;
00404
00405 num_removed_elems = 0;
00406
00407 assert(size() == 0);
00408
00409 assert(enoughBins());
00410 }
00411
00412 template<class K, class V>
00413 unsigned
00414 dictionary_hash<K,V>::locate(const K& key, bool evenIfRemoved) const {
00415
00416
00417
00418 if(hasher == NULL) {
00419 cerr << "hasher == NULL\n";
00420 assert(false);
00421 }
00422 unsigned hashval = hasher(key) & 0x7fffffff;
00423
00424 const unsigned bin = hashval % bins.size();
00425
00426 unsigned elem_ndx = bins[bin];
00427 while (elem_ndx != UINT_MAX) {
00428 const entry &elem = all_elems[elem_ndx];
00429
00430
00431 assert(elem.key_hashval % bins.size() == bin);
00432
00433 if (elem.key_hashval == hashval && elem.key == key) {
00434
00435 if (elem.removed && !evenIfRemoved)
00436 elem_ndx = UINT_MAX;
00437
00438 break;
00439 }
00440 else
00441 elem_ndx = elem.next;
00442 }
00443
00444 return elem_ndx;
00445 }
00446
00447
00448 template<class K, class V>
00449 unsigned
00450 dictionary_hash<K,V>::add(const K& key, const V &val) {
00451
00452
00453
00454
00455 assert(enoughBins());
00456
00457 if (!enoughBinsIf1MoreItemAdded()) {
00458
00459
00460
00461 const unsigned new_numbins = (unsigned)(bins.size() * bin_grow_factor);
00462 assert(new_numbins > bins.size() && "bin_grow_factor too small");
00463
00464 grow_numbins(new_numbins);
00465
00466
00467 assert(enoughBinsIf1MoreItemAdded());
00468
00469
00470 }
00471
00472
00473 const unsigned hashval = hasher(key) & 0x7fffffff;
00474 const unsigned bin = hashval % bins.size();
00475
00476 entry e(key, hashval, val, UINT_MAX);
00477 e.next = bins[bin];
00478 all_elems.push_back(e);
00479
00480
00481 const unsigned new_entry_ndx = all_elems.size()-1;
00482
00483
00484
00485 bins[bin] = new_entry_ndx;
00486
00487
00488
00489 assert(enoughBins());
00490 return new_entry_ndx;
00491 }
00492
00493 template<class K, class V>
00494 unsigned
00495 dictionary_hash<K,V>::locate_addIfNotFound(const K& key) {
00496
00497
00498
00499 unsigned result = locate(key, true);
00500
00501
00502 if (result == UINT_MAX)
00503 return add(key, V());
00504 else {
00505
00506 entry &e = all_elems[result];
00507 if (e.removed) {
00508
00509
00510
00511
00512 assert(num_removed_elems > 0);
00513
00514 e.removed = false;
00515 e.val = V();
00516 num_removed_elems--;
00517
00518
00519
00520 }
00521
00522
00523
00524 return result;
00525 }
00526 }
00527
00528 template<class K, class V>
00529 void
00530 dictionary_hash<K,V>::grow_numbins(unsigned new_numbins) {
00531 assert(new_numbins > bins.size() && "grow_numbins not adding any bins?");
00532
00533 bins.resize(new_numbins, true);
00534 for (unsigned binlcv=0; binlcv < bins.size(); binlcv++)
00535 bins[binlcv] = UINT_MAX;
00536
00537
00538 if (num_removed_elems > 0) {
00539 for (unsigned lcv=0; lcv < all_elems.size(); ) {
00540 entry &e = all_elems[lcv];
00541 if (e.removed) {
00542 const unsigned oldsize = all_elems.size();
00543 assert(oldsize > 0);
00544
00545
00546 all_elems[lcv] = all_elems[oldsize-1];
00547 all_elems.resize(oldsize-1);
00548
00549 num_removed_elems--;
00550
00551
00552 }
00553 else
00554 lcv++;
00555 }
00556
00557 assert(num_removed_elems == 0);
00558 }
00559
00560
00561
00562
00563
00564
00565
00566 const unsigned numbins = bins.size();
00567 for (unsigned lcv=0; lcv < all_elems.size(); lcv++) {
00568 entry &e = all_elems[lcv];
00569 assert(!e.removed);
00570
00571
00572 const unsigned bin = e.key_hashval % numbins;
00573
00574
00575 unsigned &thebin = bins[bin];
00576
00577 e.next = thebin;
00578 thebin = lcv;
00579 }
00580
00581
00582
00583 assert(enoughBins());
00584 }
00585
00586 #endif