Blender V4.3
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
13#include <algorithm>
14
15#include "BLI_memory_utils.hh"
16#include "BLI_utildefines.h"
17#include "BLI_vector.hh"
18
19namespace blender {
20
21/* -------------------------------------------------------------------- */
27template<typename IntT> inline constexpr IntT ceil_division(const IntT x, const IntT y)
28{
29 BLI_assert(x >= 0);
30 BLI_assert(y >= 0);
31 return x / y + ((x % y) != 0);
32}
33
34template<typename IntT> inline constexpr IntT floor_division(const IntT x, const IntT y)
35{
36 BLI_assert(x >= 0);
37 BLI_assert(y >= 0);
38 return x / y;
39}
40
41inline constexpr int64_t ceil_division_by_fraction(const int64_t x,
42 const int64_t numerator,
43 const int64_t denominator)
44{
45 return int64_t(ceil_division(uint64_t(x) * uint64_t(denominator), uint64_t(numerator)));
46}
47
49 const int64_t numerator,
50 const int64_t denominator)
51{
52 return int64_t((uint64_t(x) * uint64_t(numerator) / uint64_t(denominator)));
53}
54
56 const int64_t min_usable_slots,
57 const int64_t max_load_factor_numerator,
58 const int64_t max_load_factor_denominator)
59{
60 return power_of_2_max(ceil_division_by_fraction(
61 min_usable_slots, max_load_factor_numerator, max_load_factor_denominator));
62}
63
66/* -------------------------------------------------------------------- */
75 private:
76 uint8_t numerator_;
77 uint8_t denominator_;
78
79 public:
80 LoadFactor(uint8_t numerator, uint8_t denominator)
81 : numerator_(numerator), denominator_(denominator)
82 {
83 BLI_assert(numerator > 0);
84 BLI_assert(numerator < denominator);
85 }
86
88 int64_t min_usable_slots,
89 int64_t *r_total_slots,
90 int64_t *r_usable_slots) const
91 {
92 BLI_assert(is_power_of_2(int(min_total_slots)));
93
94 int64_t total_slots = this->compute_total_slots(min_usable_slots, numerator_, denominator_);
95 total_slots = std::max(total_slots, min_total_slots);
97 total_slots, numerator_, denominator_);
98 BLI_assert(min_usable_slots <= usable_slots);
99
100 *r_total_slots = total_slots;
101 *r_usable_slots = usable_slots;
102 }
103
104 static constexpr int64_t compute_total_slots(int64_t min_usable_slots,
105 uint8_t numerator,
106 uint8_t denominator)
107 {
108 return total_slot_amount_for_usable_slots(min_usable_slots, numerator, denominator);
109 }
110};
111
114/* -------------------------------------------------------------------- */
137template<typename Key, Key EmptyValue, Key RemovedValue> struct TemplatedKeyInfo {
141 static Key get_empty()
142 {
143 return EmptyValue;
144 }
145
149 static void remove(Key &key)
150 {
151 key = RemovedValue;
152 }
153
157 static bool is_empty(const Key &key)
158 {
159 return key == EmptyValue;
160 }
161
165 static bool is_removed(const Key &key)
166 {
167 return key == RemovedValue;
168 }
169
173 static bool is_not_empty_or_removed(const Key &key)
174 {
175 return key != EmptyValue && key != RemovedValue;
176 }
177};
178
187template<typename Pointer> struct PointerKeyInfo {
188 static Pointer get_empty()
189 {
190 return (Pointer)UINTPTR_MAX;
191 }
192
193 static void remove(Pointer &pointer)
194 {
195 pointer = (Pointer)(UINTPTR_MAX - 1);
196 }
197
198 static bool is_empty(Pointer pointer)
199 {
200 return uintptr_t(pointer) == UINTPTR_MAX;
201 }
202
203 static bool is_removed(Pointer pointer)
204 {
205 return uintptr_t(pointer) == UINTPTR_MAX - 1;
206 }
207
208 static bool is_not_empty_or_removed(Pointer pointer)
209 {
210 return uintptr_t(pointer) < UINTPTR_MAX - 1;
211 }
212};
213
216/* -------------------------------------------------------------------- */
227 private:
228 Vector<int64_t> keys_by_collision_count_;
229 int64_t total_collisions_;
230 float average_collisions_;
231 int64_t size_;
232 int64_t capacity_;
233 int64_t removed_amount_;
234 float load_factor_;
235 float removed_load_factor_;
236 int64_t size_per_element_;
237 int64_t size_in_bytes_;
238 const void *address_;
239
240 public:
250 template<typename HashTable, typename Keys>
251 HashTableStats(const HashTable &hash_table, const Keys &keys)
252 {
253 total_collisions_ = 0;
254 size_ = hash_table.size();
255 capacity_ = hash_table.capacity();
256 removed_amount_ = hash_table.removed_amount();
257 size_per_element_ = hash_table.size_per_element();
258 size_in_bytes_ = hash_table.size_in_bytes();
259 address_ = static_cast<const void *>(&hash_table);
260
261 for (const auto &key : keys) {
262 int64_t collisions = hash_table.count_collisions(key);
263 if (keys_by_collision_count_.size() <= collisions) {
264 keys_by_collision_count_.append_n_times(0,
265 collisions - keys_by_collision_count_.size() + 1);
266 }
267 keys_by_collision_count_[collisions]++;
268 total_collisions_ += collisions;
269 }
270
271 average_collisions_ = (size_ == 0) ? 0 : (float)total_collisions_ / (float)size_;
272 load_factor_ = (float)size_ / (float)capacity_;
273 removed_load_factor_ = (float)removed_amount_ / (float)capacity_;
274 }
275
276 void print(const char *name) const;
277};
278
287template<typename T> struct DefaultEquality {
288 template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
289 {
290 return a == b;
291 }
292};
293
298 template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
299 {
300 return &*a == &*b;
301 }
302};
303
304template<typename T> struct DefaultEquality<std::unique_ptr<T>> : public PointerComparison {};
305template<typename T> struct DefaultEquality<std::shared_ptr<T>> : public PointerComparison {};
306
308 template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
309 {
310 const auto a_begin = a.begin();
311 const auto a_end = a.end();
312 const auto b_begin = b.begin();
313 const auto b_end = b.end();
314 if (a_end - a_begin != b_end - b_begin) {
315 return false;
316 }
317 return std::equal(a_begin, a_end, b_begin);
318 }
319};
320
321template<typename T, int64_t InlineBufferCapacity, typename Allocator>
322struct DefaultEquality<Vector<T, InlineBufferCapacity, Allocator>> : public SequenceComparison {};
323
324} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:50
HashTableStats(const HashTable &hash_table, const Keys &keys)
void print(const char *name) const
LoadFactor(uint8_t numerator, uint8_t denominator)
static constexpr int64_t compute_total_slots(int64_t min_usable_slots, uint8_t numerator, uint8_t denominator)
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
int64_t size() const
void append_n_times(const T &value, const int64_t n)
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
#define T2
Definition md5.cpp:19
#define T1
Definition md5.cpp:18
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)
_W64 unsigned int uintptr_t
Definition stdint.h:119
__int64 int64_t
Definition stdint.h:89
#define UINTPTR_MAX
Definition stdint.h:181
unsigned char uint8_t
Definition stdint.h:78
unsigned __int64 uint64_t
Definition stdint.h:90
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)