Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgHashTable.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgHashTable.h
00003     Hash table.
00004 */
00005 //----------------------------------------------------------------------------
00006 
00007 #ifndef SG_HASHTABLE_H
00008 #define SG_HASHTABLE_H
00009 
00010 #include "SgHash.h"
00011 #include "SgWrite.h"
00012 
00013 //----------------------------------------------------------------------------
00014 
00015 /** Entry in a HashTable: code and data */
00016 template <class DATA>
00017 struct SgHashEntry
00018 {
00019     SgHashEntry()
00020         : m_hash(),
00021           m_data()
00022     { }
00023 
00024     SgHashEntry(const SgHashCode& code, const DATA& data)
00025         : m_hash(code),
00026           m_data(data)
00027     { }
00028 
00029     SgHashCode m_hash;
00030 
00031     DATA m_data;
00032 };
00033 
00034 //----------------------------------------------------------------------------
00035 
00036 /** HashTable implements an array of DATA */
00037 template <class DATA>
00038 class SgHashTable
00039 {
00040 public:
00041     /** Create a hash table with 'maxHash' entries. */
00042     explicit SgHashTable(int maxHash);
00043 
00044     ~SgHashTable();
00045 
00046     /** Leaves the positions in the hash table, but set all depths to zero, so
00047         that only the best move is valid, not the value. The hash entries will
00048         easily be replaced by fresh information.
00049     */
00050     void Age();
00051 
00052     /** Clear the hash table by marking all entries as invalid. */
00053     void Clear();
00054 
00055     /** Return true and the data stored under that code, or false if
00056         none stored.
00057     */
00058     bool Lookup(const SgHashCode& code, DATA* data) const;
00059 
00060     /** Size of hash table. */
00061     int MaxHash() const;
00062 
00063     /** Try to store 'data' under the hash code 'code'.
00064         Return whether the data was stored. The only reason for not storing
00065         it would be some 'better' data already hashing to the same hash code.
00066     */
00067     bool Store(const SgHashCode& code, const DATA& data);
00068 
00069     /** number of collisions on store */
00070     int NuCollisions() const
00071     {
00072         return m_nuCollisions;
00073     }
00074 
00075     /** total number of stores attempted */
00076     int NuStores() const
00077     {
00078         return m_nuStores;
00079     }
00080 
00081     /** total number of lookups attempted */
00082     int NuLookups() const
00083     {
00084         return m_nuLookups;
00085     }
00086 
00087     /** number of successful lookups */
00088     int NuFound() const
00089     {
00090         return m_nuFound;
00091     }
00092 
00093 private:
00094     /** complete hash code for each entry */
00095     SgHashEntry<DATA>* m_entry;
00096 
00097     /** size of hash table */
00098     int m_maxHash;
00099 
00100     // AR: the following statistics can be made debug only
00101     // AR: pass a HashStatistics class to the HashTable when constructed
00102 
00103     /** number of collisions on store */
00104     mutable int m_nuCollisions;
00105 
00106     /** total number of stores attempted */
00107     mutable int m_nuStores;
00108 
00109     /** total number of lookups attempted */
00110     mutable int m_nuLookups;
00111 
00112     /** number of successful lookups */
00113     mutable int m_nuFound;
00114 
00115     /** not implemented */
00116     SgHashTable(const SgHashTable&);
00117 
00118     /** not implemented */
00119     SgHashTable& operator=(const SgHashTable&);
00120 };
00121 
00122 template <class DATA>
00123 SgHashTable<DATA>::SgHashTable(int maxHash)
00124  : m_entry(0),
00125    m_maxHash(maxHash),
00126    m_nuCollisions(0),
00127    m_nuStores(0),
00128    m_nuLookups(0),
00129    m_nuFound(0)
00130 {
00131     m_entry = new SgHashEntry<DATA>[m_maxHash];
00132     Clear();
00133 }
00134 
00135 template <class DATA>
00136 SgHashTable<DATA>::~SgHashTable()
00137 {
00138     delete[] m_entry;
00139 }
00140 
00141 template <class DATA>
00142 void SgHashTable<DATA>::Age()
00143 {
00144     for (int i = m_maxHash-1; i >= 0; --i)
00145     {
00146         m_entry[i].m_data.AgeData();
00147     }
00148 }
00149 
00150 template <class DATA>
00151 void SgHashTable<DATA>::Clear()
00152 {
00153     for (int i = m_maxHash-1; i >= 0; --i)
00154     {
00155         m_entry[i].m_data.Invalidate();
00156     }
00157 }
00158 
00159 template <class DATA>
00160 int SgHashTable<DATA>::MaxHash() const
00161 {
00162     return m_maxHash;
00163 }
00164 
00165 template <class DATA>
00166 bool SgHashTable<DATA>::Store(const SgHashCode& code, const DATA& data)
00167 {
00168     ++m_nuStores;
00169     int h = code.Hash(m_maxHash);
00170     SgHashEntry<DATA>& entry = m_entry[h];
00171     if (entry.m_data.IsValid() && code != entry.m_hash)
00172         ++m_nuCollisions;
00173     if (! entry.m_data.IsValid() || data.IsBetterThan(entry.m_data))
00174     {
00175         entry.m_hash = code;
00176         entry.m_data = data;
00177         return true;
00178     }
00179     return false;
00180 }
00181 
00182 template <class DATA>
00183 bool SgHashTable<DATA>::Lookup(const SgHashCode& code, DATA* data) const
00184 {
00185     ++m_nuLookups;
00186     int h = code.Hash(m_maxHash);
00187     const SgHashEntry<DATA>& entry = m_entry[h];
00188     if (entry.m_data.IsValid() && entry.m_hash == code)
00189     {
00190         *data = entry.m_data;
00191         ++m_nuFound;
00192         return true;
00193     }
00194     return false;
00195 }
00196 
00197 //----------------------------------------------------------------------------
00198 
00199 /** Writes statistics on hash table use (not the content) */
00200 template <class DATA>
00201 std::ostream& operator<<(std::ostream& out, const SgHashTable<DATA>& hash)
00202 {    
00203     out << "HashTableStatistics:\n"
00204         << SgWriteLabel("Stores") << hash.NuStores() << '\n'
00205         << SgWriteLabel("LookupAttempt") << hash.NuLookups() << '\n'
00206         << SgWriteLabel("LookupSuccess") << hash.NuFound() << '\n'
00207         << SgWriteLabel("Collisions") << hash.NuCollisions() << '\n';
00208     return out;
00209 }
00210 
00211 #endif // SG_HASHTABLE_H


17 Jun 2010 Doxygen 1.4.7