Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/jolt_physics/Jolt/Core/HashCombine.h
9906 views
1
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
2
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
3
// SPDX-License-Identifier: MIT
4
5
#pragma once
6
7
JPH_NAMESPACE_BEGIN
8
9
/// Implements the FNV-1a hash algorithm
10
/// @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
11
/// @param inData Data block of bytes
12
/// @param inSize Number of bytes
13
/// @param inSeed Seed of the hash (can be used to pass in the hash of a previous operation, otherwise leave default)
14
/// @return Hash
15
inline uint64 HashBytes(const void *inData, uint inSize, uint64 inSeed = 0xcbf29ce484222325UL)
16
{
17
uint64 hash = inSeed;
18
for (const uint8 *data = reinterpret_cast<const uint8 *>(inData); data < reinterpret_cast<const uint8 *>(inData) + inSize; ++data)
19
{
20
hash ^= uint64(*data);
21
hash *= 0x100000001b3UL;
22
}
23
return hash;
24
}
25
26
/// Calculate the FNV-1a hash of inString.
27
/// @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
28
constexpr uint64 HashString(const char *inString, uint64 inSeed = 0xcbf29ce484222325UL)
29
{
30
uint64 hash = inSeed;
31
for (const char *c = inString; *c != 0; ++c)
32
{
33
hash ^= uint64(*c);
34
hash *= 0x100000001b3UL;
35
}
36
return hash;
37
}
38
39
/// A 64 bit hash function by Thomas Wang, Jan 1997
40
/// See: http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm
41
/// @param inValue Value to hash
42
/// @return Hash
43
inline uint64 Hash64(uint64 inValue)
44
{
45
uint64 hash = inValue;
46
hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1;
47
hash = hash ^ (hash >> 24);
48
hash = (hash + (hash << 3)) + (hash << 8); // hash * 265
49
hash = hash ^ (hash >> 14);
50
hash = (hash + (hash << 2)) + (hash << 4); // hash * 21
51
hash = hash ^ (hash >> 28);
52
hash = hash + (hash << 31);
53
return hash;
54
}
55
56
/// Fallback hash function that calls T::GetHash()
57
template <class T>
58
struct Hash
59
{
60
uint64 operator () (const T &inValue) const
61
{
62
return inValue.GetHash();
63
}
64
};
65
66
/// A hash function for floats
67
template <>
68
struct Hash<float>
69
{
70
uint64 operator () (float inValue) const
71
{
72
float value = inValue == 0.0f? 0.0f : inValue; // Convert -0.0f to 0.0f
73
return HashBytes(&value, sizeof(value));
74
}
75
};
76
77
/// A hash function for doubles
78
template <>
79
struct Hash<double>
80
{
81
uint64 operator () (double inValue) const
82
{
83
double value = inValue == 0.0? 0.0 : inValue; // Convert -0.0 to 0.0
84
return HashBytes(&value, sizeof(value));
85
}
86
};
87
88
/// A hash function for character pointers
89
template <>
90
struct Hash<const char *>
91
{
92
uint64 operator () (const char *inValue) const
93
{
94
return HashString(inValue);
95
}
96
};
97
98
/// A hash function for std::string_view
99
template <>
100
struct Hash<std::string_view>
101
{
102
uint64 operator () (const std::string_view &inValue) const
103
{
104
return HashBytes(inValue.data(), uint(inValue.size()));
105
}
106
};
107
108
/// A hash function for String
109
template <>
110
struct Hash<String>
111
{
112
uint64 operator () (const String &inValue) const
113
{
114
return HashBytes(inValue.data(), uint(inValue.size()));
115
}
116
};
117
118
/// A fallback function for generic pointers
119
template <class T>
120
struct Hash<T *>
121
{
122
uint64 operator () (T *inValue) const
123
{
124
return HashBytes(&inValue, sizeof(inValue));
125
}
126
};
127
128
/// Helper macro to define a hash function for trivial types
129
#define JPH_DEFINE_TRIVIAL_HASH(type) \
130
template <> \
131
struct Hash<type> \
132
{ \
133
uint64 operator () (const type &inValue) const \
134
{ \
135
return HashBytes(&inValue, sizeof(inValue)); \
136
} \
137
};
138
139
/// Commonly used types
140
JPH_DEFINE_TRIVIAL_HASH(char)
141
JPH_DEFINE_TRIVIAL_HASH(int)
142
JPH_DEFINE_TRIVIAL_HASH(uint32)
143
JPH_DEFINE_TRIVIAL_HASH(uint64)
144
145
/// Helper function that hashes a single value into ioSeed
146
/// Based on https://github.com/jonmaiga/mx3 by Jon Maiga
147
template <typename T>
148
inline void HashCombine(uint64 &ioSeed, const T &inValue)
149
{
150
constexpr uint64 c = 0xbea225f9eb34556dUL;
151
152
uint64 h = ioSeed;
153
uint64 x = Hash<T> { } (inValue);
154
155
// See: https://github.com/jonmaiga/mx3/blob/master/mx3.h
156
// mix_stream(h, x)
157
x *= c;
158
x ^= x >> 39;
159
h += x * c;
160
h *= c;
161
162
// mix(h)
163
h ^= h >> 32;
164
h *= c;
165
h ^= h >> 29;
166
h *= c;
167
h ^= h >> 32;
168
h *= c;
169
h ^= h >> 29;
170
171
ioSeed = h;
172
}
173
174
/// Hash combiner to use a custom struct in an unordered map or set
175
///
176
/// Usage:
177
///
178
/// struct SomeHashKey
179
/// {
180
/// std::string key1;
181
/// std::string key2;
182
/// bool key3;
183
/// };
184
///
185
/// JPH_MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3)
186
template <typename FirstValue, typename... Values>
187
inline uint64 HashCombineArgs(const FirstValue &inFirstValue, Values... inValues)
188
{
189
// Prime the seed by hashing the first value
190
uint64 seed = Hash<FirstValue> { } (inFirstValue);
191
192
// Hash all remaining values together using a fold expression
193
(HashCombine(seed, inValues), ...);
194
195
return seed;
196
}
197
198
#define JPH_MAKE_HASH_STRUCT(type, name, ...) \
199
struct [[nodiscard]] name \
200
{ \
201
::JPH::uint64 operator()(const type &t) const \
202
{ \
203
return ::JPH::HashCombineArgs(__VA_ARGS__); \
204
} \
205
};
206
207
#define JPH_MAKE_STD_HASH(type) \
208
JPH_SUPPRESS_WARNING_PUSH \
209
JPH_SUPPRESS_WARNINGS \
210
namespace std \
211
{ \
212
template<> \
213
struct [[nodiscard]] hash<type> \
214
{ \
215
size_t operator()(const type &t) const \
216
{ \
217
return size_t(::JPH::Hash<type>{ }(t)); \
218
} \
219
}; \
220
} \
221
JPH_SUPPRESS_WARNING_POP
222
223
#define JPH_MAKE_HASHABLE(type, ...) \
224
JPH_SUPPRESS_WARNING_PUSH \
225
JPH_SUPPRESS_WARNINGS \
226
namespace JPH \
227
{ \
228
template<> \
229
JPH_MAKE_HASH_STRUCT(type, Hash<type>, __VA_ARGS__) \
230
} \
231
JPH_SUPPRESS_WARNING_POP \
232
JPH_MAKE_STD_HASH(type)
233
234
JPH_NAMESPACE_END
235
236