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