| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // -*- mode: C++ -*- | |
| // | |
| // Copyright 2022 Google LLC | |
| // | |
| // Licensed under the Apache License v2.0 with LLVM Exceptions (the | |
| // "License"); you may not use this file except in compliance with the | |
| // License. You may obtain a copy of the License at | |
| // | |
| // https://llvm.org/LICENSE.txt | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // | |
| // Author: Giuliano Procida | |
| // Author: Siddharth Nayyar | |
| #ifndef STG_HASHING_H_ | |
| #define STG_HASHING_H_ | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <functional> | |
| #include <string> | |
| #include <string_view> | |
| namespace stg { | |
| struct HashValue { | |
| constexpr explicit HashValue(uint32_t value) : value(value) {} | |
| auto operator<=>(const HashValue&) const = default; | |
| uint32_t value; | |
| }; | |
| } // namespace stg | |
| namespace std { | |
| template <> | |
| struct hash<stg::HashValue> { | |
| size_t operator()(const stg::HashValue& hv) const { | |
| // do not overhash | |
| return hv.value; | |
| } | |
| }; | |
| } // namespace std | |
| namespace stg { | |
| struct Hash { | |
| constexpr HashValue operator()(HashValue hash_value) const { | |
| return hash_value; | |
| } | |
| // Hash boolean by converting to int. | |
| constexpr HashValue operator()(bool x) const { | |
| return x ? (*this)(1) : (*this)(0); | |
| } | |
| // Hash unsigned 64 bits by splitting, hashing and combining. | |
| constexpr HashValue operator()(uint64_t x) const { | |
| const uint32_t lo = x; | |
| const uint32_t hi = x >> 32; | |
| return (*this)(lo, hi); | |
| } | |
| // Hash signed 64 bits by casting to unsigned 64 bits. | |
| constexpr HashValue operator()(int64_t x) const { | |
| return (*this)(static_cast<uint64_t>(x)); | |
| } | |
| // See https://github.com/skeeto/hash-prospector. | |
| constexpr HashValue operator()(uint32_t x) const { | |
| x ^= x >> 16; | |
| x *= 0x21f0aaad; | |
| x ^= x >> 15; | |
| x *= 0xd35a2d97; | |
| x ^= x >> 15; | |
| return HashValue(x); | |
| } | |
| // Hash signed 32 bits by casting to unsigned 32 bits. | |
| constexpr HashValue operator()(int32_t x) const { | |
| return (*this)(static_cast<uint32_t>(x)); | |
| } | |
| // Hash 8 bits by zero extending to 32 bits. | |
| constexpr HashValue operator()(char x) const { | |
| return (*this)(static_cast<uint32_t>(static_cast<unsigned char>(x))); | |
| } | |
| // 32-bit FNV-1a. See https://wikipedia.org/wiki/Fowler-Noll-Vo_hash_function. | |
| constexpr HashValue operator()(const std::string_view x) const { | |
| uint32_t h = 0x811c9dc5; | |
| for (auto ch : x) { | |
| h ^= static_cast<unsigned char>(ch); | |
| h *= 0x01000193; | |
| } | |
| return HashValue(h); | |
| } | |
| // Hash std::string by constructing a std::string_view. | |
| HashValue operator()(const std::string& x) const { | |
| return (*this)(std::string_view(x)); | |
| } | |
| // Hash C string by constructing a std::string_view. | |
| constexpr HashValue operator()(const char* x) const { | |
| return (*this)(std::string_view(x)); | |
| } | |
| // Reverse order Boost hash_combine (must be used with good hashes). | |
| template <typename Arg, typename... Args> | |
| constexpr HashValue operator()(Arg arg, Args... args) const { | |
| const uint32_t seed = (*this)(args...).value; | |
| const uint32_t hash = (*this)(arg).value; | |
| return HashValue(seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2))); | |
| } | |
| }; | |
| } // namespace stg | |
| #endif // STG_HASHING_H_ |