Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 pmbaty 1
/*
2
    Texel - A UCI chess engine.
3
    Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com
4
 
5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9
 
10
    This program 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 General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
 
19
/*
20
 * util.hpp
21
 *
22
 *  Created on: Feb 26, 2012
23
 *      Author: petero
24
 */
25
 
26
#ifndef UTIL_HPP_
27
#define UTIL_HPP_
28
 
29
#include <cstddef>
30
#include <cstdint>
31
#include <string>
32
#include <cstdlib>
33
#include <sstream>
34
#include <vector>
35
#include <array>
36
#include <algorithm>
37
#include <atomic>
38
#include <cctype>
39
#include <iomanip>
40
 
41
using U64 = uint64_t;
42
using S64 = int64_t;
43
using U32 = uint32_t;
44
using S32 = int32_t;
45
using U16 = uint16_t;
46
using S16 = int16_t;
47
using S8  = int8_t;
48
using U8  = uint8_t;
49
 
50
template <typename T, size_t N> char (&ArraySizeHelper(T(&array)[N]))[N];
51
#define COUNT_OF(array) (sizeof(ArraySizeHelper(array)))
52
 
53
template <typename T> class AlignedAllocator;
54
/** std::vector with cache line aware allocator. */
55
template <typename T>
56
class vector_aligned : public std::vector<T, AlignedAllocator<T>> { };
57
 
58
 
59
/** Helper class to perform static initialization of a class T. */
60
template <typename T>
61
class StaticInitializer {
62
public:
63
    StaticInitializer() {
64
        T::staticInitialize();
65
    }
66
};
67
 
68
template <typename T>
69
T clamp(T val, T min, T max) {
70
    if (val < min)
71
        return min;
72
    else if (val > max)
73
        return max;
74
    else
75
        return val;
76
}
77
 
78
/** Return integer 2-logarithm of a positive number. */
79
int floorLog2(U32 x);
80
 
81
// ----------------------------------------------------------------------------
82
 
83
/** Split a string using " " as delimiter. Append words to out. */
84
inline void
85
splitString(const std::string& str, std::vector<std::string>& out)
86
{
87
    std::string word;
88
    std::istringstream iss(str, std::istringstream::in);
89
    while (iss >> word)
90
        out.push_back(word);
91
}
92
 
93
/** Convert a string to a number. */
94
template <typename T>
95
bool
96
str2Num(const std::string& str, T& result) {
97
    std::stringstream ss(str);
98
    ss >> result;
99
    return !!ss;
100
}
101
#if defined(__linux__) && !defined(__arm__) && !defined(__ANDROID__)
102
inline bool
103
str2Num(const std::string& str, int& result) {
104
    try {
105
        result = std::stoi(str);
106
        return true;
107
    } catch (...) {
108
        result = 0;
109
        return false;
110
    }
111
}
112
inline bool
113
str2Num(const std::string& str, double& result) {
114
    try {
115
        result = std::stod(str);
116
        return true;
117
    } catch (...) {
118
        result = 0.0;
119
        return false;
120
    }
121
}
122
#endif
123
 
124
template <typename T>
125
bool
126
hexStr2Num(const std::string& str, T& result) {
127
    std::stringstream ss;
128
    ss << std::hex << str;
129
    ss >> result;
130
    return !!ss;
131
}
132
 
133
template <typename T>
134
inline std::string
135
num2Str(const T& num) {
136
    std::stringstream ss;
137
    ss << num;
138
    return ss.str();
139
}
140
 
141
inline std::string
142
num2Hex(U64 num) {
143
    std::stringstream ss;
144
    ss << std::hex << std::setw(16) << std::setfill('0') << num;
145
    return ss.str();
146
}
147
 
148
/** Convert string to lower case. */
149
inline std::string
150
toLowerCase(std::string str) {
151
  for (size_t i = 0; i < str.length(); i++)
152
    str[i] = std::tolower(str[i]);
153
  return str;
154
}
155
 
156
inline bool
157
startsWith(const std::string& str, const std::string& startsWith) {
158
    size_t N = startsWith.length();
159
    if (str.length() < N)
160
        return false;
161
    for (size_t i = 0; i < N; i++)
162
        if (str[i] != startsWith[i])
163
            return false;
164
    return true;
165
}
166
 
