Antkeeper  0.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
fnv1a.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef ANTKEEPER_UTILITY_HASH_FNV1A_HPP
21 #define ANTKEEPER_UTILITY_HASH_FNV1A_HPP
22 
23 #include <concepts>
24 #include <cstdint>
25 #include <string_view>
26 #include <utility>
27 #include <span>
28 
29 namespace hash {
30 
45 template <std::unsigned_integral HashT, std::integral DataT>
46 [[nodiscard]] constexpr HashT fnv1a(std::span<const DataT> data, HashT offset, HashT prime) noexcept
47 {
48  for (auto element: data)
49  {
50  if constexpr (sizeof(DataT) == 1)
51  {
52  offset ^= static_cast<HashT>(element);
53  offset *= prime;
54  }
55  else
56  {
58  for (std::size_t j = 0; j < sizeof(DataT); ++j)
59  {
60  offset ^= static_cast<HashT>(((element) >> (j * 8)) & 255);
61  offset *= prime;
62  }
63  }
64  }
65 
66  return offset;
67 }
68 
78 template <std::integral DataT>
79 [[nodiscard]] constexpr std::uint32_t fnv1a32(std::span<const DataT> data) noexcept
80 {
81  // 32-bit FNV offset basis value.
82  constexpr std::uint32_t offset = 2166136261;
83 
84  // 32-bit FNV prime value.
85  constexpr std::uint32_t prime = 16777619;
86 
87  return fnv1a<std::uint32_t, DataT>(data, offset, prime);
88 }
89 
99 template <std::integral DataT>
100 [[nodiscard]] constexpr std::uint64_t fnv1a64(std::span<const DataT> data) noexcept
101 {
102  // 64-bit FNV offset basis value.
103  constexpr std::uint64_t offset = 14695981039346656037ULL;
104 
105  // 64-bit FNV prime value.
106  constexpr std::uint64_t prime = 1099511628211ULL;
107 
108  return fnv1a<std::uint64_t, DataT>(data, offset, prime);
109 }
110 
111 namespace types {
112 
116 struct fnv1a32_t
117 {
119  using value_type = std::uint32_t;
120 
127  inline constexpr explicit(false) fnv1a32_t(value_type value) noexcept:
128  value{value}
129  {}
130  fnv1a32_t() = default;
132 
139  constexpr explicit(false) fnv1a32_t(const char* string) noexcept:
140  value{fnv1a32<char>({string, std::string_view(string).length()})}
141  {}
142  constexpr explicit(false) fnv1a32_t(const wchar_t* string) noexcept:
143  value{fnv1a32<wchar_t>({string, std::wstring_view(string).length()})}
144  {}
145  constexpr explicit(false) fnv1a32_t(const char8_t* string) noexcept:
146  value{fnv1a32<char8_t>({string, std::u8string_view(string).length()})}
147  {}
148  constexpr explicit(false) fnv1a32_t(const char16_t* string) noexcept:
149  value{fnv1a32<char16_t>({string, std::u16string_view(string).length()})}
150  {}
151  constexpr explicit(false) fnv1a32_t(const char32_t* string) noexcept:
152  value{fnv1a32<char32_t>({string, std::u32string_view(string).length()})}
153  {}
155 
161  [[nodiscard]] inline constexpr operator value_type() const noexcept
162  {
163  return value;
164  }
165 
168 };
169 static_assert(sizeof(fnv1a32_t) == sizeof(std::uint32_t));
170 
174 struct fnv1a64_t
175 {
177  using value_type = std::uint64_t;
178 
183  inline constexpr explicit(false) fnv1a64_t(value_type value) noexcept:
184  value{value}
185  {}
186  fnv1a64_t() = default;
188 
195  constexpr explicit(false) fnv1a64_t(const char* string) noexcept:
196  value{fnv1a64<char>({string, std::string_view(string).length()})}
197  {}
198  constexpr explicit(false) fnv1a64_t(const wchar_t* string) noexcept:
199  value{fnv1a64<wchar_t>({string, std::wstring_view(string).length()})}
200  {}
201  constexpr explicit(false) fnv1a64_t(const char8_t* string) noexcept:
202  value{fnv1a64<char8_t>({string, std::u8string_view(string).length()})}
203  {}
204  constexpr explicit(false) fnv1a64_t(const char16_t* string) noexcept:
205  value{fnv1a64<char16_t>({string, std::u16string_view(string).length()})}
206  {}
207  constexpr explicit(false) fnv1a64_t(const char32_t* string) noexcept:
208  value{fnv1a64<char32_t>({string, std::u32string_view(string).length()})}
209  {}
211 
217  [[nodiscard]] inline constexpr operator value_type() const noexcept
218  {
219  return value;
220  }
221 
224 };
225 static_assert(sizeof(fnv1a64_t) == sizeof(std::uint64_t));
226 
227 } // namespace types
228 
229 // Bring hash::types namespace into hash namespace
230 using namespace hash::types;
231 
232 namespace literals {
233 
243 [[nodiscard]] consteval std::uint32_t operator"" _fnv1a32(const char* string, std::size_t length) noexcept
244 {
245  return hash::fnv1a32<char>({string, length});
246 }
247 
248 [[nodiscard]] consteval std::uint32_t operator"" _fnv1a32(const wchar_t* string, std::size_t length) noexcept
249 {
250  return hash::fnv1a32<wchar_t>({string, length});
251 }
252 
253 [[nodiscard]] consteval std::uint32_t operator"" _fnv1a32(const char8_t* string, std::size_t length) noexcept
254 {
255  return hash::fnv1a32<char8_t>({string, length});
256 }
257 
258 [[nodiscard]] consteval std::uint32_t operator"" _fnv1a32(const char16_t* string, std::size_t length) noexcept
259 {
260  return hash::fnv1a32<char16_t>({string, length});
261 }
262 
263 [[nodiscard]] consteval std::uint32_t operator"" _fnv1a32(const char32_t* string, std::size_t length) noexcept
264 {
265  return hash::fnv1a32<char32_t>({string, length});
266 }
268 
278 [[nodiscard]] consteval std::uint64_t operator"" _fnv1a64(const char* string, std::size_t length) noexcept
279 {
280  return hash::fnv1a64<char>({string, length});
281 }
282 
283 [[nodiscard]] consteval std::uint64_t operator"" _fnv1a64(const wchar_t* string, std::size_t length) noexcept
284 {
285  return hash::fnv1a64<wchar_t>({string, length});
286 }
287 
288 [[nodiscard]] consteval std::uint64_t operator"" _fnv1a64(const char8_t* string, std::size_t length) noexcept
289 {
290  return hash::fnv1a64<char8_t>({string, length});
291 }
292 
293 [[nodiscard]] consteval std::uint64_t operator"" _fnv1a64(const char16_t* string, std::size_t length) noexcept
294 {
295  return hash::fnv1a64<char16_t>({string, length});
296 }
297 
298 [[nodiscard]] consteval std::uint64_t operator"" _fnv1a64(const char32_t* string, std::size_t length) noexcept
299 {
300  return hash::fnv1a64<char32_t>({string, length});
301 }
303 
304 } // namespace literals
305 
306 // Bring hash::literals namespace into hash namespace
307 using namespace hash::literals;
308 
309 } // namespace hash
310 
315 [[nodiscard]] inline constexpr bool operator==(const ::hash::fnv1a32_t& lhs, const ::hash::fnv1a32_t& rhs) noexcept
316 {
317  return lhs.value == rhs.value;
318 }
319 [[nodiscard]] inline constexpr bool operator==(const ::hash::fnv1a64_t& lhs, const ::hash::fnv1a64_t& rhs) noexcept
320 {
321  return lhs.value == rhs.value;
322 }
324 
329 [[nodiscard]] inline constexpr bool operator<(const ::hash::fnv1a32_t& lhs, const ::hash::fnv1a32_t& rhs) noexcept
330 {
331  return lhs.value < rhs.value;
332 }
333 [[nodiscard]] inline constexpr bool operator<(const ::hash::fnv1a64_t& lhs, const ::hash::fnv1a64_t& rhs) noexcept
334 {
335  return lhs.value < rhs.value;
336 }
338 
339 namespace std {
340 
341  template <>
343  {
344  [[nodiscard]] inline constexpr std::size_t operator()(const ::hash::fnv1a32_t& hash) const noexcept
345  {
346  return static_cast<std::size_t>(hash.value);
347  }
348  };
349 
350  template <>
352  {
353  [[nodiscard]] inline constexpr std::size_t operator()(const ::hash::fnv1a64_t& hash) const noexcept
354  {
355  return static_cast<std::size_t>(hash.value);
356  }
357  };
358 
359 } // namespace std
360 
361 #endif // ANTKEEPER_UTILITY_HASH_FNV1A_HPP
constexpr bool operator==(const ::hash::fnv1a32_t &lhs, const ::hash::fnv1a32_t &rhs) noexcept
Compares two FNV-1a hash values for equality.
Definition: fnv1a.hpp:315
constexpr bool operator<(const ::hash::fnv1a32_t &lhs, const ::hash::fnv1a32_t &rhs) noexcept
Checks if one FNV-1a hash value is less than another.
Definition: fnv1a.hpp:329
User-defined literals for compile-time string hashing.
Definition: fnv1a.hpp:232
Distinct hash value types for different hash algorithms.
Definition: fnv1a.hpp:111
Hash functions.
Definition: fnv1a.hpp:29
constexpr std::uint32_t fnv1a32(std::span< const DataT > data) noexcept
32-bit FNV-1a hash function.
Definition: fnv1a.hpp:79
constexpr std::uint64_t fnv1a64(std::span< const DataT > data) noexcept
64-bit FNV-1a hash function.
Definition: fnv1a.hpp:100
constexpr HashT fnv1a(std::span< const DataT > data, HashT offset, HashT prime) noexcept
FNV-1a hash function.
Definition: fnv1a.hpp:46
T length(const quaternion< T > &q)
Calculates the length of a quaternion.
Definition: quaternion.hpp:602
T offset(T longitude)
Calculates the UTC offset at a given longitude.
Definition: utc.hpp:38
32-bit FNV-1a hash value.
Definition: fnv1a.hpp:117
fnv1a32_t()=default
Constructs a 32-bit FNV-1a hash value.
value_type value
32-bit FNV-1a hash value.
Definition: fnv1a.hpp:167
std::uint32_t value_type
Hash value type.
Definition: fnv1a.hpp:119
64-bit FNV-1a hash value.
Definition: fnv1a.hpp:175
value_type value
64-bit FNV-1a hash value.
Definition: fnv1a.hpp:223
fnv1a64_t()=default
Constructs a 64-bit FNV-1a hash value.
std::uint64_t value_type
Hash value type.
Definition: fnv1a.hpp:177
constexpr std::size_t operator()(const ::hash::fnv1a32_t &hash) const noexcept
Definition: fnv1a.hpp:344
constexpr std::size_t operator()(const ::hash::fnv1a64_t &hash) const noexcept
Definition: fnv1a.hpp:353