1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT license.
3 
4 #pragma once
5 
6 #include "kuku/common.h"
7 #ifdef _MSC_VER
8 #   pragma warning(push)
9 #   pragma warning(disable: 4804)
10 #endif
11 #include "kuku/internal/blake2.h"
12 #ifdef _MSC_VER
13 #   pragma warning(pop)
14 #endif
15 #include <array>
16 #include <cstdint>
17 #include <cstddef>
18 #include <stdexcept>
19 
20 namespace kuku
21 {
22     class HashFunc
23     {
24     public:
HashFunc(item_type seed)25         HashFunc(item_type seed)
26         {
27             if (blake2xb(
28                 random_array_.data(),
29                 random_array_size_ * sizeof(location_type),
30                 seed.data(),
31                 sizeof(seed),
32                 nullptr, 0) != 0)
33             {
34                 throw std::runtime_error("blake2xb failed");
35             }
36         }
37 
operator()38         inline location_type operator ()(item_type item) const noexcept
39         {
40             return
41                 random_array_[0 * block_value_count_ + static_cast<std::size_t>(item[0])] ^
42                 random_array_[1 * block_value_count_ + static_cast<std::size_t>(item[1])] ^
43                 random_array_[2 * block_value_count_ + static_cast<std::size_t>(item[2])] ^
44                 random_array_[3 * block_value_count_ + static_cast<std::size_t>(item[3])] ^
45                 random_array_[4 * block_value_count_ + static_cast<std::size_t>(item[4])] ^
46                 random_array_[5 * block_value_count_ + static_cast<std::size_t>(item[5])] ^
47                 random_array_[6 * block_value_count_ + static_cast<std::size_t>(item[6])] ^
48                 random_array_[7 * block_value_count_ + static_cast<std::size_t>(item[7])] ^
49                 random_array_[8 * block_value_count_ + static_cast<std::size_t>(item[8])] ^
50                 random_array_[9 * block_value_count_ + static_cast<std::size_t>(item[9])] ^
51                 random_array_[10 * block_value_count_ + static_cast<std::size_t>(item[10])] ^
52                 random_array_[11 * block_value_count_ + static_cast<std::size_t>(item[11])] ^
53                 random_array_[12 * block_value_count_ + static_cast<std::size_t>(item[12])] ^
54                 random_array_[13 * block_value_count_ + static_cast<std::size_t>(item[13])] ^
55                 random_array_[14 * block_value_count_ + static_cast<std::size_t>(item[14])] ^
56                 random_array_[15 * block_value_count_ + static_cast<std::size_t>(item[15])];
57         }
58 
59     private:
60         static constexpr std::size_t block_size_ = 1;
61 
62         static constexpr std::size_t block_count_ = sizeof(item_type);
63 
64         static constexpr std::size_t block_value_count_ = (std::size_t(1) << (8 * block_size_));
65 
66         static constexpr std::size_t random_array_size_ = block_value_count_ * block_count_;
67 
68         static constexpr std::uint32_t block_mask_ =
69             static_cast<std::uint32_t>(block_value_count_ - 1);
70 
71         std::array<location_type, random_array_size_> random_array_;
72     };
73 }
74