68template<
typename Key,
typename Value>
struct MapItem {
83 return {this->
key, this->value};
111 typename Hash = DefaultHash<Key>,
116 typename IsEqual = DefaultEquality<Key>,
141 int64_t occupied_and_removed_slots_;
162#define LOAD_FACTOR 1, 2
163 LoadFactor max_load_factor_ = LoadFactor(
LOAD_FACTOR);
175#define MAP_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
176 SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
177 auto &R_SLOT = slots_[SLOT_INDEX];
178#define MAP_SLOT_PROBING_END() SLOT_PROBING_END()
186 Map(Allocator allocator = {})
noexcept
188 occupied_and_removed_slots_(0),
203 Map(
Map &&other)
noexcept(std::is_nothrow_move_constructible_v<SlotArray>)
206 if constexpr (std::is_nothrow_move_constructible_v<SlotArray>) {
207 slots_ = std::move(other.slots_);
211 slots_ = std::move(other.slots_);
214 other.noexcept_reset();
218 removed_slots_ = other.removed_slots_;
219 occupied_and_removed_slots_ = other.occupied_and_removed_slots_;
220 usable_slots_ = other.usable_slots_;
221 slot_mask_ = other.slot_mask_;
222 hash_ = std::move(other.hash_);
223 is_equal_ = std::move(other.is_equal_);
224 other.noexcept_reset();
255 this->
add_new_as(std::move(key), std::move(value));
257 template<
typename ForwardKey,
typename... ForwardValue>
261 std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
271 bool add(
const Key &key,
const Value &value)
273 return this->
add_as(key, value);
277 return this->
add_as(key, std::move(value));
281 return this->
add_as(std::move(key), value);
285 return this->
add_as(std::move(key), std::move(value));
287 template<
typename ForwardKey,
typename... ForwardValue>
288 bool add_as(ForwardKey &&key, ForwardValue &&...value)
290 return this->add__impl(
291 std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
317 template<
typename ForwardKey,
typename... ForwardValue>
320 return this->add_overwrite__impl(
321 std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
333 template<
typename ForwardKey>
bool contains_as(
const ForwardKey &key)
const
335 return this->lookup_slot_ptr(key, hash_(key)) !=
nullptr;
348 template<
typename ForwardKey>
bool remove_as(
const ForwardKey &key)
350 Slot *slot = this->lookup_slot_ptr(key, hash_(key));
351 if (slot ==
nullptr) {
369 Slot &slot = this->lookup_slot(key, hash_(key));
382 template<
typename ForwardKey> Value
pop_as(
const ForwardKey &key)
384 Slot &slot = this->lookup_slot(key, hash_(key));
385 Value value = std::move(*slot.value());
399 template<
typename ForwardKey> std::optional<Value>
pop_try_as(
const ForwardKey &key)
401 Slot *slot = this->lookup_slot_ptr(key, hash_(key));
402 if (slot ==
nullptr) {
405 std::optional<Value> value = std::move(*slot->value());
423 template<
typename ForwardKey,
typename... ForwardValue>
426 Slot *slot = this->lookup_slot_ptr(key, hash_(key));
427 if (slot ==
nullptr) {
428 return Value(std::forward<ForwardValue>(default_value)...);
430 Value value = std::move(*slot->value());
456 template<
typename CreateValueF,
typename ModifyValueF>
458 const CreateValueF &create_value,
459 const ModifyValueF &modify_value) ->
decltype(create_value(
nullptr))
463 template<
typename CreateValueF,
typename ModifyValueF>
464 auto add_or_modify(
Key &&key,
const CreateValueF &create_value,
const ModifyValueF &modify_value)
465 ->
decltype(create_value(
nullptr))
469 template<
typename ForwardKey,
typename CreateValueF,
typename ModifyValueF>
471 const CreateValueF &create_value,
472 const ModifyValueF &modify_value) ->
decltype(create_value(
nullptr))
474 return this->add_or_modify__impl(
475 std::forward<ForwardKey>(key), create_value, modify_value, hash_(key));
492 template<
typename ForwardKey>
const Value *
lookup_ptr_as(
const ForwardKey &key)
const
494 const Slot *slot = this->lookup_slot_ptr(key, hash_(key));
495 return (slot !=
nullptr) ? slot->value() :
nullptr;
499 return const_cast<Value *
>(
const_cast<const Map *
>(
this)->
lookup_ptr_as(key));
514 template<
typename ForwardKey>
const Value &
lookup_as(
const ForwardKey &key)
const
520 template<
typename ForwardKey> Value &
lookup_as(
const ForwardKey &key)
535 template<
typename ForwardKey,
typename... ForwardValue>
539 if (
ptr !=
nullptr) {
543 return Value(std::forward<ForwardValue>(default_value)...);
567 template<
typename ForwardKey,
typename... ForwardValue>
570 return this->lookup_or_add__impl(
571 std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
581 template<
typename CreateValueF>
586 template<
typename CreateValueF>
591 template<
typename ForwardKey,
typename CreateValueF>
594 return this->lookup_or_add_cb__impl(std::forward<ForwardKey>(key), create_value, hash_(key));
624 const Slot &slot = this->lookup_slot(key, hash_(key));
638 const Slot *slot = this->lookup_slot_ptr(key, hash_(key));
639 if (slot ==
nullptr) {
653 const Slot &slot = slots_[i];
654 if (slot.is_occupied()) {
655 const Key &key = *slot.key();
656 const Value &value = *slot.value();
697 return copied_iterator;
704 return a.current_slot_ !=
b.current_slot_;
733 if (this->
slots_[i].is_occupied()) {
734 return SubIterator(this->
slots_, this->total_slots_, i);
811 return {*slot.key(), *slot.value()};
829 return {*slot.key(), *slot.value()};
902 for (Slot &slot : slots_) {
903 if (slot.is_occupied()) {
904 const Key &key = *slot.key();
905 Value &value = *slot.value();
912 return prev_size - this->
size();
929 return occupied_and_removed_slots_ - removed_slots_;
939 return occupied_and_removed_slots_ == removed_slots_;
947 return slots_.
size();
955 return removed_slots_;
981 if (usable_slots_ < n) {
982 this->realloc_and_reinsert(n);
991 for (Slot &slot : slots_) {
997 occupied_and_removed_slots_ = 0;
1005 std::destroy_at(
this);
1015 return this->count_collisions__impl(key, hash_(key));
1023 if (a.size() !=
b.size()) {
1026 for (
const Item item : a.items()) {
1027 const Key &key = item.key;
1028 const Value &value_a = item.value;
1029 const Value *value_b =
b.lookup_ptr(key);
1030 if (value_b ==
nullptr) {
1033 if (value_a != *value_b) {
1048 int64_t total_slots, usable_slots;
1057 if (this->
size() == 0) {
1062 this->noexcept_reset();
1066 occupied_and_removed_slots_ = 0;
1067 usable_slots_ = usable_slots;
1068 slot_mask_ = new_slot_mask;
1072 SlotArray new_slots(total_slots);
1075 for (Slot &slot : slots_) {
1076 if (slot.is_occupied()) {
1077 this->add_after_grow(slot, new_slots, new_slot_mask);
1081 slots_ = std::move(new_slots);
1084 this->noexcept_reset();
1088 occupied_and_removed_slots_ -= removed_slots_;
1089 usable_slots_ = usable_slots;
1091 slot_mask_ = new_slot_mask;
1094 void add_after_grow(Slot &old_slot, SlotArray &new_slots,
uint64_t new_slot_mask)
1098 Slot &slot = new_slots[slot_index];
1099 if (slot.is_empty()) {
1100 slot.occupy(std::move(*old_slot.key()),
hash, std::move(*old_slot.value()));
1107 void noexcept_reset() noexcept
1109 Allocator allocator = slots_.
allocator();
1111 new (
this)
Map(NoExceptConstructor(), allocator);
1114 template<
typename ForwardKey,
typename... ForwardValue>
1115 void add_new__impl(ForwardKey &&key,
uint64_t hash, ForwardValue &&...value)
1119 this->ensure_can_add();
1122 if (slot.is_empty()) {
1123 slot.occupy(std::forward<ForwardKey>(key),
hash, std::forward<ForwardValue>(value)...);
1125 occupied_and_removed_slots_++;
1132 template<
typename ForwardKey,
typename... ForwardValue>
1133 bool add__impl(ForwardKey &&key,
uint64_t hash, ForwardValue &&...value)
1135 this->ensure_can_add();
1138 if (slot.is_empty()) {
1139 slot.occupy(std::forward<ForwardKey>(key),
hash, std::forward<ForwardValue>(value)...);
1141 occupied_and_removed_slots_++;
1144 if (slot.contains(key, is_equal_,
hash)) {
1151 template<
typename ForwardKey,
typename CreateValueF,
typename ModifyValueF>
1152 auto add_or_modify__impl(ForwardKey &&key,
1153 const CreateValueF &create_value,
1154 const ModifyValueF &modify_value,
1157 using CreateReturnT =
decltype(create_value(
nullptr));
1158 using ModifyReturnT =
decltype(modify_value(
nullptr));
1160 "Both callbacks should return the same type.");
1162 this->ensure_can_add();
1165 if (slot.is_empty()) {
1166 Value *value_ptr = slot.value();
1167 if constexpr (std::is_void_v<CreateReturnT>) {
1168 create_value(value_ptr);
1169 slot.occupy_no_value(std::forward<ForwardKey>(key),
hash);
1170 occupied_and_removed_slots_++;
1174 auto &&return_value = create_value(value_ptr);
1175 slot.occupy_no_value(std::forward<ForwardKey>(key),
hash);
1176 occupied_and_removed_slots_++;
1177 return return_value;
1180 if (slot.contains(key, is_equal_,
hash)) {
1181 Value *value_ptr = slot.value();
1182 return modify_value(value_ptr);
1188 template<
typename ForwardKey,
typename CreateValueF>
1189 Value &lookup_or_add_cb__impl(ForwardKey &&key,
const CreateValueF &create_value,
uint64_t hash)
1191 this->ensure_can_add();
1194 if (slot.is_empty()) {
1195 slot.occupy(std::forward<ForwardKey>(key),
hash, create_value());
1197 occupied_and_removed_slots_++;
1198 return *slot.value();
1200 if (slot.contains(key, is_equal_,
hash)) {
1201 return *slot.value();
1207 template<
typename ForwardKey,
typename... ForwardValue>
1208 Value &lookup_or_add__impl(ForwardKey &&key,
uint64_t hash, ForwardValue &&...value)
1210 this->ensure_can_add();
1213 if (slot.is_empty()) {
1214 slot.occupy(std::forward<ForwardKey>(key),
hash, std::forward<ForwardValue>(value)...);
1216 occupied_and_removed_slots_++;
1217 return *slot.value();
1219 if (slot.contains(key, is_equal_,
hash)) {
1220 return *slot.value();
1226 template<
typename ForwardKey,
typename... ForwardValue>
1227 bool add_overwrite__impl(ForwardKey &&key,
uint64_t hash, ForwardValue &&...value)
1230 new (
static_cast<void *
>(
ptr))
Value(std::forward<ForwardValue>(value)...);
1233 auto modify_func = [&](Value *
ptr) {
1234 *
ptr =
Value(std::forward<ForwardValue>(value)...);
1237 return this->add_or_modify__impl(
1241 template<
typename ForwardKey>
1242 const Slot &lookup_slot(
const ForwardKey &key,
const uint64_t hash)
const
1246 if (slot.contains(key, is_equal_,
hash)) {
1253 template<
typename ForwardKey> Slot &lookup_slot(
const ForwardKey &key,
const uint64_t hash)
1255 return const_cast<Slot &
>(
const_cast<const Map *
>(
this)->lookup_slot(key,
hash));
1258 template<
typename ForwardKey>
1259 const Slot *lookup_slot_ptr(
const ForwardKey &key,
const uint64_t hash)
const
1262 if (slot.contains(key, is_equal_,
hash)) {
1265 if (slot.is_empty()) {
1272 template<
typename ForwardKey> Slot *lookup_slot_ptr(
const ForwardKey &key,
const uint64_t hash)
1274 return const_cast<Slot *
>(
const_cast<const Map *
>(
this)->lookup_slot_ptr(key,
hash));
1277 template<
typename ForwardKey>
1283 if (slot.contains(key, is_equal_,
hash)) {
1286 if (slot.is_empty()) {
1294 void ensure_can_add()
1296 if (occupied_and_removed_slots_ >= usable_slots_) {
1297 this->realloc_and_reinsert(this->
size() + 1);
1298 BLI_assert(occupied_and_removed_slots_ < usable_slots_);
1307template<
typename Key,
1312 typename Hash = DefaultHash<Key>,
1313 typename IsEqual = DefaultEquality<Key>,
#define BLI_STATIC_ASSERT(a, msg)
#define MAP_SLOT_PROBING_END()
#define MAP_SLOT_PROBING_BEGIN(HASH, R_SLOT)
#define SLOT_PROBING_BEGIN(PROBING_STRATEGY, HASH, MASK, R_SLOT_INDEX)
#define SLOT_PROBING_END()
#define BLI_NO_UNIQUE_ADDRESS
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Value
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Map
static int64_t inline_buffer_capacity()
void reinitialize(const int64_t new_size)
void print(const char *name) const
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
SubIterator begin() const
BaseIteratorRange(const Slot *slots, int64_t total_slots, int64_t current_slot)
ItemIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
KeyIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
const Key & operator*() const
MutableItemIterator(Slot *slots, int64_t total_slots, int64_t current_slot)
MutableItem operator*() const
MutableValueIterator(Slot *slots, int64_t total_slots, int64_t current_slot)
const Value & operator*() const
ValueIterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
MutableItemIterator items()
Value pop_as(const ForwardKey &key)
bool add_overwrite(Key &&key, Value &&value)
Value pop_default_as(const ForwardKey &key, ForwardValue &&...default_value)
const Value * lookup_ptr(const Key &key) const
void print_stats(const char *name) const
int64_t size_in_bytes() const
Value pop(const Key &key)
Value & lookup(const Key &key)
friend bool operator!=(const Map &a, const Map &b)
Value & lookup_as(const ForwardKey &key)
std::optional< Value > pop_try(const Key &key)
void add_new(const Key &key, Value &&value)
Value & lookup_or_add_default(const Key &key)
MutableMapItem< Key, Value > MutableItem
void add_new(Key &&key, const Value &value)
Value & lookup_or_add(Key &&key, const Value &value)
const Key & lookup_key_as(const ForwardKey &key) const
Value & lookup_or_add_default(Key &&key)
int64_t removed_amount() const
Map(NoExceptConstructor, Allocator allocator={}) noexcept
bool remove_as(const ForwardKey &key)
bool add_overwrite(const Key &key, const Value &value)
bool add(const Key &key, const Value &value)
int64_t size_per_element() const
const Value & lookup(const Key &key) const
Value & lookup_or_add(const Key &key, Value &&value)
void remove_contained_as(const ForwardKey &key)
Value lookup_default(const Key &key, const Value &default_value) const
const Key * lookup_key_ptr_as(const ForwardKey &key) const
bool add_overwrite(Key &&key, const Value &value)
int64_t count_collisions(const Key &key) const
ValueIterator values() const
MutableValueIterator values()
Value & lookup_or_add_cb(Key &&key, const CreateValueF &create_value)
void add_new_as(ForwardKey &&key, ForwardValue &&...value)
Value & lookup_or_add_default_as(ForwardKey &&key)
Value & lookup_or_add_as(ForwardKey &&key, ForwardValue &&...value)
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
const Value * lookup_ptr_as(const ForwardKey &key) const
friend bool operator==(const Map &a, const Map &b)
Value * lookup_ptr(const Key &key)
void foreach_item(const FuncT &func) const
void remove_contained(const Key &key)
Map(const Map &other)=default
Map(Allocator allocator={}) noexcept
const Key & lookup_key(const Key &key) const
bool add_as(ForwardKey &&key, ForwardValue &&...value)
auto add_or_modify_as(ForwardKey &&key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
Value & lookup_or_add_cb_as(ForwardKey &&key, const CreateValueF &create_value)
void add_new(Key &&key, Value &&value)
const Key * lookup_key_ptr(const Key &key) const
void add_new(const Key &key, const Value &value)
bool add(Key &&key, Value &&value)
Map & operator=(Map &&other)
Map(Map &&other) noexcept(std::is_nothrow_move_constructible_v< SlotArray >)
const Value & lookup_as(const ForwardKey &key) const
bool remove(const Key &key)
bool contains_as(const ForwardKey &key) const
MapItem< Key, Value > Item
ItemIterator items() const
bool add(const Key &key, Value &&value)
auto add_or_modify(Key &&key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
bool add_overwrite_as(ForwardKey &&key, ForwardValue &&...value)
bool contains(const Key &key) const
Map & operator=(const Map &other)
Value pop_default(const Key &key, Value &&default_value)
bool add(Key &&key, const Value &value)
Value * lookup_ptr_as(const ForwardKey &key)
bool add_overwrite(const Key &key, Value &&value)
Value lookup_default_as(const ForwardKey &key, ForwardValue &&...default_value) const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
int64_t remove_if(Predicate &&predicate)
Value pop_default(const Key &key, const Value &default_value)
Value & lookup_or_add(Key &&key, Value &&value)
std::optional< Value > pop_try_as(const ForwardKey &key)
void remove(const BaseIterator &iterator)
Value & lookup_or_add(const Key &key, const Value &value)
local_group_size(16, 16) .push_constant(Type b
Container & copy_assign_container(Container &dst, const Container &src)
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
constexpr int64_t default_inline_buffer_capacity(size_t element_size)
PythonProbingStrategy<> DefaultProbingStrategy
static PyObject * create_func(PyObject *, PyObject *args)
unsigned __int64 uint64_t
SimpleMapSlot< Key, Value > type
friend bool operator==(const BaseIterator &a, const BaseIterator &b)
Slot & current_slot() const
BaseIterator operator++(int)
friend bool operator!=(const BaseIterator &a, const BaseIterator &b)
BaseIterator & operator++()
std::ptrdiff_t difference_type
std::forward_iterator_tag iterator_category
BaseIterator(const Slot *slots, const int64_t total_slots, const int64_t current_slot)