Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  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_ */
  301.