1#ifndef SIMPLEHASHSET_HH
2#define SIMPLEHASHSET_HH
38template<
typename Value, Value Inval
idValue,
typename Hasher,
typename Equality>
43 : hasher(hasher_), equality(equality_)
60 grow(std::bit_ceil(2 * n));
65 return (mask + 1) / 2;
68 [[nodiscard]]
size_t size()
const
72 [[nodiscard]]
bool empty()
const
77 template<
typename Value2>
80 auto h = hash(val) & mask;
82 while (table[h] != InvalidValue) {
83 if (equal(table[h], val)) {
91 table[h] = std::forward<Value2>(val);
93 growAndInsert(std::forward<Value2>(val));
99 template<
typename Value2>
102 auto pos1 = locate(val);
103 if (pos1 ==
size_t(-1))
return false;
106 auto mustMove = [&](
size_t p1,
size_t p2,
size_t p3) {
107 p2 = (p2 - p1 - 1) & mask;
108 p3 = (
p3 - p1 - 1) & mask;
113 pos2 = (pos2 + 1) & mask;
114 if (table[pos2] == InvalidValue) {
116 table[pos1] = InvalidValue;
122 auto pos3 = hash(table[pos2] & mask);
123 if (mustMove(pos1, pos2, pos3)) {
127 table[pos1] = std::move(table[pos2]);
133 template<
typename Value2>
134 [[nodiscard]] Value*
find(
const Value2& val)
const
136 auto h = locate(val);
137 return (h ==
size_t(-1)) ? nullptr : &table[h];
140 template<
typename Value2>
141 [[nodiscard]]
bool contains(
const Value2& val)
const
143 return locate(val) != size_t(-1);
147 template<
typename Value2>
148 [[nodiscard]]
size_t hash(
const Value2& val)
const
153 template<
typename Value2>
154 [[nodiscard]]
bool equal(
const Value& val,
const Value2& val2)
const
156 return equality(val, val2);
159 template<
typename Value2>
160 [[nodiscard]]
size_t locate(
const Value2& val)
const
163 auto h = hash(val) & mask;
164 while (table[h] != InvalidValue) {
165 if (equal(table[h], val)) {
175 template<
typename Value2>
176 void insertValue(Value2&& val, Value* tab,
size_t msk)
178 auto h = hash(val) & msk;
179 while (tab[h] != InvalidValue) {
182 tab[h] = std::forward<Value2>(val);
185 void grow(
size_t newSize)
187 assert(std::has_single_bit(newSize));
188 assert(newSize > (mask + 1));
190 auto* newTable =
static_cast<Value*
>(malloc(newSize *
sizeof(Value)));
191 std::uninitialized_fill(newTable, newTable + newSize, InvalidValue);
193 size_t newMask = newSize - 1;
195 for (
size_t i = 0; i <= mask; ++i) {
196 if (table[i] != InvalidValue) {
197 insertValue(std::move(table[i]), newTable, newMask);
204 mask =
static_cast<decltype(mask)
>(newMask);
207 template<
typename Value2>
208 void growAndInsert(Value2&& val)
210 grow(std::max<size_t>(4, 2 * (mask + 1)));
211 insertValue(std::forward<Value2>(val), table, mask);
216 if (!std::is_trivially_destructible_v<Value> && table) {
217 for (
size_t i = 0; i <= mask; ++i) {
225 [[no_unique_address]] Hasher hasher;
226 [[no_unique_address]] Equality equality;
227 Value* table =
nullptr;
229 uint32_t num_elems = 0;
bool contains(const Value2 &val) const
SimpleHashSet & operator=(const SimpleHashSet &)=delete
SimpleHashSet & operator=(SimpleHashSet &&)=delete
bool insert(Value2 &&val)
Value * find(const Value2 &val) const
bool erase(const Value2 &val)
SimpleHashSet(Hasher hasher_={}, Equality equality_={})
SimpleHashSet(const SimpleHashSet &)=delete
SimpleHashSet(SimpleHashSet &&)=delete
mat3 p3(vec3(1, 2, 3), vec3(4, 5, 6), vec3(7, 0, 9))