xref: /aosp_15_r20/external/stg/hashing.h (revision 9e3b08ae94a55201065475453d799e8b1378bea6)
1*9e3b08aeSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2*9e3b08aeSAndroid Build Coastguard Worker // -*- mode: C++ -*-
3*9e3b08aeSAndroid Build Coastguard Worker //
4*9e3b08aeSAndroid Build Coastguard Worker // Copyright 2022 Google LLC
5*9e3b08aeSAndroid Build Coastguard Worker //
6*9e3b08aeSAndroid Build Coastguard Worker // Licensed under the Apache License v2.0 with LLVM Exceptions (the
7*9e3b08aeSAndroid Build Coastguard Worker // "License"); you may not use this file except in compliance with the
8*9e3b08aeSAndroid Build Coastguard Worker // License.  You may obtain a copy of the License at
9*9e3b08aeSAndroid Build Coastguard Worker //
10*9e3b08aeSAndroid Build Coastguard Worker //     https://llvm.org/LICENSE.txt
11*9e3b08aeSAndroid Build Coastguard Worker //
12*9e3b08aeSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
13*9e3b08aeSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
14*9e3b08aeSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*9e3b08aeSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
16*9e3b08aeSAndroid Build Coastguard Worker // limitations under the License.
17*9e3b08aeSAndroid Build Coastguard Worker //
18*9e3b08aeSAndroid Build Coastguard Worker // Author: Giuliano Procida
19*9e3b08aeSAndroid Build Coastguard Worker // Author: Siddharth Nayyar
20*9e3b08aeSAndroid Build Coastguard Worker 
21*9e3b08aeSAndroid Build Coastguard Worker #ifndef STG_HASHING_H_
22*9e3b08aeSAndroid Build Coastguard Worker #define STG_HASHING_H_
23*9e3b08aeSAndroid Build Coastguard Worker 
24*9e3b08aeSAndroid Build Coastguard Worker #include <cstddef>
25*9e3b08aeSAndroid Build Coastguard Worker #include <cstdint>
26*9e3b08aeSAndroid Build Coastguard Worker #include <functional>
27*9e3b08aeSAndroid Build Coastguard Worker #include <string>
28*9e3b08aeSAndroid Build Coastguard Worker #include <string_view>
29*9e3b08aeSAndroid Build Coastguard Worker 
30*9e3b08aeSAndroid Build Coastguard Worker namespace stg {
31*9e3b08aeSAndroid Build Coastguard Worker 
32*9e3b08aeSAndroid Build Coastguard Worker struct HashValue {
HashValueHashValue33*9e3b08aeSAndroid Build Coastguard Worker   constexpr explicit HashValue(uint32_t value) : value(value) {}
34*9e3b08aeSAndroid Build Coastguard Worker   auto operator<=>(const HashValue&) const = default;
35*9e3b08aeSAndroid Build Coastguard Worker   uint32_t value;
36*9e3b08aeSAndroid Build Coastguard Worker };
37*9e3b08aeSAndroid Build Coastguard Worker 
38*9e3b08aeSAndroid Build Coastguard Worker }  // namespace stg
39*9e3b08aeSAndroid Build Coastguard Worker 
40*9e3b08aeSAndroid Build Coastguard Worker namespace std {
41*9e3b08aeSAndroid Build Coastguard Worker 
42*9e3b08aeSAndroid Build Coastguard Worker template <>
43*9e3b08aeSAndroid Build Coastguard Worker struct hash<stg::HashValue> {
44*9e3b08aeSAndroid Build Coastguard Worker   size_t operator()(const stg::HashValue& hv) const {
45*9e3b08aeSAndroid Build Coastguard Worker     // do not overhash
46*9e3b08aeSAndroid Build Coastguard Worker     return hv.value;
47*9e3b08aeSAndroid Build Coastguard Worker   }
48*9e3b08aeSAndroid Build Coastguard Worker };
49*9e3b08aeSAndroid Build Coastguard Worker 
50*9e3b08aeSAndroid Build Coastguard Worker }  // namespace std
51*9e3b08aeSAndroid Build Coastguard Worker 
52*9e3b08aeSAndroid Build Coastguard Worker namespace stg {
53*9e3b08aeSAndroid Build Coastguard Worker 
54*9e3b08aeSAndroid Build Coastguard Worker struct Hash {
55*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(HashValue hash_value) const {
56*9e3b08aeSAndroid Build Coastguard Worker     return hash_value;
57*9e3b08aeSAndroid Build Coastguard Worker   }
58*9e3b08aeSAndroid Build Coastguard Worker 
59*9e3b08aeSAndroid Build Coastguard Worker   // Hash boolean by converting to int.
60*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(bool x) const {
61*9e3b08aeSAndroid Build Coastguard Worker     return x ? (*this)(1) : (*this)(0);
62*9e3b08aeSAndroid Build Coastguard Worker   }
63*9e3b08aeSAndroid Build Coastguard Worker 
64*9e3b08aeSAndroid Build Coastguard Worker   // Hash unsigned 64 bits by splitting, hashing and combining.
65*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(uint64_t x) const {
66*9e3b08aeSAndroid Build Coastguard Worker     const uint32_t lo = x;
67*9e3b08aeSAndroid Build Coastguard Worker     const uint32_t hi = x >> 32;
68*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(lo, hi);
69*9e3b08aeSAndroid Build Coastguard Worker   }
70*9e3b08aeSAndroid Build Coastguard Worker 
71*9e3b08aeSAndroid Build Coastguard Worker   // Hash signed 64 bits by casting to unsigned 64 bits.
72*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(int64_t x) const {
73*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(static_cast<uint64_t>(x));
74*9e3b08aeSAndroid Build Coastguard Worker   }
75*9e3b08aeSAndroid Build Coastguard Worker 
76*9e3b08aeSAndroid Build Coastguard Worker   // See https://github.com/skeeto/hash-prospector.
77*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(uint32_t x) const {
78*9e3b08aeSAndroid Build Coastguard Worker     x ^= x >> 16;
79*9e3b08aeSAndroid Build Coastguard Worker     x *= 0x21f0aaad;
80*9e3b08aeSAndroid Build Coastguard Worker     x ^= x >> 15;
81*9e3b08aeSAndroid Build Coastguard Worker     x *= 0xd35a2d97;
82*9e3b08aeSAndroid Build Coastguard Worker     x ^= x >> 15;
83*9e3b08aeSAndroid Build Coastguard Worker     return HashValue(x);
84*9e3b08aeSAndroid Build Coastguard Worker   }
85*9e3b08aeSAndroid Build Coastguard Worker 
86*9e3b08aeSAndroid Build Coastguard Worker   // Hash signed 32 bits by casting to unsigned 32 bits.
87*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(int32_t x) const {
88*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(static_cast<uint32_t>(x));
89*9e3b08aeSAndroid Build Coastguard Worker   }
90*9e3b08aeSAndroid Build Coastguard Worker 
91*9e3b08aeSAndroid Build Coastguard Worker   // Hash 8 bits by zero extending to 32 bits.
92*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(char x) const {
93*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(static_cast<uint32_t>(static_cast<unsigned char>(x)));
94*9e3b08aeSAndroid Build Coastguard Worker   }
95*9e3b08aeSAndroid Build Coastguard Worker 
96*9e3b08aeSAndroid Build Coastguard Worker   // 32-bit FNV-1a. See https://wikipedia.org/wiki/Fowler-Noll-Vo_hash_function.
97*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(const std::string_view x) const {
98*9e3b08aeSAndroid Build Coastguard Worker     uint32_t h = 0x811c9dc5;
99*9e3b08aeSAndroid Build Coastguard Worker     for (auto ch : x) {
100*9e3b08aeSAndroid Build Coastguard Worker       h ^= static_cast<unsigned char>(ch);
101*9e3b08aeSAndroid Build Coastguard Worker       h *= 0x01000193;
102*9e3b08aeSAndroid Build Coastguard Worker     }
103*9e3b08aeSAndroid Build Coastguard Worker     return HashValue(h);
104*9e3b08aeSAndroid Build Coastguard Worker   }
105*9e3b08aeSAndroid Build Coastguard Worker 
106*9e3b08aeSAndroid Build Coastguard Worker   // Hash std::string by constructing a std::string_view.
107*9e3b08aeSAndroid Build Coastguard Worker   HashValue operator()(const std::string& x) const {
108*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(std::string_view(x));
109*9e3b08aeSAndroid Build Coastguard Worker   }
110*9e3b08aeSAndroid Build Coastguard Worker 
111*9e3b08aeSAndroid Build Coastguard Worker   // Hash C string by constructing a std::string_view.
112*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(const char* x) const {
113*9e3b08aeSAndroid Build Coastguard Worker     return (*this)(std::string_view(x));
114*9e3b08aeSAndroid Build Coastguard Worker   }
115*9e3b08aeSAndroid Build Coastguard Worker 
116*9e3b08aeSAndroid Build Coastguard Worker   // Reverse order Boost hash_combine (must be used with good hashes).
117*9e3b08aeSAndroid Build Coastguard Worker   template <typename Arg, typename... Args>
118*9e3b08aeSAndroid Build Coastguard Worker   constexpr HashValue operator()(Arg arg, Args... args) const {
119*9e3b08aeSAndroid Build Coastguard Worker     const uint32_t seed = (*this)(args...).value;
120*9e3b08aeSAndroid Build Coastguard Worker     const uint32_t hash = (*this)(arg).value;
121*9e3b08aeSAndroid Build Coastguard Worker     return HashValue(seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)));
122*9e3b08aeSAndroid Build Coastguard Worker   }
123*9e3b08aeSAndroid Build Coastguard Worker };
124*9e3b08aeSAndroid Build Coastguard Worker 
125*9e3b08aeSAndroid Build Coastguard Worker }  // namespace stg
126*9e3b08aeSAndroid Build Coastguard Worker 
127*9e3b08aeSAndroid Build Coastguard Worker #endif  // STG_HASHING_H_
128