84 typename Hash = DefaultHash<Key>,
89 typename IsEqual = DefaultEquality,
119 int64_t occupied_and_removed_slots_;
140 #define LOAD_FACTOR 1, 2
141 LoadFactor max_load_factor_ = LoadFactor(
LOAD_FACTOR);
156 Key *keys_ =
nullptr;
159 #define VECTOR_SET_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
160 SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
161 auto &R_SLOT = slots_[SLOT_INDEX];
162 #define VECTOR_SET_SLOT_PROBING_END() SLOT_PROBING_END()
172 occupied_and_removed_slots_(0),
175 slots_(1, allocator),
192 VectorSet(
const std::initializer_list<Key> &keys, Allocator allocator = {})
200 if (keys_ !=
nullptr) {
201 this->deallocate_keys_array(keys_);
207 keys_ = this->allocate_keys_array(other.usable_slots_);
212 this->deallocate_keys_array(keys_);
216 removed_slots_ = other.removed_slots_;
217 occupied_and_removed_slots_ = other.occupied_and_removed_slots_;
218 usable_slots_ = other.usable_slots_;
219 slot_mask_ = other.slot_mask_;
221 is_equal_ = other.is_equal_;
225 : removed_slots_(other.removed_slots_),
226 occupied_and_removed_slots_(other.occupied_and_removed_slots_),
227 usable_slots_(other.usable_slots_),
228 slot_mask_(other.slot_mask_),
229 slots_(std::move(other.slots_)),
232 other.removed_slots_ = 0;
233 other.occupied_and_removed_slots_ = 0;
234 other.usable_slots_ = 0;
235 other.slot_mask_ = 0;
237 other.keys_ =
nullptr;
283 this->add_new__impl(key, hash_(key));
287 this->add_new__impl(std::move(key), hash_(key));
302 return this->
add_as(std::move(key));
304 template<
typename ForwardKey>
bool add_as(ForwardKey &&key)
306 return this->add__impl(std::forward<ForwardKey>(key), hash_(key));
318 for (
const Key &key : keys) {
332 template<
typename ForwardKey>
bool contains_as(
const ForwardKey &key)
const
334 return this->contains__impl(key, hash_(key));
347 template<
typename ForwardKey>
bool remove_as(
const ForwardKey &key)
349 return this->remove__impl(key, hash_(key));
362 this->remove_contained__impl(key, hash_(key));
371 return this->pop__impl();
384 return this->index_of__impl(key, hash_(key));
397 return this->index_of_try__impl(key, hash_(key));
415 return keys_ + this->
size();
432 return occupied_and_removed_slots_ - removed_slots_;
440 return occupied_and_removed_slots_ == removed_slots_;
448 return slots_.size();
456 return removed_slots_;
464 return sizeof(Slot) +
sizeof(
Key);
473 return static_cast<int64_t>(
sizeof(Slot) * slots_.size() +
sizeof(
Key) * usable_slots_);
481 if (usable_slots_ < n) {
482 this->realloc_and_reinsert(n);
492 return this->count_collisions__impl(key, hash_(key));
498 int64_t total_slots, usable_slots;
499 max_load_factor_.compute_total_and_usable_slots(
505 if (this->
size() == 0) {
507 slots_.reinitialize(total_slots);
508 keys_ = this->allocate_keys_array(usable_slots);
511 this->noexcept_reset();
515 occupied_and_removed_slots_ = 0;
516 usable_slots_ = usable_slots;
517 slot_mask_ = new_slot_mask;
521 SlotArray new_slots(total_slots);
524 for (Slot &slot : slots_) {
525 if (slot.is_occupied()) {
526 this->add_after_grow(slot, new_slots, new_slot_mask);
530 slots_ = std::move(new_slots);
533 this->noexcept_reset();
537 Key *new_keys = this->allocate_keys_array(usable_slots);
542 this->deallocate_keys_array(new_keys);
543 this->noexcept_reset();
546 this->deallocate_keys_array(keys_);
549 occupied_and_removed_slots_ -= removed_slots_;
550 usable_slots_ = usable_slots;
552 slot_mask_ = new_slot_mask;
555 void add_after_grow(Slot &old_slot, SlotArray &new_slots,
const uint64_t new_slot_mask)
557 const Key &key = keys_[old_slot.index()];
561 Slot &slot = new_slots[slot_index];
562 if (slot.is_empty()) {
563 slot.occupy(old_slot.index(),
hash);
570 void noexcept_reset() noexcept
572 Allocator allocator = slots_.allocator();
574 new (
this)
VectorSet(NoExceptConstructor(), allocator);
577 template<
typename ForwardKey>
578 bool contains__impl(
const ForwardKey &key,
const uint64_t hash)
const
581 if (slot.is_empty()) {
584 if (slot.contains(key, is_equal_,
hash, keys_)) {
591 template<
typename ForwardKey>
void add_new__impl(ForwardKey &&key,
const uint64_t hash)
595 this->ensure_can_add();
598 if (slot.is_empty()) {
600 new (keys_ + index)
Key(std::forward<ForwardKey>(key));
601 slot.occupy(index,
hash);
602 occupied_and_removed_slots_++;
609 template<
typename ForwardKey>
bool add__impl(ForwardKey &&key,
const uint64_t hash)
611 this->ensure_can_add();
614 if (slot.is_empty()) {
616 new (keys_ + index)
Key(std::forward<ForwardKey>(key));
617 slot.occupy(index,
hash);
618 occupied_and_removed_slots_++;
621 if (slot.contains(key, is_equal_,
hash, keys_)) {
628 template<
typename ForwardKey>
634 if (slot.contains(key, is_equal_,
hash, keys_)) {
641 template<
typename ForwardKey>
645 if (slot.contains(key, is_equal_,
hash, keys_)) {
648 if (slot.is_empty()) {
660 Key key = std::move(keys_[index_to_pop]);
661 keys_[index_to_pop].~Key();
667 if (slot.has_index(index_to_pop)) {
675 template<
typename ForwardKey>
bool remove__impl(
const ForwardKey &key,
const uint64_t hash)
678 if (slot.contains(key, is_equal_,
hash, keys_)) {
679 this->remove_key_internal(slot);
682 if (slot.is_empty()) {
689 template<
typename ForwardKey>
690 void remove_contained__impl(
const ForwardKey &key,
const uint64_t hash)
695 if (slot.contains(key, is_equal_,
hash, keys_)) {
696 this->remove_key_internal(slot);
703 void remove_key_internal(Slot &slot)
705 int64_t index_to_remove = slot.index();
709 if (index_to_remove < last_element_index) {
710 keys_[index_to_remove] = std::move(keys_[last_element_index]);
711 this->update_slot_index(keys_[index_to_remove], last_element_index, index_to_remove);
714 keys_[last_element_index].~Key();
720 void update_slot_index(
const Key &key,
const int64_t old_index,
const int64_t new_index)
724 if (slot.has_index(old_index)) {
725 slot.update_index(new_index);
732 template<
typename ForwardKey>
738 if (slot.contains(key, is_equal_,
hash, keys_)) {
741 if (slot.is_empty()) {
749 void ensure_can_add()
751 if (occupied_and_removed_slots_ >= usable_slots_) {
752 this->realloc_and_reinsert(this->
size() + 1);
753 BLI_assert(occupied_and_removed_slots_ < usable_slots_);
759 return static_cast<Key *
>(
760 slots_.allocator().allocate(
sizeof(
Key) *
static_cast<size_t>(
size),
alignof(
Key),
AT));
763 void deallocate_keys_array(
Key *keys)
765 slots_.allocator().deallocate(keys);
773 template<
typename Key,
775 typename Hash = DefaultHash<Key>,
776 typename IsEqual = DefaultEquality,
#define SLOT_PROBING_BEGIN(PROBING_STRATEGY, HASH, MASK, R_SLOT_INDEX)
#define SLOT_PROBING_END()
#define VECTOR_SET_SLOT_PROBING_BEGIN(HASH, R_SLOT)
#define VECTOR_SET_SLOT_PROBING_END()
static int64_t inline_buffer_capacity()
void print(StringRef name="")
static constexpr int64_t compute_total_slots(int64_t min_usable_slots, uint8_t numerator, uint8_t denominator)
Span< Key > as_span() const
VectorSet & operator=(const VectorSet &other)
VectorSet(VectorSet &&other) noexcept
int64_t index_of(const Key &key) const
void reserve(const int64_t n)
int64_t count_collisions(const Key &key) const
const Key * begin() const
int64_t index_of_try_as(const ForwardKey &key) const
void add_new(const Key &key)
int64_t index_of_as(const ForwardKey &key) const
bool add_as(ForwardKey &&key)
bool contains_as(const ForwardKey &key) const
int64_t size_per_element() const
VectorSet(Allocator allocator={}) noexcept
VectorSet(Span< Key > keys, Allocator allocator={})
void print_stats(StringRef name="") const
int64_t index_of_try(const Key &key) const
int64_t size_in_bytes() const
void remove_contained_as(const ForwardKey &key)
VectorSet(NoExceptConstructor, Allocator allocator={})
VectorSet(const std::initializer_list< Key > &keys, Allocator allocator={})
void remove_contained(const Key &key)
VectorSet & operator=(VectorSet &&other)
int64_t removed_amount() const
VectorSet(const VectorSet &other)
const Key & operator[](const int64_t index) const
bool contains(const Key &key) const
bool remove_as(const ForwardKey &key)
void add_multiple(Span< Key > keys)
bool remove(const Key &key)
Container & move_assign_container(Container &dst, Container &&src) noexcept(std::is_nothrow_move_constructible_v< Container >)
Container & copy_assign_container(Container &dst, const Container &src)
PythonProbingStrategy<> DefaultProbingStrategy
void uninitialized_relocate_n(T *src, int64_t n, T *dst)
void destruct_n(T *ptr, int64_t n)
void uninitialized_copy_n(const T *src, int64_t n, T *dst)
unsigned __int64 uint64_t
SimpleVectorSetSlot< Key > type