BitBully 0.0.39
Loading...
Searching...
No Matches
TranspositionTable.hpp
1/*
2 * This file is part of Connect4 Game Solver <http://connect4.gamesolver.org>
3 * Copyright (C) 2017-2019 Pascal Pons <contact@gamesolver.org>
4 *
5 * Connect4 Game Solver is free software: you can redistribute it and/or
6 * modify it under the terms of the GNU Affero General Public License as
7 * published by the Free Software Foundation, either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * Connect4 Game Solver is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with Connect4 Game Solver. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef TRANSPOSITION_TABLE_HPP
20#define TRANSPOSITION_TABLE_HPP
21
22#include <cstring>
23
24namespace GameSolver {
25namespace Connect4 {
26
30constexpr uint64_t med(uint64_t min, uint64_t max) {
31 return (min + max) / 2;
32}
36constexpr bool has_factor(uint64_t n, uint64_t min, uint64_t max) {
37 return min * min > n ? false : // do not search for factor above sqrt(n)
38 min + 1 >= max ? n % min == 0 :
39 has_factor(n, min, med(min, max)) || has_factor(n, med(min, max), max);
40}
41
42// return next prime number greater or equal to n.
43// n must be >= 2
44constexpr uint64_t next_prime(uint64_t n) {
45 return has_factor(n, 2, n) ? next_prime(n + 1) : n;
46}
47
48// log2(1) = 0; log2(2) = 1; log2(3) = 1; log2(4) = 2; log2(8) = 3
49constexpr unsigned int log2(unsigned int n) {
50 return n <= 1 ? 0 : log2(n / 2) + 1;
51}
52
56template<class key_t, class value_t>
58 private:
59 virtual void* getKeys() = 0;
60 virtual void* getValues() = 0;
61 virtual size_t getSize() = 0;
62 virtual int getKeySize() = 0;
63 virtual int getValueSize() = 0;
64
65 public:
66 virtual value_t get(key_t key) const = 0;
67 virtual ~TableGetter() {};
68
69 friend class OpeningBook;
70};
71
72// uint_t<S> is a template type providing an unsigned int able to fit interger of S bits.
73// uint_t<8> = uint8_t and uint_t<9> = uint_16t
74template<int S> using uint_t =
75 typename std::conditional < S <= 8, uint_least8_t,
76 typename std::conditional < S <= 16, uint_least16_t,
77 typename std::conditional<S <= 32, uint_least32_t,
78 uint_least64_t>::type>::type >::type;
79
93template<class partial_key_t, class key_t, class value_t, int log_size>
94class TranspositionTable : public TableGetter<key_t, value_t> {
95 private:
96 static const size_t size = next_prime(1 << log_size); // size of the transition table. Have to be odd to be prime with 2^sizeof(key_t)
97 partial_key_t *K; // Array to store truncated version of keys;
98 value_t *V; // Array to store values;
99
100 void* getKeys() override {return K;}
101 void* getValues() override {return V;}
102 size_t getSize() override {return size;}
103 int getKeySize() override {return sizeof(partial_key_t);}
104 int getValueSize() override {return sizeof(value_t);}
105
106 size_t index(key_t key) const {
107 return key % size;
108 }
109
110 public:
111 TranspositionTable() {
112 K = new partial_key_t[size];
113 V = new value_t[size];
114 reset();
115 }
116
117 ~TranspositionTable() {
118 delete[] K;
119 delete[] V;
120 }
121
125 void reset() { // fill everything with 0, because 0 value means missing data
126 memset(K, 0, size * sizeof(partial_key_t));
127 memset(V, 0, size * sizeof(value_t));
128 }
129
135 void put(key_t key, value_t value) {
136 size_t pos = index(key);
137 K[pos] = key; // key is possibly trucated as key_t is possibly less than key_size bits.
138 V[pos] = value;
139 }
140
146 value_t get(key_t key) const override {
147 size_t pos = index(key);
148 if(K[pos] == (partial_key_t)key) return V[pos]; // need to cast to key_t because key may be truncated due to size of key_t
149 else return 0;
150 }
151};
152
153} // namespace Connect4
154} // namespace GameSolver
155#endif
value_t get(key_t key) const override