167
inline bool
168
endsWith(const std::string& str, const std::string& endsWith) {
169
    size_t N = endsWith.length();
170
    size_t sN = str.length();
171
    if (sN < N)
172
        return false;
173
    for (size_t i = 0; i < N; i++)
174
        if (str[sN - N + i] != endsWith[i])
175
            return false;
176
    return true;
177
}
178
 
179
/** Return true if vector v contains element e. */
180
template <typename T>
181
inline bool
182
contains(const std::vector<T>& v, const T& e) {
183
    return std::find(v.begin(), v.end(), e) != v.end();
184
}
185
 
186
/** Return true if vector v contains element e converted to a string. */
187
inline bool
188
contains(const std::vector<std::string> v, const char* e) {
189
    return contains(v, std::string(e));
190
}
191
 
192
inline std::string
193
trim(const std::string& s) {
194
    for (int i = 0; i < (int)s.length(); i++) {
195
        if (!isspace(s[i])) {
196
            for (int j = (int)s.length()-1; j >= i; j--)
197
                if (!isspace(s[j]))
198
                    return s.substr(i, j-i+1);
199
            return "";
200
        }
201
    }
202
    return "";
203
}
204
 
205
// ----------------------------------------------------------------------------
206
 
207
// A fixed size array that can compute the sum of a range of values in time O(log N)
208
template <int N>
209
class RangeSumArray {
210
public:
211
 
212
    /** Get value at index i. */
213
    int get(size_t i) const {
214
        return arr[i];
215
    }
216
 
217
    /** Add delta to value at index i. */
218
    void add(size_t i, int delta) {
219
        arr[i] += delta;
220
        pairs.add(i/2, delta);
221
    }
222
 
223
    /** Compute sum of all elements in [b,e). */
224
    int sum(size_t b, size_t e) const {
225
        int result = 0;
226
        sumHelper(b, e, result);
227
        return result;
228
    }
229
 
230
private:
231
    template <int N2> friend class RangeSumArray;
232
 
233
    void sumHelper(size_t b, size_t e, int& result) const {
234
        if (b >= e)
235
            return;
236
        if (b & 1) {
237
            result += arr[b];
238
            b++;
239
        }
240
        if (e & 1) {
241
            if (e != N)
242
                result -= arr[e];
243
            e++;
244
        }
245
        pairs.sumHelper(b/2, e/2, result);
246
    }
247
 
248
    std::array<std::atomic<int>, N> arr {};
249
    RangeSumArray<(N+1)/2> pairs;
250
};
251
 
252
template<>
253
class RangeSumArray<1> {
254
public:
255
    int get(size_t i) const {
256
        return value;
257
    }
258
 
259
    void add(size_t i, int delta) {
260
        value += delta;
261
    }
262
 
263
    int sum(size_t b, size_t e) const {
264
        int result = 0;
265
        sumHelper(b, e, result);
266
        return result;
267
    }
268
 
269
private:
270
    template <int N2> friend class RangeSumArray;
271
 
272
    void sumHelper(size_t b, size_t e, int& result) const {
273
        if (b < e)
274
            result += value;
275
    }
276
 
277
    std::atomic<int> value { 0 };
278
};
279
 
280
// ----------------------------------------------------------------------------
281
 
282
/** Helper class for shared data where read/write accesses do not have to be sequentially ordered.
283
 * This typically generates code as efficient as using a plain T. However using a plain T in this
284
 * context would invoke undefined behavior, see section 1.10.21 in the C++11 standard. */
285
template <typename T>
286
class RelaxedShared {
287
public:
288
    RelaxedShared<T>() { }
289
    RelaxedShared<T>(T value) { set(value); }
290
    RelaxedShared<T>(const RelaxedShared<T>& r) { set(r.get()); }
291
    RelaxedShared<T>& operator=(const RelaxedShared<T>& r) { set(r.get()); return *this; }
292
    RelaxedShared<T>& operator=(const T& t) { set(t); return *this; }
293
    operator T() const { return get(); }
294
    T get() const { return data.load(std::memory_order_relaxed); }
295
    void set(T value) { data.store(value, std::memory_order_relaxed); }
296
private:
297
    std::atomic<T> data;
298
};
299
 
300
#endif /* UTIL_HPP_ */