22 #include <unordered_map> 23 #include <unordered_set> 33 const char* s1 =
"hello, world!";
34 const uint32_t s1_res = 3605494790UL;
38 const char* s2 =
"monkeys! m0nk3yz! ev3ry \\/\\/here~~~~";
39 const uint32_t s2_res = 1270448334UL;
44 const uint32_t s3_res = 2166136261UL;
48 const uint8_t s4_data[] = {0xFF, 0xFF, 0xFF, 0x00};
49 const char* s4 =
reinterpret_cast<const char*
>(s4_data);
50 const uint32_t s4_res = 2420936562UL;
56 const char* s1 =
"hello, world!";
57 const uint64_t s1_res = 13991426986746681734ULL;
61 const char* s2 =
"monkeys! m0nk3yz! ev3ry \\/\\/here~~~~";
62 const uint64_t s2_res = 6091394665637302478ULL;
67 const uint64_t s3_res = 14695981039346656037ULL;
71 const uint8_t s4_data[] = {0xFF, 0xFF, 0xFF, 0x00};
72 const char* s4 =
reinterpret_cast<const char*
>(s4_data);
73 const uint64_t s4_res = 2787597222566293202ULL;
79 const char* t4_a =
"E Pluribus";
80 int64_t t4_b = 0xF1E2D3C4B5A69788;
82 const char* t4_d =
"Unum";
83 uint64_t t4_res = 15571330457339273965ULL;
100 const char* s1 =
"hello, world!";
101 const uint32_t s1_res = 2918802987ul;
105 const char* s2 =
"monkeys! m0nk3yz! ev3ry \\/\\/here~~~~";
117 uint64_t i1 = 0x78a87873e2d31dafULL;
118 uint64_t i1_res = 3389151152926383528ULL;
122 uint64_t i2 = 0x0123456789abcdefULL;
123 uint64_t i2_res = 3061460455458984563ull;
137 for (
int i = 1;
i < 64;
i++) {
145 uint64_t i1 = 0x78a87873e2d31dafULL;
149 uint64_t i2 = 0x0123456789abcdefULL;
154 TEST(Hash, Jenkins_Rev_Mix32) {
173 TEST(Hash, Jenkins_Rev_Unmix32) {
175 for (
int i = 1;
i < 32;
i++) {
176 checkJenkins((1U <<
i) - 1);
177 checkJenkins(1U <<
i);
178 checkJenkins((1U <<
i) + 1);
184 std::unordered_map<int32_t, int32_t, folly::hasher<int32_t>>
m;
185 m.insert(std::make_pair(4, 5));
191 std::unordered_set<size_t> hashes;
193 hashes.insert(hasher((
char)1));
194 hashes.insert(hasher((
signed char)2));
195 hashes.insert(hasher((
unsigned char)3));
196 hashes.insert(hasher((
short)4));
197 hashes.insert(hasher((
signed short)5));
198 hashes.insert(hasher((
unsigned short)6));
199 hashes.insert(hasher((
int)7));
200 hashes.insert(hasher((
signed int)8));
201 hashes.insert(hasher((
unsigned int)9));
202 hashes.insert(hasher((
long)10));
203 hashes.insert(hasher((
signed long)11));
204 hashes.insert(hasher((
unsigned long)12));
205 hashes.insert(hasher((
long long)13));
206 hashes.insert(hasher((
signed long long)14));
207 hashes.insert(hasher((
unsigned long long)15));
208 hashes.insert(hasher((
int8_t)16));
209 hashes.insert(hasher((
uint8_t)17));
210 hashes.insert(hasher((
int16_t)18));
211 hashes.insert(hasher((
uint16_t)19));
212 hashes.insert(hasher((
int32_t)20));
213 hashes.insert(hasher((
uint32_t)21));
214 hashes.insert(hasher((
int64_t)22));
215 hashes.insert(hasher((
uint64_t)23));
216 hashes.insert(hasher((
size_t)24));
219 #if FOLLY_HAVE_INT128_T 220 hashes.insert(hasher((__int128_t)25));
221 hashes.insert(hasher((__uint128_t)26));
238 struct TestStruct {};
245 return hash<int>()(static_cast<int>(e));
250 struct hash<TestStruct> {
258 thread_local
size_t allocatedMemorySize{0};
263 using Alloc = std::allocator<T>;
268 using reference =
typename Alloc::reference;
269 using const_reference =
typename Alloc::const_reference;
279 TestAlloc(TestAlloc<T2>
const& other)
noexcept : a_(other.a_) {}
282 TestAlloc& operator=(TestAlloc<T2>
const& other)
noexcept {
291 TestAlloc& operator=(TestAlloc<T2>&& other)
noexcept {
296 static size_t getAllocatedMemorySize() {
297 return allocatedMemorySize;
301 allocatedMemorySize = 0;
304 T* allocate(
size_t n) {
305 allocatedMemorySize += n *
sizeof(
T);
306 return a_.allocate(n);
308 void deallocate(
T* p,
size_t n) {
309 allocatedMemorySize -= n *
sizeof(
T);
314 std::allocator<T> a_;
317 friend class TestAlloc;
320 template <
class T1,
class T2>
321 bool operator==(TestAlloc<T1>
const&, TestAlloc<T2>
const&) {
325 template <
class T1,
class T2>
326 bool operator!=(TestAlloc<T1>
const&, TestAlloc<T2>
const&) {
330 template <
class M,
class A>
331 std::vector<size_t> getStats(
size_t iter) {
332 std::vector<size_t> ret;
336 ret.push_back(A::getAllocatedMemorySize());
337 for (
size_t i = 1;
i < iter; ++
i) {
338 m.insert(std::make_pair(
339 folly::to<typename M::key_type>(
i),
typename M::mapped_type{}));
340 ret.push_back(A::getAllocatedMemorySize());
345 template <
typename K,
typename V,
typename H>
346 void testNoCachedHashCode() {
347 using A = TestAlloc<std::pair<const K, V>>;
348 using M = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
A>;
349 using MActual = std::unordered_map<K, V, H, std::equal_to<K>, A>;
350 constexpr
int kIter = 10;
351 auto expected = getStats<M, A>(kIter);
352 auto actual = getStats<MActual, A>(kIter);
353 ASSERT_EQ(expected.size(), actual.size());
354 for (
size_t i = 0;
i < expected.size(); ++
i) {
361 testNoCachedHashCode<bool, char, folly::hasher<bool>>();
362 testNoCachedHashCode<int, char, folly::hasher<int>>();
363 testNoCachedHashCode<double, char, folly::hasher<double>>();
364 testNoCachedHashCode<TestEnum, char, folly::hasher<TestEnum>>();
366 testNoCachedHashCode<bool, std::string, folly::Hash>();
367 testNoCachedHashCode<int, std::string, folly::Hash>();
368 testNoCachedHashCode<double, std::string, folly::Hash>();
369 testNoCachedHashCode<TestEnum, std::string, folly::Hash>();
372 TEST(Hash, integer_conversion) {
378 #if FOLLY_HAVE_INT128_T 379 TEST(Hash, int128_std_hash) {
380 std::unordered_set<__int128> hs;
381 hs.insert(__int128_t{1});
382 hs.insert(__int128_t{2});
385 std::set<unsigned __int128>
s;
386 s.insert(static_cast<unsigned __int128>(1));
387 s.insert(static_cast<unsigned __int128>(2));
399 std::unordered_set<size_t> hashes;
400 hashes.insert(hasher(0.0
f));
401 hashes.insert(hasher(0.1
f));
402 hashes.insert(hasher(0.2));
403 hashes.insert(hasher(0.2
f));
404 hashes.insert(hasher(-0.3));
405 hashes.insert(hasher(-0.3
f));
414 return p.first + p.second;
418 template <
typename T,
typename... Ts>
424 auto a = std::make_pair(1, 2);
425 auto b = std::make_pair(3, 4);
426 auto c = std::make_pair(1, 2);
427 auto d = std::make_pair(2, 1);
464 for (
bool b1 : {
false,
true}) {
465 for (
bool b2 : {
false,
true}) {
466 for (
bool b3 : {
false,
true}) {
467 for (
bool b4 : {
false,
true}) {
468 for (
bool b5 : {
false,
true}) {
469 for (
bool b6 : {
false,
true}) {
470 for (
bool b7 : {
false,
true}) {
471 for (
bool b8 : {
false,
true}) {
472 for (
bool b9 : {
false,
true}) {
473 for (
bool b10 : {
false,
true}) {
475 hash(b1, b2, b3, b4, b5, b6, b7, b8, b9, b10));
490 typedef std::tuple<int64_t, std::string, int32_t> tuple3;
491 tuple3
t(42,
"foo", 1);
493 std::unordered_map<tuple3, std::string>
m;
502 EXPECT_EQ(hash(static_cast<int32_t>(Enum32::Foo)), hash(Enum32::Foo));
503 EXPECT_EQ(hash(static_cast<int32_t>(Enum32::Bar)), hash(Enum32::Bar));
504 EXPECT_NE(hash(Enum32::Foo), hash(Enum32::Bar));
506 std::unordered_map<Enum32, std::string, folly::Hash> m32;
507 m32[Enum32::Foo] =
"foo";
510 enum class Enum64 :
int64_t { Foo, Bar };
511 EXPECT_EQ(hash(static_cast<int64_t>(Enum64::Foo)), hash(Enum64::Foo));
512 EXPECT_EQ(hash(static_cast<int64_t>(Enum64::Bar)), hash(Enum64::Bar));
513 EXPECT_NE(hash(Enum64::Foo), hash(Enum64::Bar));
515 std::unordered_map<Enum64, std::string, folly::Hash> m64;
516 m64[Enum64::Foo] =
"foo";
521 typedef std::pair<int64_t, int32_t> pair2;
524 std::unordered_map<pair2, std::string, folly::Hash>
m;
530 typedef std::tuple<int64_t, int32_t, int32_t> tuple3;
533 std::unordered_map<tuple3, std::string, folly::Hash>
m;
540 size_t hash_vector(
const std::vector<T>&
v) {
546 EXPECT_EQ(hash_vector<int32_t>({1, 2}), hash_vector<int16_t>({1, 2}));
547 EXPECT_NE(hash_vector<int>({2, 1}), hash_vector<int>({1, 2}));
548 EXPECT_EQ(hash_vector<int>({}), hash_vector<float>({}));
558 std::vector<int>
v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
559 std::random_device
rd;
560 std::mt19937
g(
rd());
562 for (
int i = 0;
i < 100;
i++) {
563 std::shuffle(v.begin(), v.end(),
g);
573 EXPECT_EQ(
h,
commutative_hash_combine(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
574 EXPECT_EQ(
h,
commutative_hash_combine(10, 2, 3, 4, 5, 6, 7, 8, 9, 1));
581 TEST(Hash, std_tuple_different_hash) {
582 typedef std::tuple<int64_t, std::string, int32_t> tuple3;
583 tuple3 t1(42,
"foo", 1);
584 tuple3 t2(9,
"bar", 3);
585 tuple3 t3(42,
"foo", 3);
587 EXPECT_NE(std::hash<tuple3>()(t1), std::hash<tuple3>()(t2));
588 EXPECT_NE(std::hash<tuple3>()(t1), std::hash<tuple3>()(t3));
592 using namespace folly;
594 StringPiece a1 =
"10050517", b1 =
"51107032", a2 =
"10050518",
595 b2 =
"51107033", a3 =
"10050519", b3 =
"51107034",
596 a4 =
"10050525", b4 =
"51107040";
598 w3 =
range(L
"10050518"), w4 =
range(L
"51107033");
624 class FNVTest :
public ::testing::TestWithParam<FNVTestParam> {};
628 GetParam().out,
fnva64_buf(GetParam().in.data(), GetParam().in.size()));
636 size_t partialLen = GetParam().in.size() / 2;
637 auto data = GetParam().in.data();
642 data + partialLen, GetParam().in.size() - partialLen,
partial));
656 FNVTestParam{
"http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash",
659 0x07aaa640476e0b9a}));
663 static constexpr
bool k32Bit =
sizeof(std::size_t) == 4;
698 std::hash<std::pair<int, int>>,
699 std::pair<int, int>>::
value,
707 std::hash<std::tuple<std::string>>,
708 std::tuple<std::string>>::
value,
712 std::hash<std::tuple<int, int>>,
713 std::tuple<int, int>>::
value,
717 std::hash<std::tuple<int, int, int>>,
718 std::tuple<int, int, int>>::
value,
809 std::pair<int, int>>::
value,
815 std::tuple<int>>::
value,
820 std::tuple<std::string>>::
value,
825 std::tuple<int, int>>::
value,
830 std::tuple<int, int, int>>::
value,
843 template <
typename H,
typename T,
typename F>
844 void verifyAvalanching(
T initialValue, F
const& advance) {
853 constexpr std::size_t N =
sizeof(decltype(hasher(initialValue))) * 8;
856 bool seen[N][N] = {};
857 std::size_t unseenCount = N * (N - 1);
858 auto v = initialValue;
860 std::size_t
steps = 0;
862 while (unseenCount > (N * (N - 1)) / 95) {
869 for (std::size_t
i = 0;
i < N - 1; ++
i) {
870 if (((delta >>
i) & 1) == 0) {
874 for (std::size_t j =
i + 1; j < N; ++j) {
875 if (((delta >> j) & 1) == 0) {
879 bool iOn = ((hPrev >>
i) & 1) == 0;
880 bool jOn = ((hPrev >> j) & 1) == 0;
882 auto on = iOn ?
i : j;
883 auto off = iOn ? j :
i;
884 if (!seen[
on][off]) {
885 seen[
on][off] =
true;
893 ASSERT_LT(steps, 1000) << unseenCount <<
" of " << (N * (N - 1))
894 <<
" pair transitions unseen";
899 TEST(Traits, stdHashPairAvalances) {
900 verifyAvalanching<std::hash<std::pair<int, int>>>(
901 std::make_pair(0, 0), [](std::pair<int, int>&
v) { v.first++; });
904 TEST(Traits, stdHashTuple2Avalances) {
905 verifyAvalanching<std::hash<std::tuple<int, int>>>(
907 [](std::tuple<int, int>&
v) { std::get<0>(
v) += 1; });
910 TEST(Traits, stdHashStringAvalances) {
911 verifyAvalanching<std::hash<std::string>,
std::string>(
912 "00000000000000000000000000000", [](std::string& str) {
914 while (str[i] ==
'1') {
922 TEST(Traits, follyHashUint64Avalances) {
926 TEST(Traits, follyHasherInt64Avalances) {
927 verifyAvalanching<folly::hasher<int64_t>>(
931 TEST(Traits, follyHasherFloatAvalanches) {
932 verifyAvalanching<folly::hasher<float>>(0.0f, [](
float&
v) { v += 1; });
935 TEST(Traits, follyHasherDoubleAvalanches) {
936 verifyAvalanching<folly::hasher<double>>(0.0, [](
double&
v) { v += 1; });
uint64_t fnv64_buf(const void *buf, size_t n, uint64_t hash=FNV_64_HASH_START) noexcept
Map::mapped_type get_default(const Map &map, const Key &key)
uint32_t jenkins_rev_unmix32(uint32_t key) noexcept
uint64_t commutative_hash_combine_range(Iter first, Iter last)
#define ASSERT_EQ(val1, val2)
size_t hash_combine_test(const T &t, const Ts &...ts)
uint64_t fnva64(const std::string &str, uint64_t hash=FNVA_64_HASH_START) noexcept
uint32_t hsieh_hash32_buf(const void *buf, size_t len) noexcept
#define ASSERT_LT(val1, val2)
uint64_t commutative_hash_combine_range_generic(uint64_t seed, Hash const &hasher, Iter first, Iter last)
#define EXPECT_EQ(val1, val2)
constexpr detail::Map< Move > move
std::allocator< T >::value_type value_type
size_t operator()(const std::pair< int, int > &p) const
—— Concurrent Priority Queue Implementation ——
requires E e noexcept(noexcept(s.error(std::move(e))))
uint32_t twang_32from64(uint64_t key) noexcept
uint32_t jenkins_rev_mix32(uint32_t key) noexcept
uint64_t commutative_hash_combine_value_generic(uint64_t seed, Hash const &hasher, Value const &value)
bool_constant< true > true_type
std::unordered_set< std::pair< const IValidator *, const dynamic * > > seen
uint64_t hash_range(Iter begin, Iter end, uint64_t hash=0, Hash hasher=Hash())
bool operator!=(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
static constexpr bool k32Bit
uint32_t fnv32_buf(const void *buf, size_t n, uint32_t hash=FNV_32_HASH_START) noexcept
uint32_t fnv32(const char *buf, uint32_t hash=FNV_32_HASH_START) noexcept
auto partial(F &&f, Args &&...args) -> detail::partial::Partial< typename std::decay< F >::type, std::tuple< typename std::decay< Args >::type... >>
TEST_P(FNVTest, Fnva64Buf)
size_t hash_combine(const T &t, const Ts &...ts) noexcept(noexcept(hash_combine_generic(StdHasher{}, t, ts...)))
uint64_t fnv64(const char *buf, uint64_t hash=FNV_64_HASH_START) noexcept
constexpr auto data(C &c) -> decltype(c.data())
constexpr Range< Iter > range(Iter first, Iter last)
static map< string, int > m
std::size_t operator()(TestEnum const &e) const noexcept
uint64_t fnva64_buf(const void *buf, size_t n, uint64_t hash=FNVA_64_HASH_START) noexcept
**Optimized Holders **The template hazptr_array< M > provides most of the functionality *of M hazptr_holder s but with faster construction destruction *for M
std::allocator< T >::const_pointer const_pointer
#define EXPECT_TRUE(condition)
uint64_t twang_mix64(uint64_t key) noexcept
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Range< const unsigned char * > ByteRange
size_t hash_combine_generic(const Hasher &) noexcept
::std::vector< string > Strings
#define EXPECT_NE(val1, val2)
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
std::allocator< T >::size_type size_type
INSTANTIATE_TEST_CASE_P(FNVTesting, FNVTest,::testing::Values(FNVTestParam{"foobar", 0x85944171f73967e8}, FNVTestParam{"chongo was here!\n", 0x46810940eff5f915}, FNVTestParam{"127.0.0.3", 0xaabafc7104d91158}, FNVTestParam{"http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash", 0xd9b957fb7fe794c5}, FNVTestParam{"http://norvig.com/21-days.html", 0x07aaa640476e0b9a}))
std::size_t operator()(TestStruct const &) const noexcept
uint32_t hsieh_hash32(const char *s) noexcept
TEST(SequencedExecutor, CPUThreadPoolExecutor)
PUSHMI_INLINE_VAR constexpr detail::on_fn on
uint64_t commutative_hash_combine(Value const &...value)
uint64_t twang_unmix64(uint64_t key) noexcept
std::vector< int > values(1'000)
std::allocator< T >::pointer pointer