00001 //---------------------------------------------------------------------------- 00002 /** @file TransTable.hpp 00003 */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef TRANSTABLE_H 00007 #define TRANSTABLE_H 00008 00009 #include <boost/concept_check.hpp> 00010 00011 #include "Hex.hpp" 00012 00013 _BEGIN_BENZENE_NAMESPACE_ 00014 00015 //---------------------------------------------------------------------------- 00016 00017 /** Concept of a state in a transposition table. */ 00018 template<class T> 00019 struct TransTableStateConcept 00020 { 00021 void constraints() 00022 { 00023 boost::function_requires< boost::DefaultConstructibleConcept<T> >(); 00024 boost::function_requires< boost::AssignableConcept<T> >(); 00025 00026 const T a; 00027 if (a.Initialized()) { } 00028 00029 const T b; 00030 if (a.ReplaceWith(b)) { } 00031 } 00032 }; 00033 00034 //---------------------------------------------------------------------------- 00035 00036 /** Transposition table. The state class must meet the requirements of 00037 TransTableStateConcept. */ 00038 template<class T> 00039 class TransTable 00040 { 00041 BOOST_CLASS_REQUIRE(T, benzene, TransTableStateConcept); 00042 00043 public: 00044 00045 /** Creates table with 2^n slots. */ 00046 TransTable(int bits); 00047 00048 /** Destructor. */ 00049 ~TransTable(); 00050 00051 /** Returns lg2 of number of entries. */ 00052 std::size_t Bits() const; 00053 00054 /** Returns the number of slots in the TT. */ 00055 std::size_t Size() const; 00056 00057 /** Clears the table. */ 00058 void Clear(); 00059 00060 /** Stores data in slot for hash. New data 00061 overwrites old only if "old.ReplaceWith(new)" is true. 00062 */ 00063 bool Put(hash_t hash, const T& data); 00064 00065 /** Returns true if the slot for hash contains a state with that 00066 hash value, data is copied into data if so. Otherwise, nothing 00067 is copied into data. 00068 */ 00069 bool Get(hash_t hash, T& data); 00070 00071 /** Returns statistics in string form. */ 00072 std::string Stats() const; 00073 00074 private: 00075 00076 // ----------------------------------------------------------------------- 00077 00078 struct Statistics 00079 { 00080 unsigned reads; 00081 unsigned hits; 00082 unsigned writes; 00083 unsigned overwrites; 00084 00085 Statistics() : reads(0), hits(0), writes(0), overwrites(0) { } 00086 }; 00087 00088 // ----------------------------------------------------------------------- 00089 00090 int m_bits; 00091 00092 std::size_t m_size; 00093 00094 std::size_t m_mask; 00095 00096 std::vector<T> m_data; 00097 00098 std::vector<hash_t> m_hash; 00099 00100 Statistics m_stats; 00101 }; 00102 00103 //---------------------------------------------------------------------------- 00104 00105 template<typename T> 00106 TransTable<T>::TransTable(int bits) 00107 : m_bits(bits), 00108 m_size(1 << bits), 00109 m_mask(m_size - 1), 00110 m_data(m_size), 00111 m_hash(m_size, 0), 00112 m_stats() 00113 { 00114 Clear(); 00115 } 00116 00117 template<typename T> 00118 TransTable<T>::~TransTable() 00119 { 00120 } 00121 00122 template<typename T> 00123 inline std::size_t TransTable<T>::Bits() const 00124 { 00125 return m_bits; 00126 } 00127 00128 template<typename T> 00129 inline std::size_t TransTable<T>::Size() const 00130 { 00131 return m_size; 00132 } 00133 00134 template<typename T> 00135 inline void TransTable<T>::Clear() 00136 { 00137 for (std::size_t i = 0; i < m_size; ++i) 00138 { 00139 m_data[i] = T(); 00140 m_hash[i] = 0; 00141 } 00142 } 00143 00144 template<typename T> 00145 bool TransTable<T>::Put(hash_t hash, const T& data) 00146 { 00147 std::size_t slot = hash & m_mask; 00148 if (m_data[slot].ReplaceWith(data)) 00149 { 00150 m_stats.writes++; 00151 if (m_hash[slot] && m_hash[slot] != hash) 00152 m_stats.overwrites++; 00153 m_data[slot] = data; 00154 m_hash[slot] = hash; 00155 } 00156 return true; 00157 } 00158 00159 template<typename T> 00160 bool TransTable<T>::Get(hash_t hash, T& data) 00161 { 00162 m_stats.reads++; 00163 std::size_t slot = hash & m_mask; 00164 T& old = m_data[slot]; 00165 bool ret = old.Initialized() && (m_hash[slot] == hash); 00166 if (ret) 00167 { 00168 data = old; 00169 m_stats.hits++; 00170 } 00171 return ret; 00172 } 00173 00174 template<typename T> 00175 std::string TransTable<T>::Stats() const 00176 { 00177 std::ostringstream os; 00178 os << "TT statistics\n" 00179 << "Reads " << m_stats.reads << '\n' 00180 << "Hits " << m_stats.hits << '\n' 00181 << "Writes " << m_stats.writes << '\n' 00182 << "Overwrites " << m_stats.overwrites << '\n'; 00183 return os.str(); 00184 } 00185 00186 //---------------------------------------------------------------------------- 00187 00188 _END_BENZENE_NAMESPACE_ 00189 00190 #endif // TRANSTABLE_H