Line data Source code
1 : // SPDX-FileCopyrightText: 2024 PairInteraction Developers 2 : // SPDX-License-Identifier: LGPL-3.0-or-later 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <complex> 8 : #include <functional> 9 : #include <vector> 10 : 11 : namespace pairinteraction::utils { 12 : 13 : /** 14 : * @struct hash 15 : * 16 : * @brief Hash function 17 : * 18 : * The `std::hash` template allows specialization but only for types that are 19 : * not in the standard library. This means that we cannot specialize 20 : * `std::hash` for, e.g. `std::array`. To this end we define a struct `hash` 21 : * which just inherits from `std::hash` by default. 22 : * 23 : * @tparam T type to be hashed 24 : */ 25 : 26 : template <typename T> 27 : struct hash; 28 : 29 : /** 30 : * @function hash_combine 31 : * 32 : * @brief Combine hashes 33 : * 34 : * The implementation of `hash_combine` is copied from Boost but simplified. 35 : * 36 : * @param seed start hash 37 : * @param v value whose hash is to be added to \p seed 38 : * 39 : * @tparam T type to be hashed 40 : */ 41 : 42 : template <typename T> 43 34928844 : inline void hash_combine(std::size_t &seed, T const &v) { 44 : hash<T> hasher; 45 34928844 : seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 46 34964296 : } 47 : 48 : /** 49 : * @function hash_range 50 : * 51 : * @brief Combine hashes of values in a range 52 : * 53 : * @param first forward iterator 54 : * @param last forward iterator 55 : * 56 : * @return combined hash 57 : * 58 : * @tparam It forward iterator 59 : */ 60 : 61 : template <typename It> 62 17683541 : inline std::size_t hash_range(It first, It last) { 63 17683541 : std::size_t seed = 0; 64 52335894 : for (; first != last; ++first) { 65 34058727 : hash_combine(seed, *first); 66 : } 67 18170885 : return seed; 68 : } 69 : 70 : // By default use std::hash 71 : template <typename T> 72 : struct hash : std::hash<T> {}; 73 : 74 : // Specializations for other types 75 : template <typename T, std::size_t N> 76 : struct hash<std::array<T, N>> { 77 65348 : std::size_t operator()(std::array<T, N> const &a) const { 78 65348 : return hash_range(a.begin(), a.end()); 79 : } 80 : }; 81 : 82 : template <typename T> 83 : struct hash<std::vector<T>> { 84 17631959 : std::size_t operator()(std::vector<T> const &v) const { return hash_range(v.begin(), v.end()); } 85 : }; 86 : 87 : template <typename T> 88 : struct hash<std::complex<T>> { 89 : std::size_t operator()(std::complex<T> const &c) const { 90 : std::size_t seed = 0; 91 : hash_combine(seed, c.real()); 92 : hash_combine(seed, c.imag()); 93 : return seed; 94 : } 95 : }; 96 : 97 : enum class Parity : int; 98 : 99 : template <> 100 : struct hash<Parity> { 101 : std::size_t operator()(const Parity &parity) const { 102 : return std::hash<char>{}(static_cast<char>(parity)); 103 : } 104 : }; 105 : 106 : } // namespace pairinteraction::utils