LCOV - code coverage report
Current view: top level - pairinteraction - utils.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 26 43 60.5 %
Date: 2024-04-29 00:41:50 Functions: 24 32 75.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Sebastian Weber, Henri Menke. All rights reserved.
       3             :  *
       4             :  * This file is part of the pairinteraction library.
       5             :  *
       6             :  * The pairinteraction library is free software: you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser General Public License as published by
       8             :  * the Free Software Foundation, either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * The pairinteraction library is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public License
      17             :  * along with the pairinteraction library. If not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #ifndef UTILS_H
      21             : #define UTILS_H
      22             : 
      23             : #include <algorithm>
      24             : #include <array>
      25             : #include <complex>
      26             : #include <functional>
      27             : #include <random>
      28             : #include <type_traits>
      29             : 
      30             : #ifdef _WIN32
      31             : #include <Windows.h>
      32             : #else
      33             : #include <unistd.h>
      34             : #endif
      35             : 
      36             : namespace utils {
      37             : 
      38             : template <typename T>
      39             : struct is_complex : std::false_type {};
      40             : template <typename S>
      41             : struct is_complex<std::complex<S>> : std::true_type {};
      42             : 
      43             : template <typename T>
      44           0 : inline T conjugate(const T &val) {
      45           0 :     return val;
      46             : }
      47             : template <typename S>
      48           0 : inline std::complex<S> conjugate(const std::complex<S> &val) {
      49           0 :     return std::conj(val);
      50             : }
      51             : 
      52             : template <typename T>
      53         169 : inline bool is_true(const T &val) {
      54         338 :     return std::all_of(val.begin(), val.end(), [](bool i) { return i; });
      55             : }
      56         125 : inline bool is_true(bool val) { return val; }
      57             : 
      58             : template <typename T>
      59           0 : inline typename std::enable_if<!is_complex<T>::value, T>::type imaginary_unit() {
      60           0 :     throw std::runtime_error(
      61             :         "For operations that invoke the imaginary number, a complex data type is needed.");
      62             : }
      63             : template <typename T>
      64          28 : inline typename std::enable_if<is_complex<T>::value, T>::type imaginary_unit() {
      65          28 :     return {0, 1};
      66             : }
      67             : 
      68             : template <typename T, typename U>
      69        4380 : inline T convert(const U &val) {
      70        4380 :     return val;
      71             : }
      72             : template <typename S>
      73         152 : inline S convert(const std::complex<S> &val) {
      74         152 :     return std::real(val);
      75             : }
      76             : 
      77             : /** \brief Thread-local static random engine
      78             :  *
      79             :  * To save some effort this function initializes a static thread-local
      80             :  * random engine to avoid race conditions and broken random sampling.
      81             :  * It is seeded once using `std::random_device` for good entropy.
      82             :  *
      83             :  * \returns Reference to static thread-local random engine
      84             :  */
      85           1 : inline std::default_random_engine &randint_engine() {
      86           1 :     static thread_local std::default_random_engine eng{std::random_device{}()};
      87           1 :     return eng;
      88             : }
      89             : 
      90             : /** \brief Generate a random integer
      91             :  *
      92             :  * This is very similar to the implementation of randint in the GCC
      93             :  * standard library Fundamentals TS v2.  It is specified by the
      94             :  * standard per clause 13.2.2.1, Function template randint.
      95             :  *
      96             :  * The function generates a random integer in the closed interval
      97             :  * [\p a,\p b].
      98             :  *
      99             :  * \param a  lower bound
     100             :  * \param b  upper bound
     101             :  * \returns random integer between \p a and \p b.
     102             :  */
     103             : template <typename T>
     104           1 : inline T randint(T a, T b) {
     105             :     static_assert(std::is_integral<T>::value && sizeof(T) > 1, "The type must be an integer!");
     106           1 :     return std::uniform_int_distribution<T>(a, b)(randint_engine());
     107             : }
     108             : 
     109             : // https://de.wikipedia.org/wiki/FNV_(Informatik)
     110           0 : inline uint64_t FNV64(const uint8_t *s, size_t sz) {
     111           0 :     const uint64_t magicPrime = 0x00000100000001b3;
     112           0 :     uint64_t hash = 0xcbf29ce484222325;
     113             : 
     114           0 :     for (size_t i = 0; i < sz; ++i) {
     115           0 :         hash = (hash ^ s[i]) * magicPrime;
     116             :     }
     117           0 :     return hash;
     118             : }
     119             : 
     120         308 : inline long get_pid() {
     121             : #ifdef _WIN32
     122             :     return GetCurrentProcessId();
     123             : #else
     124         308 :     return ::getpid();
     125             : #endif
     126             : }
     127             : 
     128             : /// \brief Hash function
     129             : ///
     130             : /// The `std::hash` template allows specialization but only for types that are
     131             : /// not in the standard library.  This means that we cannot specialize
     132             : /// `std::hash` for, e.g. `std::array`.  To this end we define a struct `hash`
     133             : /// which just inherits from `std::hash` by default.
     134             : ///
     135             : /// \tparam Key  type to be hashed
     136             : template <typename Key>
     137             : struct hash;
     138             : 
     139             : /// \brief Combine hashes
     140             : ///
     141             : /// The implementation of `hash_combine` is copied from Boost but simplified.
     142             : /// It uses the custom `hash`.
     143             : ///
     144             : /// \param seed  start hash
     145             : /// \param v  value whose hash is to be added to \p seed
     146             : template <typename T>
     147    26104435 : inline void hash_combine(std::size_t &seed, T const &v) {
     148             :     hash<T> hasher;
     149    26104435 :     seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
     150    26104435 : }
     151             : 
     152             : /// \brief Combine hashes of values in a range
     153             : ///
     154             : /// \param first  forward iterator
     155             : /// \param last  forward iterator
     156             : /// \returns combined hash of all values in the range
     157             : template <typename It>
     158     5106180 : inline std::size_t hash_range(It first, It last) {
     159     5106180 :     std::size_t seed = 0;
     160    15318584 :     for (; first != last; ++first) {
     161    10212404 :         hash_combine(seed, *first);
     162             :     }
     163     5106180 :     return seed;
     164             : }
     165             : 
     166             : // By default use std::hash
     167             : template <typename T>
     168             : struct hash : std::hash<T> {};
     169             : 
     170             : // Specializations for other types
     171             : template <typename T, std::size_t N>
     172             : struct hash<std::array<T, N>> {
     173             :     using argument_type = std::array<T, N>;
     174             :     using result_type = std::size_t;
     175     5106178 :     std::size_t operator()(std::array<T, N> const &a) const {
     176     5106178 :         return hash_range(a.begin(), a.end());
     177             :     }
     178             : };
     179             : 
     180             : template <typename T>
     181             : struct hash<std::complex<T>> {
     182             :     using argument_type = std::complex<T>;
     183             :     using result_type = std::size_t;
     184           0 :     std::size_t operator()(std::complex<T> const &c) const {
     185           0 :         std::size_t seed = 0;
     186           0 :         hash_combine(seed, c.real());
     187           0 :         hash_combine(seed, c.imag());
     188           0 :         return seed;
     189             :     }
     190             : };
     191             : 
     192             : } // namespace utils
     193             : 
     194             : #endif // UTILS_H

Generated by: LCOV version 1.14