Blender  V2.93
BLI_hash_tables.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
25 #include <cmath>
26 
27 #include "BLI_allocator.hh"
28 #include "BLI_array.hh"
29 #include "BLI_math_base.h"
30 #include "BLI_memory_utils.hh"
31 #include "BLI_string.h"
32 #include "BLI_string_ref.hh"
33 #include "BLI_utildefines.h"
34 #include "BLI_vector.hh"
35 
36 namespace blender {
37 
38 /* -------------------------------------------------------------------- */
44 inline constexpr int64_t is_power_of_2_constexpr(const int64_t x)
45 {
46  BLI_assert(x >= 0);
47  return (x & (x - 1)) == 0;
48 }
49 
50 inline constexpr int64_t log2_floor_constexpr(const int64_t x)
51 {
52  BLI_assert(x >= 0);
53  return x <= 1 ? 0 : 1 + log2_floor_constexpr(x >> 1);
54 }
55 
56 inline constexpr int64_t log2_ceil_constexpr(const int64_t x)
57 {
58  BLI_assert(x >= 0);
59  return (is_power_of_2_constexpr(static_cast<int>(x))) ? log2_floor_constexpr(x) :
61 }
62 
63 inline constexpr int64_t power_of_2_max_constexpr(const int64_t x)
64 {
65  BLI_assert(x >= 0);
66  return 1ll << log2_ceil_constexpr(x);
67 }
68 
69 template<typename IntT> inline constexpr IntT ceil_division(const IntT x, const IntT y)
70 {
71  BLI_assert(x >= 0);
72  BLI_assert(y >= 0);
73  return x / y + ((x % y) != 0);
74 }
75 
76 template<typename IntT> inline constexpr IntT floor_division(const IntT x, const IntT y)
77 {
78  BLI_assert(x >= 0);
79  BLI_assert(y >= 0);
80  return x / y;
81 }
82 
83 inline constexpr int64_t ceil_division_by_fraction(const int64_t x,
84  const int64_t numerator,
85  const int64_t denominator)
86 {
87  return static_cast<int64_t>(
88  ceil_division(static_cast<uint64_t>(x) * static_cast<uint64_t>(denominator),
89  static_cast<uint64_t>(numerator)));
90 }
91 
93  const int64_t numerator,
94  const int64_t denominator)
95 {
96  return static_cast<int64_t>((static_cast<uint64_t>(x) * static_cast<uint64_t>(numerator) /
97  static_cast<uint64_t>(denominator)));
98 }
99 
101  const int64_t min_usable_slots,
102  const int64_t max_load_factor_numerator,
103  const int64_t max_load_factor_denominator)
104 {
106  min_usable_slots, max_load_factor_numerator, max_load_factor_denominator));
107 }
108 
111 /* -------------------------------------------------------------------- */
119 class LoadFactor {
120  private:
121  uint8_t numerator_;
122  uint8_t denominator_;
123 
124  public:
125  LoadFactor(uint8_t numerator, uint8_t denominator)
126  : numerator_(numerator), denominator_(denominator)
127  {
128  BLI_assert(numerator > 0);
129  BLI_assert(numerator < denominator);
130  }
131 
133  int64_t min_usable_slots,
134  int64_t *r_total_slots,
135  int64_t *r_usable_slots) const
136  {
137  BLI_assert(is_power_of_2_i(static_cast<int>(min_total_slots)));
138 
139  int64_t total_slots = this->compute_total_slots(min_usable_slots, numerator_, denominator_);
140  total_slots = std::max(total_slots, min_total_slots);
141  const int64_t usable_slots = floor_multiplication_with_fraction(
142  total_slots, numerator_, denominator_);
143  BLI_assert(min_usable_slots <= usable_slots);
144 
145  *r_total_slots = total_slots;
146  *r_usable_slots = usable_slots;
147  }
148 
149  static constexpr int64_t compute_total_slots(int64_t min_usable_slots,
150  uint8_t numerator,
151  uint8_t denominator)
152  {
153  return total_slot_amount_for_usable_slots(min_usable_slots, numerator, denominator);
154  }
155 };
156 
159 /* -------------------------------------------------------------------- */
182 template<typename Key, Key EmptyValue, Key RemovedValue> struct TemplatedKeyInfo {
186  static Key get_empty()
187  {
188  return EmptyValue;
189  }
190 
194  static void remove(Key &key)
195  {
196  key = RemovedValue;
197  }
198 
202  static bool is_empty(const Key &key)
203  {
204  return key == EmptyValue;
205  }
206 
210  static bool is_removed(const Key &key)
211  {
212  return key == RemovedValue;
213  }
214 
218  static bool is_not_empty_or_removed(const Key &key)
219  {
220  return key != EmptyValue && key != RemovedValue;
221  }
222 };
223 
232 template<typename Pointer> struct PointerKeyInfo {
233  static Pointer get_empty()
234  {
235  return (Pointer)UINTPTR_MAX;
236  }
237 
238  static void remove(Pointer &pointer)
239  {
240  pointer = (Pointer)(UINTPTR_MAX - 1);
241  }
242 
243  static bool is_empty(Pointer pointer)
244  {
245  return (uintptr_t)pointer == UINTPTR_MAX;
246  }
247 
248  static bool is_removed(Pointer pointer)
249  {
250  return (uintptr_t)pointer == UINTPTR_MAX - 1;
251  }
252 
253  static bool is_not_empty_or_removed(Pointer pointer)
254  {
255  return (uintptr_t)pointer < UINTPTR_MAX - 1;
256  }
257 };
258 
261 /* -------------------------------------------------------------------- */
272  private:
273  Vector<int64_t> keys_by_collision_count_;
274  int64_t total_collisions_;
275  float average_collisions_;
276  int64_t size_;
277  int64_t capacity_;
278  int64_t removed_amount_;
279  float load_factor_;
280  float removed_load_factor_;
281  int64_t size_per_element_;
282  int64_t size_in_bytes_;
283  const void *address_;
284 
285  public:
295  template<typename HashTable, typename Keys>
296  HashTableStats(const HashTable &hash_table, const Keys &keys)
297  {
298  total_collisions_ = 0;
299  size_ = hash_table.size();
300  capacity_ = hash_table.capacity();
301  removed_amount_ = hash_table.removed_amount();
302  size_per_element_ = hash_table.size_per_element();
303  size_in_bytes_ = hash_table.size_in_bytes();
304  address_ = static_cast<const void *>(&hash_table);
305 
306  for (const auto &key : keys) {
307  int64_t collisions = hash_table.count_collisions(key);
308  if (keys_by_collision_count_.size() <= collisions) {
309  keys_by_collision_count_.append_n_times(0,
310  collisions - keys_by_collision_count_.size() + 1);
311  }
312  keys_by_collision_count_[collisions]++;
313  total_collisions_ += collisions;
314  }
315 
316  average_collisions_ = (size_ == 0) ? 0 : (float)total_collisions_ / (float)size_;
317  load_factor_ = (float)size_ / (float)capacity_;
318  removed_load_factor_ = (float)removed_amount_ / (float)capacity_;
319  }
320 
321  void print(StringRef name = "")
322  {
323  std::cout << "Hash Table Stats: " << name << "\n";
324  std::cout << " Address: " << address_ << "\n";
325  std::cout << " Total Slots: " << capacity_ << "\n";
326  std::cout << " Occupied Slots: " << size_ << " (" << load_factor_ * 100.0f << " %)\n";
327  std::cout << " Removed Slots: " << removed_amount_ << " (" << removed_load_factor_ * 100.0f
328  << " %)\n";
329 
330  char memory_size_str[15];
331  BLI_str_format_byte_unit(memory_size_str, size_in_bytes_, true);
332  std::cout << " Size: ~" << memory_size_str << "\n";
333  std::cout << " Size per Slot: " << size_per_element_ << " bytes\n";
334 
335  std::cout << " Average Collisions: " << average_collisions_ << "\n";
336  for (int64_t collision_count : keys_by_collision_count_.index_range()) {
337  std::cout << " " << collision_count
338  << " Collisions: " << keys_by_collision_count_[collision_count] << "\n";
339  }
340  }
341 };
342 
352  template<typename T1, typename T2> bool operator()(const T1 &a, const T2 &b) const
353  {
354  return a == b;
355  }
356 };
357 
358 } // namespace blender
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE int is_power_of_2_i(int n)
void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10) ATTR_NONNULL()
Definition: string.c:1206
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
HashTableStats(const HashTable &hash_table, const Keys &keys)
void print(StringRef name="")
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
Definition: BLI_vector.hh:662
IndexRange index_range() const
Definition: BLI_vector.hh:887
void append_n_times(const T &value, const int64_t n)
Definition: BLI_vector.hh:489
static unsigned a[3]
Definition: RandGen.cpp:92
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 power_of_2_max_constexpr(const int64_t x)
constexpr int64_t log2_ceil_constexpr(const int64_t x)
constexpr int64_t log2_floor_constexpr(const int64_t x)
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)
constexpr int64_t is_power_of_2_constexpr(const int64_t x)
_W64 unsigned int uintptr_t
Definition: stdint.h:122
__int64 int64_t
Definition: stdint.h:92
#define UINTPTR_MAX
Definition: stdint.h:184
unsigned char uint8_t
Definition: stdint.h:81
unsigned __int64 uint64_t
Definition: stdint.h:93
bool operator()(const T1 &a, const T2 &b) const
static bool is_empty(Pointer pointer)
static Pointer get_empty()
static bool is_not_empty_or_removed(Pointer pointer)
static void remove(Pointer &pointer)
static bool is_removed(Pointer pointer)
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)
float max
#define T2
Definition: util_md5.cpp:36
#define T1
Definition: util_md5.cpp:35