- /* 
-     Texel - A UCI chess engine. 
-     Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com 
-   
-     This program is free software: you can redistribute it and/or modify 
-     it under the terms of the GNU General Public License as published by 
-     the Free Software Foundation, either version 3 of the License, or 
-     (at your option) any later version. 
-   
-     This program is distributed in the hope that it will be useful, 
-     but WITHOUT ANY WARRANTY; without even the implied warranty of 
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-     GNU General Public License for more details. 
-   
-     You should have received a copy of the GNU General Public License 
-     along with this program.  If not, see <http://www.gnu.org/licenses/>. 
- */ 
-   
- /* 
-  * util.hpp 
-  * 
-  *  Created on: Feb 26, 2012 
-  *      Author: petero 
-  */ 
-   
- #ifndef UTIL_HPP_ 
- #define UTIL_HPP_ 
-   
- #include <cstddef> 
- #include <cstdint> 
- #include <string> 
- #include <cstdlib> 
- #include <sstream> 
- #include <vector> 
- #include <array> 
- #include <algorithm> 
- #include <atomic> 
- #include <cctype> 
- #include <iomanip> 
-   
- using U64 = uint64_t; 
- using S64 = int64_t; 
- using U32 = uint32_t; 
- using S32 = int32_t; 
- using U16 = uint16_t; 
- using S16 = int16_t; 
- using S8  = int8_t; 
- using U8  = uint8_t; 
-   
- template <typename T, size_t N> char (&ArraySizeHelper(T(&array)[N]))[N]; 
- #define COUNT_OF(array) (sizeof(ArraySizeHelper(array))) 
-   
- template <typename T> class AlignedAllocator; 
- /** std::vector with cache line aware allocator. */ 
- template <typename T> 
- class vector_aligned : public std::vector<T, AlignedAllocator<T>> { }; 
-   
-   
- /** Helper class to perform static initialization of a class T. */ 
- template <typename T> 
- class StaticInitializer { 
- public: 
-     StaticInitializer() { 
-         T::staticInitialize(); 
-     } 
- }; 
-   
- template <typename T> 
- T clamp(T val, T min, T max) { 
-     if (val < min) 
-         return min; 
-     else if (val > max) 
-         return max; 
-     else 
-         return val; 
- } 
-   
- /** Return integer 2-logarithm of a positive number. */ 
- int floorLog2(U32 x); 
-   
- // ---------------------------------------------------------------------------- 
-   
- /** Split a string using " " as delimiter. Append words to out. */ 
- inline void 
- splitString(const std::string& str, std::vector<std::string>& out) 
- { 
-     std::string word; 
-     std::istringstream iss(str, std::istringstream::in); 
-     while (iss >> word) 
-         out.push_back(word); 
- } 
-   
- /** Convert a string to a number. */ 
- template <typename T> 
- bool 
- str2Num(const std::string& str, T& result) { 
-     std::stringstream ss(str); 
-     ss >> result; 
-     return !!ss; 
- } 
- #if defined(__linux__) && !defined(__arm__) && !defined(__ANDROID__) 
- inline bool 
- str2Num(const std::string& str, int& result) { 
-     try { 
-         result = std::stoi(str); 
-         return true; 
-     } catch (...) { 
-         result = 0; 
-         return false; 
-     } 
- } 
- inline bool 
- str2Num(const std::string& str, double& result) { 
-     try { 
-         result = std::stod(str); 
-         return true; 
-     } catch (...) { 
-         result = 0.0; 
-         return false; 
-     } 
- } 
- #endif 
-   
- template <typename T> 
- bool 
- hexStr2Num(const std::string& str, T& result) { 
-     std::stringstream ss; 
-     ss << std::hex << str; 
-     ss >> result; 
-     return !!ss; 
- } 
-   
- template <typename T> 
- inline std::string 
- num2Str(const T& num) { 
-     std::stringstream ss; 
-     ss << num; 
-     return ss.str(); 
- } 
-   
- inline std::string 
- num2Hex(U64 num) { 
-     std::stringstream ss; 
-     ss << std::hex << std::setw(16) << std::setfill('0') << num; 
-     return ss.str(); 
- } 
-   
- /** Convert string to lower case. */ 
- inline std::string 
- toLowerCase(std::string str) { 
-   for (size_t i = 0; i < str.length(); i++) 
-     str[i] = std::tolower(str[i]); 
-   return str; 
- } 
-   
- inline bool 
- startsWith(const std::string& str, const std::string& startsWith) { 
-     size_t N = startsWith.length(); 
-     if (str.length() < N) 
-         return false; 
-     for (size_t i = 0; i < N; i++) 
-         if (str[i] != startsWith[i]) 
-             return false; 
-     return true; 
- } 
-   
- inline bool 
- endsWith(const std::string& str, const std::string& endsWith) { 
-     size_t N = endsWith.length(); 
-     size_t sN = str.length(); 
-     if (sN < N) 
-         return false; 
-     for (size_t i = 0; i < N; i++) 
-         if (str[sN - N + i] != endsWith[i]) 
-             return false; 
-     return true; 
- } 
-   
- /** Return true if vector v contains element e. */ 
- template <typename T> 
- inline bool 
- contains(const std::vector<T>& v, const T& e) { 
-     return std::find(v.begin(), v.end(), e) != v.end(); 
- } 
-   
- /** Return true if vector v contains element e converted to a string. */ 
- inline bool 
- contains(const std::vector<std::string> v, const char* e) { 
-     return contains(v, std::string(e)); 
- } 
-   
- inline std::string 
- trim(const std::string& s) { 
-     for (int i = 0; i < (int)s.length(); i++) { 
-         if (!isspace(s[i])) { 
-             for (int j = (int)s.length()-1; j >= i; j--) 
-                 if (!isspace(s[j])) 
-                     return s.substr(i, j-i+1); 
-             return ""; 
-         } 
-     } 
-     return ""; 
- } 
-   
- // ---------------------------------------------------------------------------- 
-   
- // A fixed size array that can compute the sum of a range of values in time O(log N) 
- template <int N> 
- class RangeSumArray { 
- public: 
-   
-     /** Get value at index i. */ 
-     int get(size_t i) const { 
-         return arr[i]; 
-     } 
-   
-     /** Add delta to value at index i. */ 
-     void add(size_t i, int delta) { 
-         arr[i] += delta; 
-         pairs.add(i/2, delta); 
-     } 
-   
-     /** Compute sum of all elements in [b,e). */ 
-     int sum(size_t b, size_t e) const { 
-         int result = 0; 
-         sumHelper(b, e, result); 
-         return result; 
-     } 
-   
- private: 
-     template <int N2> friend class RangeSumArray; 
-   
-     void sumHelper(size_t b, size_t e, int& result) const { 
-         if (b >= e) 
-             return; 
-         if (b & 1) { 
-             result += arr[b]; 
-             b++; 
-         } 
-         if (e & 1) { 
-             if (e != N) 
-                 result -= arr[e]; 
-             e++; 
-         } 
-         pairs.sumHelper(b/2, e/2, result); 
-     } 
-   
-     std::array<std::atomic<int>, N> arr {}; 
-     RangeSumArray<(N+1)/2> pairs; 
- }; 
-   
- template<> 
- class RangeSumArray<1> { 
- public: 
-     int get(size_t i) const { 
-         return value; 
-     } 
-   
-     void add(size_t i, int delta) { 
-         value += delta; 
-     } 
-   
-     int sum(size_t b, size_t e) const { 
-         int result = 0; 
-         sumHelper(b, e, result); 
-         return result; 
-     } 
-   
- private: 
-     template <int N2> friend class RangeSumArray; 
-   
-     void sumHelper(size_t b, size_t e, int& result) const { 
-         if (b < e) 
-             result += value; 
-     } 
-   
-     std::atomic<int> value { 0 }; 
- }; 
-   
- // ---------------------------------------------------------------------------- 
-   
- /** Helper class for shared data where read/write accesses do not have to be sequentially ordered. 
-  * This typically generates code as efficient as using a plain T. However using a plain T in this 
-  * context would invoke undefined behavior, see section 1.10.21 in the C++11 standard. */ 
- template <typename T> 
- class RelaxedShared { 
- public: 
-     RelaxedShared<T>() { } 
-     RelaxedShared<T>(T value) { set(value); } 
-     RelaxedShared<T>(const RelaxedShared<T>& r) { set(r.get()); } 
-     RelaxedShared<T>& operator=(const RelaxedShared<T>& r) { set(r.get()); return *this; } 
-     RelaxedShared<T>& operator=(const T& t) { set(t); return *this; } 
-     operator T() const { return get(); } 
-     T get() const { return data.load(std::memory_order_relaxed); } 
-     void set(T value) { data.store(value, std::memory_order_relaxed); } 
- private: 
-     std::atomic<T> data; 
- }; 
-   
- #endif /* UTIL_HPP_ */ 
-