xref: /aosp_15_r20/external/openscreen/util/hashing.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #ifndef UTIL_HASHING_H_
6*3f982cf4SFabien Sanglard #define UTIL_HASHING_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard namespace openscreen {
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard // Computes the aggregate hash of the provided hashable objects.
11*3f982cf4SFabien Sanglard // Seed must initially use a large prime between 2^63 and 2^64 as a starting
12*3f982cf4SFabien Sanglard // value, or the result of a previous call to this function.
13*3f982cf4SFabien Sanglard template <typename... T>
ComputeAggregateHash(uint64_t seed,const T &...objs)14*3f982cf4SFabien Sanglard uint64_t ComputeAggregateHash(uint64_t seed, const T&... objs) {
15*3f982cf4SFabien Sanglard   auto hash_combiner = [](uint64_t seed, uint64_t hash_value) -> uint64_t {
16*3f982cf4SFabien Sanglard     static const uint64_t kMultiplier = UINT64_C(0x9ddfea08eb382d69);
17*3f982cf4SFabien Sanglard     uint64_t a = (hash_value ^ seed) * kMultiplier;
18*3f982cf4SFabien Sanglard     a ^= (a >> 47);
19*3f982cf4SFabien Sanglard     uint64_t b = (seed ^ a) * kMultiplier;
20*3f982cf4SFabien Sanglard     b ^= (b >> 47);
21*3f982cf4SFabien Sanglard     b *= kMultiplier;
22*3f982cf4SFabien Sanglard     return b;
23*3f982cf4SFabien Sanglard   };
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard   uint64_t result = seed;
26*3f982cf4SFabien Sanglard   std::vector<uint64_t> hashes{std::hash<T>()(objs)...};
27*3f982cf4SFabien Sanglard   for (uint64_t hash : hashes) {
28*3f982cf4SFabien Sanglard     result = hash_combiner(result, hash);
29*3f982cf4SFabien Sanglard   }
30*3f982cf4SFabien Sanglard   return result;
31*3f982cf4SFabien Sanglard }
32*3f982cf4SFabien Sanglard 
33*3f982cf4SFabien Sanglard template <typename... T>
ComputeAggregateHash(const T &...objs)34*3f982cf4SFabien Sanglard uint64_t ComputeAggregateHash(const T&... objs) {
35*3f982cf4SFabien Sanglard   // This value is taken from absl::Hash implementation.
36*3f982cf4SFabien Sanglard   constexpr uint64_t default_seed = UINT64_C(0xc3a5c85c97cb3127);
37*3f982cf4SFabien Sanglard   return ComputeAggregateHash(default_seed, objs...);
38*3f982cf4SFabien Sanglard }
39*3f982cf4SFabien Sanglard 
40*3f982cf4SFabien Sanglard struct PairHash {
41*3f982cf4SFabien Sanglard   template <typename TFirst, typename TSecond>
operatorPairHash42*3f982cf4SFabien Sanglard   size_t operator()(const std::pair<TFirst, TSecond>& pair) const {
43*3f982cf4SFabien Sanglard     return ComputeAggregateHash(pair.first, pair.second);
44*3f982cf4SFabien Sanglard   }
45*3f982cf4SFabien Sanglard };
46*3f982cf4SFabien Sanglard 
47*3f982cf4SFabien Sanglard }  // namespace openscreen
48*3f982cf4SFabien Sanglard 
49*3f982cf4SFabien Sanglard #endif  // UTIL_HASHING_H_
50