A library for working with phylogenetic and population genetic data.
v0.32.0
std.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CORE_STD_H_
2 #define GENESIS_UTILS_CORE_STD_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2024 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
34 #include <cstdint>
35 #include <memory>
36 #include <stdexcept>
37 #include <string>
38 
39 namespace genesis {
40 namespace utils {
41 
42 // =================================================================================================
43 // Expection Handling
44 // =================================================================================================
45 
46 // Try to find a macro that expands to the current function name.
47 #ifdef __cplusplus
48 # define GENESIS_FUNC __PRETTY_FUNCTION__
49 #else
50 # if defined __STDC_VERSION__
51 # define GENESIS_FUNC __func__
52 # else
53 # define GENESIS_FUNC __FUNCTION__
54 // # define GENESIS_FUNC ((const char *) 0)
55 # endif
56 #endif
57 
58 // =================================================================================================
59 // Compiler Attributes
60 // =================================================================================================
61 
62 // We define them here as specified by later standards.
63 // Using them this way allows us to easily switch them off (by turning them into empty statements).
64 // #define GENESIS_LIKELY [[likely]]
65 // #define GENESIS_UNLIKELY [[unlikely]]
66 #define GENESIS_LIKELY
67 #define GENESIS_UNLIKELY
68 
69 // =================================================================================================
70 // Shortcomings of the C++ 11 STL...
71 // =================================================================================================
72 
81 template<typename T, typename... Args>
82 std::unique_ptr<T> make_unique(Args&&... args)
83 {
84  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
85 }
86 
93 template <typename T>
95 public:
96 
97  explicit ArrowOperatorProxy( T const& v )
98  : t(v)
99  {}
100 
101  T* operator ->() const {
102  return &t;
103  }
104 
105 private:
106 
107  T t;
108 };
109 
110 // =================================================================================================
111 // Hash Helpers
112 // =================================================================================================
113 
114 inline constexpr std::size_t combine_hashes_32( std::size_t h1, std::size_t h2 )
115 {
116  return h1 ^ ( h2 + 0x9e3779b9 + ( h1 << 6 ) + ( h1 >> 2 ));
117 }
118 
119 inline constexpr std::size_t combine_hashes_64( std::size_t h1, std::size_t h2 )
120 {
121  return h1 ^ ( h2 + 0x9e3779b97f4a7c16 + ( h1 << 12 ) + ( h1 >> 4 ));
122 }
123 
127 inline constexpr std::size_t combine_hashes( std::size_t h1, std::size_t h2 )
128 {
129  // We use a run-time check for the size of size_t,
130  // which however most likely is already resolved at compile time.
131  // The inner functions use the golden ratio phi = (1 + sqrt(5))/2 as an irrational number
132  // with random independent bits, by using its inverse and the max size:
133  // 2^64 / phi = 0x9e3779b97f4a7c16 for the 64bit version for example.
134  // Furthermore, shifting is added in order to spread bits around for greater diversity.
135  // This whole approach follows the Boost hash combine functions.
136 
137  static_assert(
138  ( sizeof( std::size_t ) == 4 ) || ( sizeof( std::size_t ) == 8 ),
139  "Need sizeof( std::size_t ) to be 4 or 8 (32bit or 64bit integer)"
140  );
141  return ( sizeof( std::size_t ) == 4 )
142  ? combine_hashes_32( h1, h2 )
143  : combine_hashes_64( h1, h2 )
144  ;
145 
146  // constexpr in C++11 cannot have multiple return values
147  // if( sizeof( std::size_t ) == 4 ) {
148  // return combine_hashes_32( seed, value );
149  // } else if( sizeof( std::size_t ) == 8 ) {
150  // return combine_hashes_64( seed, value );
151  // } else {
152  // throw std::runtime_error( "Invalid std::size_t size." );
153  // }
154 }
155 
159 template <typename T>
160 inline constexpr std::size_t hash_combine( std::size_t seed, T const& value )
161 {
162  return combine_hashes( seed, std::hash<T>()( value ));
163 }
164 
165 } // namespace utils
166 } // namespace genesis
167 
168 #endif // include guard
genesis::utils::combine_hashes
constexpr std::size_t combine_hashes(std::size_t h1, std::size_t h2)
Combine two hash values.
Definition: std.hpp:127
genesis::utils::ArrowOperatorProxy::ArrowOperatorProxy
ArrowOperatorProxy(T const &v)
Definition: std.hpp:97
genesis::utils::ArrowOperatorProxy
Proxy class to hold an element accessible via arrow operator.
Definition: std.hpp:94
genesis::utils::combine_hashes_32
constexpr std::size_t combine_hashes_32(std::size_t h1, std::size_t h2)
Definition: std.hpp:114
genesis::utils::ArrowOperatorProxy::operator->
T * operator->() const
Definition: std.hpp:101
genesis::utils::combine_hashes_64
constexpr std::size_t combine_hashes_64(std::size_t h1, std::size_t h2)
Definition: std.hpp:119
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::make_unique
std::unique_ptr< T > make_unique(Args &&... args)
Returns a std::unique_ptr for a given type.
Definition: std.hpp:82
genesis::utils::hash_combine
constexpr std::size_t hash_combine(std::size_t seed, T const &value)
Combine a seed value (e.g., another hash) with the hash of a given type.
Definition: std.hpp:160