Blender V5.0
BLI_hash_tables.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
12
13#include <algorithm>
14
15#include "BLI_utildefines.h"
16#include "BLI_vector.hh"
17
18namespace blender {
19
20/* -------------------------------------------------------------------- */
25
26template<typename IntT> constexpr IntT ceil_division(const IntT x, const IntT y)
27{
28 BLI_assert(x >= 0);
29 BLI_assert(y >= 0);
30 return x / y + ((x % y) != 0);
31}
32
33template<typename IntT> constexpr IntT floor_division(const IntT x, const IntT y)
34{
35 BLI_assert(x >= 0);
36 BLI_assert(y >= 0);
37 return x / y;
38}
39
41 const int64_t numerator,
42 const int64_t denominator)
43{
44 return int64_t(ceil_division(uint64_t(x) * uint64_t(denominator), uint64_t(numerator)));
45}
46
48 const int64_t numerator,
49 const int64_t denominator)
50{
51 return int64_t((uint64_t(x) * uint64_t(numerator) / uint64_t(denominator)));
52}
53
54constexpr int64_t total_slot_amount_for_usable_slots(const int64_t min_usable_slots,
55 const int64_t max_load_factor_numerator,
56 const int64_t max_load_factor_denominator)
57{
58 return power_of_2_max(ceil_division_by_fraction(
59 min_usable_slots, max_load_factor_numerator, max_load_factor_denominator));
60}
61
63
64/* -------------------------------------------------------------------- */
71
73 private:
74 uint8_t numerator_;
75 uint8_t denominator_;
76
77 public:
78 constexpr LoadFactor(uint8_t numerator, uint8_t denominator)
79 : numerator_(numerator), denominator_(denominator)
80 {
81 BLI_assert(numerator > 0);
82 BLI_assert(numerator < denominator);
83 }
84
85 constexpr void compute_total_and_usable_slots(int64_t min_total_slots,
86 int64_t min_usable_slots,
87 int64_t *r_total_slots,
88 int64_t *r_usable_slots) const
89 {
90 BLI_assert(is_power_of_2(int(min_total_slots)));
91
92 int64_t total_slots = this->compute_total_slots(min_usable_slots, numerator_, denominator_);
93 total_slots = std::max(total_slots, min_total_slots);
95 total_slots, numerator_, denominator_);
96 BLI_assert(min_usable_slots <= usable_slots);
97
98 *r_total_slots = total_slots;
99 *r_usable_slots = usable_slots;
100 }
101
102 static constexpr int64_t compute_total_slots(int64_t min_usable_slots,
103 uint8_t numerator,
104 uint8_t denominator)
105 {
106 return total_slot_amount_for_usable_slots(min_usable_slots, numerator, denominator);
107 }
108};
109
111
112/* -------------------------------------------------------------------- */
129
135template<typename Key, Key EmptyValue, Key RemovedValue> struct TemplatedKeyInfo {
139 static Key get_empty()
140 {
141 return EmptyValue;
142 }
143
147 static void remove(Key &key)
148 {
149 key = RemovedValue;
150 }
151
155 static bool is_empty(const Key &key)
156 {
157 return key == EmptyValue;
158 }
159
163 static bool is_removed(const Key &key)
164 {
165 return key == RemovedValue;
166 }
167
171 static bool is_not_empty_or_removed(const Key &key)
172 {
173 return key != EmptyValue && key != RemovedValue;
174 }
175};
176
185template<typename Pointer> struct PointerKeyInfo {
187 {
188 return (Pointer)UINTPTR_MAX;
189 }
190
191 static void remove(Pointer &pointer)
192 {
193 pointer = (Pointer)(UINTPTR_MAX - 1);
194 }
195
196 static bool is_empty(Pointer pointer)
197 {
198 return uintptr_t(pointer) == UINTPTR_MAX;
199 }
200
201 static bool is_removed(Pointer pointer)
202 {
203 return uintptr_t(pointer) == UINTPTR_MAX - 1;
204 }
205
206 static bool is_not_empty_or_removed(Pointer pointer)
207 {
208 return uintptr_t(pointer) < UINTPTR_MAX - 1;
209 }
210};
211
213
214/* -------------------------------------------------------------------- */
223
225 private:
226 Vector<int64_t> keys_by_collision_count_;
227 int64_t total_collisions_;
228 float average_collisions_;
229 int64_t size_;
230 int64_t capacity_;
231 int64_t removed_amount_;
232 float load_factor_;
233 float removed_load_factor_;
234 int64_t size_per_element_;
235 int64_t size_in_bytes_;
236 const void *address_;
237
238 public:
248 template<typename HashTable, typename Keys>
249 HashTableStats(const HashTable &hash_table, const Keys &keys)
250 {
251 total_collisions_ = 0;
252 size_ = hash_table.size();
253 capacity_ = hash_table.capacity();
254 removed_amount_ = hash_table.removed_amount();
255 size_per_element_ = hash_table.size_per_element();
256 size_in_bytes_ = hash_table.size_in_bytes();
257 address_ = static_cast<const void *>(&hash_table);
258
259 for (const auto &key : keys) {
260 int64_t collisions = hash_table.count_collisions(key);
261 if (keys_by_collision_count_.size() <= collisions) {
262 keys_by_collision_count_.append_n_times(0,
263 collisions - keys_by_collision_count_.size() + 1);
264 }
265 keys_by_collision_count_[collisions]++;
266 total_collisions_ += collisions;
267 }
268
269 average_collisions_ = (size_ == 0) ? 0 : (float)total_collisions_ / (float)size_;
270 load_factor_ = (float)size_ / (float)capacity_;
271 removed_load_factor_ = (float)removed_amount_ / (float)capacity_;
272 }
273
274 void print(const char *name) const;
275};
276
278
285template<typename T> struct DefaultEquality {
286 template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
287 {
288 return a == b;
289 }
290};
291
296 template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
297 {
298 return &*a == &*b;
299 }
300};
301
302template<typename T> struct DefaultEquality<std::unique_ptr<T>> : public PointerComparison {};
303template<typename T> struct DefaultEquality<std::shared_ptr<T>> : public PointerComparison {};
304
306 template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
307 {
308 const auto a_begin = a.begin();
309 const auto a_end = a.end();
310 const auto b_begin = b.begin();
311 const auto b_end = b.end();
312 if (a_end - a_begin != b_end - b_begin) {
313 return false;
314 }
315 return std::equal(a_begin, a_end, b_begin);
316 }
317};
318
319template<typename T, int64_t InlineBufferCapacity, typename Allocator>
320struct DefaultEquality<Vector<T, InlineBufferCapacity, Allocator>> : public SequenceComparison {};
321
322} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
long long int int64_t
unsigned long long int uint64_t
HashTableStats(const HashTable &hash_table, const Keys &keys)
void print(const char *name) const
constexpr LoadFactor(uint8_t numerator, uint8_t denominator)
constexpr void compute_total_and_usable_slots(int64_t min_total_slots, int64_t min_usable_slots, int64_t *r_total_slots, int64_t *r_usable_slots) const
static constexpr int64_t compute_total_slots(int64_t min_usable_slots, uint8_t numerator, uint8_t denominator)
nullptr float
#define UINTPTR_MAX
#define T
#define T2
Definition md5.cpp:21
#define T1
Definition md5.cpp:20
constexpr IntT floor_division(const IntT x, const IntT y)
constexpr int64_t total_slot_amount_for_usable_slots(const int64_t min_usable_slots, const int64_t max_load_factor_numerator, const int64_t max_load_factor_denominator)
constexpr int64_t ceil_division_by_fraction(const int64_t x, const int64_t numerator, const int64_t denominator)
constexpr int64_t floor_multiplication_with_fraction(const int64_t x, const int64_t numerator, const int64_t denominator)
constexpr IntT ceil_division(const IntT x, const IntT y)
const char * name
bool operator()(const T1 &a, const T2 &b) const
bool operator()(const T1 &a, const T2 &b) const
static bool is_empty(Pointer pointer)
static bool is_not_empty_or_removed(Pointer pointer)
static void remove(Pointer &pointer)
static bool is_removed(Pointer pointer)
bool operator()(const T1 &a, const T2 &b) const
static bool is_removed(const Key &key)
static bool is_empty(const Key &key)
static void remove(Key &key)
static bool is_not_empty_or_removed(const Key &key)