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


Sun Mar 13 2011 Doxygen 1.7.1