-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathutil.h
151 lines (114 loc) · 2.97 KB
/
util.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
#include <cassert>
#include <cstdint>
#include <string>
typedef std::pair<unsigned, unsigned> Result;
/// A constant divisible by 2,3,4,5,6 used to score split results
constexpr unsigned KTie = 60;
/// Our PRNG class is a wrapper around Xoroshiro128+. Used for Monte Carlo
class PRNG {
uint64_t s[2];
uint64_t* buf;
void jump(void);
public:
PRNG(size_t idx, uint64_t seed = 0);
uint64_t next();
void set_enum_buffer(uint64_t* b) { buf = b; }
};
/// popcount() counts the number of non-zero bits in a uint64_t
inline int popcount(uint64_t b)
{
#ifndef USE_POPCNT
extern uint8_t PopCnt16[1 << 16];
union {
uint64_t bb;
uint16_t u[4];
} v = { b };
return PopCnt16[v.u[0]] + PopCnt16[v.u[1]] + PopCnt16[v.u[2]] + PopCnt16[v.u[3]];
#elif defined(_MSC_VER) || defined(__INTEL_COMPILER)
return (int)_mm_popcnt_u64(b);
#else // Assumed gcc or compatible compiler
return __builtin_popcountll(b);
#endif
}
/// lsb() and msb() return the least/most significant bit in a non-zero uint64_t
#if defined(__GNUC__) // GCC, Clang, ICC
inline int lsb(uint64_t b)
{
assert(b);
return __builtin_ctzll(b);
}
inline int msb(uint64_t b)
{
assert(b);
return 63 ^ __builtin_clzll(b);
}
#elif defined(_MSC_VER) // MSVC
#ifdef _WIN64 // MSVC, WIN64
inline unsigned long lsb(uint64_t b)
{
assert(b);
unsigned long idx;
_BitScanForward64(&idx, b);
return idx;
}
inline unsigned long msb(uint64_t b)
{
assert(b);
unsigned long idx;
_BitScanReverse64(&idx, b);
return idx;
}
#else // MSVC, WIN32
inline unsigned long lsb(uint64_t b)
{
assert(b);
unsigned long idx;
if (b & 0xffffffff) {
_BitScanForward(&idx, int32_t(b));
return idx;
} else {
_BitScanForward(&idx, int32_t(b >> 32));
return idx + 32;
}
}
inline unsigned long msb(uint64_t b)
{
assert(b);
unsigned long idx;
if (b >> 32) {
_BitScanReverse(&idx, int32_t(b >> 32));
return idx + 32;
} else {
_BitScanReverse(&idx, int32_t(b));
return idx;
}
}
#endif
#else // Compiler is neither GCC nor MSVC compatible
#error "Compiler not supported."
#endif
/// pop_lsb() finds and clears the least significant bit in a non-zero bitboard
inline unsigned pop_lsb(uint64_t* b)
{
const unsigned s = lsb(*b);
*b &= *b - 1;
return s;
}
/// pop_msb() finds and clears the most significant bit in a non-zero bitboard
inline unsigned pop_msb(uint64_t* b)
{
const unsigned s = msb(*b);
*b ^= 1ULL << s;
return s;
}
/// msb_bb() returns as a bitboard the most significant bit in a non-zero bitboard
inline uint64_t msb_bb(uint64_t b)
{
return 1ULL << msb(b);
}
/// Pretty printers of a uint64_t in "table of bits" format and of equity results
extern const std::string pretty64(uint64_t b, bool headers = false);
extern void pretty_results(Result* results, size_t players);
#endif // #ifndef UTIL_H_INCLUDED