|
Teuchos - Trilinos Tools Package
Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Teuchos: Common Tools Package 00005 // Copyright (2004) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // *********************************************************************** 00040 // @HEADER 00041 00042 #ifndef TEUCHOS_HASHTABLE_H 00043 #define TEUCHOS_HASHTABLE_H 00044 00049 #include "Teuchos_ConfigDefs.hpp" 00050 #include "Teuchos_Array.hpp" 00051 #include "Teuchos_HashUtils.hpp" 00052 00053 namespace Teuchos 00054 { 00055 using std::string; 00056 00060 template<class Key, class Value> class HashPair 00061 { 00062 public: 00064 inline HashPair() : key_(), value_() {;} 00066 inline HashPair(const Key& key, const Value& value) 00067 : key_(key), value_(value) {;} 00068 00070 Key key_; 00072 Value value_; 00073 }; 00074 00080 template<class Key, class Value> class Hashtable 00081 { 00082 public: 00083 00085 inline Hashtable(int capacity=101, double rehashDensity = 0.8); 00086 00088 inline bool containsKey(const Key& key) const ; 00089 00091 inline const Value& get(const Key& key) const ; 00092 00094 inline void put(const Key& key, const Value& value); 00095 00097 inline void remove(const Key& key); 00098 00100 inline int size() const {return count_;} 00101 00103 inline void arrayify(Array<Key>& keys, Array<Value>& values) const ; 00104 00106 inline double avgDegeneracy() const {return avgDegeneracy_;} 00107 00109 inline double density() const {return ((double)count_)/((double) capacity_);} 00110 00112 inline void setRehashDensity(double rehashDensity); 00113 00115 inline std::string toString() const ; 00116 00117 private: 00118 00119 inline void rehash(); 00120 inline int nextPrime(int newCap) const ; 00121 inline void accumulateAvgFill(int n) const ; 00122 00123 00124 Array<Array<HashPair<Key, Value> > > data_; 00125 int count_; 00126 int capacity_; 00127 mutable Value mostRecentValue_; 00128 mutable Key mostRecentKey_; 00129 00130 mutable size_t nHits_; 00131 mutable double avgDegeneracy_; 00132 double rehashDensity_; 00133 }; 00134 00135 template<class Key, class Value> 00136 std::string toString(const Hashtable<Key, Value>& h); 00137 00141 template<class Key, class Value> 00142 std::ostream& operator<<(std::ostream& os, const Hashtable<Key, Value>& h); 00143 00144 template<class Key, class Value> inline 00145 Hashtable<Key, Value>::Hashtable(int capacity, double rehashDensity): 00146 data_(), 00147 count_(0), 00148 capacity_(HashUtils::nextPrime(capacity)), 00149 nHits_(0), 00150 avgDegeneracy_(0), 00151 rehashDensity_(rehashDensity) 00152 { 00153 data_.resize(capacity_); 00154 } 00155 00156 template<class Key, class Value> inline 00157 bool Hashtable<Key, Value>::containsKey(const Key& key) const 00158 { 00159 const Array<HashPair<Key, Value> >& candidates 00160 = data_[hashCode(key) % capacity_]; 00161 00162 for (int i=0; i<candidates.length(); i++) 00163 { 00164 const HashPair<Key, Value>& c = candidates[i]; 00165 if (c.key_ == key) 00166 { 00167 // (Key&) mostRecentKey_ = key; 00168 //(Value&) mostRecentValue_ = c.value_; 00169 return true; 00170 } 00171 } 00172 return false; 00173 } 00174 00175 template<class Key, class Value> inline 00176 void Hashtable<Key, Value>::put(const Key& key, const Value& value) 00177 { 00178 int index = hashCode(key) % capacity_; 00179 00180 Array<HashPair<Key, Value> >& local = data_[index]; 00181 00182 // check for duplicate key 00183 for (int i=0; i<local.length(); i++) 00184 { 00185 if (local[i].key_ == key) 00186 { 00187 local[i].value_ = value; 00188 return; 00189 } 00190 } 00191 00192 // no duplicate key, so increment element count by one. 00193 count_++; 00194 00195 // check for need to resize. 00196 if ((double) count_ > rehashDensity_ * (double) capacity_) 00197 { 00198 capacity_ = HashUtils::nextPrime(capacity_+1); 00199 rehash(); 00200 // recaluate index 00201 index = hashCode(key) % capacity_; 00202 } 00203 00204 data_[index].append(HashPair<Key, Value>(key, value)); 00205 } 00206 00207 00208 00209 template<class Key, class Value> inline 00210 void Hashtable<Key, Value>::rehash() 00211 { 00212 Array<Array<HashPair<Key, Value> > > tmp(capacity_); 00213 00214 for (int i=0; i<data_.length(); i++) 00215 { 00216 for (int j=0; j<data_[i].length(); j++) 00217 { 00218 int newIndex = hashCode(data_[i][j].key_) % capacity_; 00219 tmp[newIndex].append(data_[i][j]); 00220 } 00221 } 00222 00223 data_ = tmp; 00224 } 00225 00226 00227 template<class Key, class Value> inline 00228 void Hashtable<Key, Value>::arrayify(Array<Key>& keys, Array<Value>& values) const 00229 { 00230 keys.reserve(size()); 00231 values.reserve(size()); 00232 00233 for (int i=0; i<data_.length(); i++) 00234 { 00235 for (int j=0; j<data_[i].length(); j++) 00236 { 00237 keys.append(data_[i][j].key_); 00238 values.append(data_[i][j].value_); 00239 } 00240 } 00241 } 00242 00243 template<class Key, class Value> inline 00244 std::string Hashtable<Key, Value>::toString() const 00245 { 00246 Array<Key> keys; 00247 Array<Value> values; 00248 arrayify(keys, values); 00249 00250 std::string rtn = "["; 00251 for (int i=0; i<keys.length(); i++) 00252 { 00253 rtn += "{" + Teuchos::toString(keys[i]) + ", " + Teuchos::toString(values[i]) 00254 + "}"; 00255 if (i < keys.length()-1) rtn += ", "; 00256 } 00257 rtn += "]"; 00258 00259 return rtn; 00260 } 00261 00262 template<class Key, class Value> inline 00263 std::string toString(const Hashtable<Key, Value>& h) 00264 { 00265 Array<Key> keys; 00266 Array<Value> values; 00267 h.arrayify(keys, values); 00268 00269 std::string rtn = "["; 00270 for (int i=0; i<keys.length(); i++) 00271 { 00272 rtn += "{" + Teuchos::toString(keys[i]) + ", " + Teuchos::toString(values[i]) 00273 + "}"; 00274 if (i < keys.length()-1) rtn += ", "; 00275 } 00276 rtn += "]"; 00277 00278 return rtn; 00279 } 00280 00281 template<class Key, class Value> inline 00282 const Value& Hashtable<Key, Value>::get(const Key& key) const 00283 { 00284 TEUCHOS_TEST_FOR_EXCEPTION(!containsKey(key), 00285 std::runtime_error, 00286 "Hashtable<Key, Value>::get: key " 00287 << Teuchos::toString(key) 00288 << " not found in Hashtable" 00289 << toString()); 00290 00291 const Array<HashPair<Key, Value> >& candidates 00292 = data_[hashCode(key) % capacity_]; 00293 00294 accumulateAvgFill(candidates.length()); 00295 00296 for (int i=0; i<candidates.length(); i++) 00297 { 00298 const HashPair<Key, Value>& c = candidates[i]; 00299 if (c.key_ == key) 00300 { 00301 return c.value_; 00302 } 00303 } 00304 return mostRecentValue_; 00305 } 00306 00307 00308 template<class Key, class Value> inline 00309 void Hashtable<Key, Value>::remove(const Key& key) 00310 { 00311 TEUCHOS_TEST_FOR_EXCEPTION(!containsKey(key), 00312 std::runtime_error, 00313 "Hashtable<Key, Value>::remove: key " 00314 << Teuchos::toString(key) 00315 << " not found in Hashtable" 00316 << toString()); 00317 00318 count_--; 00319 int h = hashCode(key) % capacity_; 00320 const Array<HashPair<Key, Value> >& candidates = data_[h]; 00321 00322 for (int i=0; i<candidates.length(); i++) 00323 { 00324 const HashPair<Key, Value>& c = candidates[i]; 00325 if (c.key_ == key) 00326 { 00327 data_[h].remove(i); 00328 break; 00329 } 00330 } 00331 } 00332 00333 template<class Key, class Value> inline 00334 void Hashtable<Key, Value>::accumulateAvgFill(int n) const 00335 { 00336 avgDegeneracy_ = ((double) nHits_)/(nHits_ + 1.0) * avgDegeneracy_ + ((double) n)/(nHits_ + 1.0); 00337 nHits_++; 00338 } 00339 00340 template<class Key, class Value> inline 00341 std::ostream& operator<<(std::ostream& os, const Hashtable<Key, Value>& h) 00342 { 00343 return os << toString(h); 00344 } 00345 00346 00347 } 00348 00349 #endif // TEUCHOS_HASHTABLE_H
1.7.6.1