72 #include <unordered_set>
101 typename Hash = DefaultHash<Key>,
106 typename IsEqual = DefaultEquality,
138 int64_t occupied_and_removed_slots_;
159 #define LOAD_FACTOR 1, 2
160 LoadFactor max_load_factor_ = LoadFactor(
LOAD_FACTOR);
172 #define SET_SLOT_PROBING_BEGIN(HASH, R_SLOT) \
173 SLOT_PROBING_BEGIN (ProbingStrategy, HASH, slot_mask_, SLOT_INDEX) \
174 auto &R_SLOT = slots_[SLOT_INDEX];
175 #define SET_SLOT_PROBING_END() SLOT_PROBING_END()
183 Set(Allocator allocator = {}) noexcept
185 occupied_and_removed_slots_(0),
212 Set(
Set &&other) noexcept(std::is_nothrow_move_constructible_v<SlotArray>)
216 if constexpr (std::is_nothrow_move_constructible_v<SlotArray>) {
217 slots_ = std::move(other.slots_);
221 slots_ = std::move(other.slots_);
224 other.noexcept_reset();
228 removed_slots_ = other.removed_slots_;
229 occupied_and_removed_slots_ = other.occupied_and_removed_slots_;
230 usable_slots_ = other.usable_slots_;
231 slot_mask_ = other.slot_mask_;
232 hash_ = std::move(other.hash_);
233 is_equal_ = std::move(other.is_equal_);
234 other.noexcept_reset();
254 this->add_new__impl(key, hash_(key));
258 this->add_new__impl(std::move(key), hash_(key));
273 return this->
add_as(std::move(key));
275 template<
typename ForwardKey>
bool add_as(ForwardKey &&key)
277 return this->add__impl(std::forward<ForwardKey>(key), hash_(key));
289 for (
const Key &key : keys) {
300 for (
const Key &key : keys) {
314 template<
typename ForwardKey>
bool contains_as(
const ForwardKey &key)
const
316 return this->contains__impl(key, hash_(key));
329 return this->lookup_key__impl(key, hash_(key));
340 template<
typename ForwardKey>
343 const Key *
ptr = this->lookup_key_ptr__impl(key, hash_(key));
344 if (
ptr ==
nullptr) {
360 return this->lookup_key_ptr__impl(key, hash_(key));
377 return this->lookup_key_or_add__impl(std::forward<ForwardKey>(key), hash_(key));
389 template<
typename ForwardKey>
bool remove_as(
const ForwardKey &key)
391 return this->remove__impl(key, hash_(key));
403 this->remove_contained__impl(key, hash_(key));
428 : slots_(slots), total_slots_(total_slots), current_slot_(current_slot)
434 while (++current_slot_ < total_slots_) {
435 if (slots_[current_slot_].is_occupied()) {
446 return copied_iterator;
451 return *slots_[current_slot_].key();
456 return slots_[current_slot_].key();
463 return a.current_slot_ != b.current_slot_;
474 for (
int64_t i = 0; i < slots_.size(); i++) {
475 if (slots_[i].is_occupied()) {
476 return Iterator(slots_.data(), slots_.size(), i);
484 return Iterator(slots_.data(), slots_.size(), slots_.size());
502 return this->count_collisions__impl(key, hash_(key));
520 this->realloc_and_reinsert(this->
size());
528 return occupied_and_removed_slots_ - removed_slots_;
536 return occupied_and_removed_slots_ == removed_slots_;
544 return slots_.size();
552 return removed_slots_;
569 return sizeof(Slot) * slots_.size();
578 if (usable_slots_ < n) {
579 this->realloc_and_reinsert(n);
589 if (
a.size() > b.
size()) {
593 for (
const Key &key :
a) {
612 int64_t total_slots, usable_slots;
613 max_load_factor_.compute_total_and_usable_slots(
621 if (this->
size() == 0) {
623 slots_.reinitialize(total_slots);
626 this->noexcept_reset();
630 occupied_and_removed_slots_ = 0;
631 usable_slots_ = usable_slots;
632 slot_mask_ = new_slot_mask;
637 SlotArray new_slots(total_slots);
640 for (Slot &slot : slots_) {
641 if (slot.is_occupied()) {
642 this->add_after_grow(slot, new_slots, new_slot_mask);
646 slots_ = std::move(new_slots);
649 this->noexcept_reset();
653 occupied_and_removed_slots_ -= removed_slots_;
654 usable_slots_ = usable_slots;
656 slot_mask_ = new_slot_mask;
659 void add_after_grow(Slot &old_slot, SlotArray &new_slots,
const uint64_t new_slot_mask)
664 Slot &slot = new_slots[slot_index];
665 if (slot.is_empty()) {
666 slot.occupy(std::move(*old_slot.key()),
hash);
677 void noexcept_reset() noexcept
679 Allocator allocator = slots_.allocator();
681 new (
this)
Set(NoExceptConstructor(), allocator);
684 template<
typename ForwardKey>
685 bool contains__impl(
const ForwardKey &key,
const uint64_t hash)
const
688 if (slot.is_empty()) {
691 if (slot.contains(key, is_equal_,
hash)) {
698 template<
typename ForwardKey>
699 const Key &lookup_key__impl(
const ForwardKey &key,
const uint64_t hash)
const
704 if (slot.contains(key, is_equal_,
hash)) {
711 template<
typename ForwardKey>
712 const Key *lookup_key_ptr__impl(
const ForwardKey &key,
const uint64_t hash)
const
715 if (slot.contains(key, is_equal_,
hash)) {
718 if (slot.is_empty()) {
725 template<
typename ForwardKey>
void add_new__impl(ForwardKey &&key,
const uint64_t hash)
729 this->ensure_can_add();
732 if (slot.is_empty()) {
733 slot.occupy(std::forward<ForwardKey>(key),
hash);
734 occupied_and_removed_slots_++;
741 template<
typename ForwardKey>
bool add__impl(ForwardKey &&key,
const uint64_t hash)
743 this->ensure_can_add();
746 if (slot.is_empty()) {
747 slot.occupy(std::forward<ForwardKey>(key),
hash);
748 occupied_and_removed_slots_++;
751 if (slot.contains(key, is_equal_,
hash)) {
758 template<
typename ForwardKey>
bool remove__impl(
const ForwardKey &key,
const uint64_t hash)
761 if (slot.contains(key, is_equal_,
hash)) {
766 if (slot.is_empty()) {
773 template<
typename ForwardKey>
774 void remove_contained__impl(
const ForwardKey &key,
const uint64_t hash)
779 if (slot.contains(key, is_equal_,
hash)) {
788 template<
typename ForwardKey>
789 const Key &lookup_key_or_add__impl(ForwardKey &&key,
const uint64_t hash)
791 this->ensure_can_add();
794 if (slot.contains(key, is_equal_,
hash)) {
797 if (slot.is_empty()) {
798 slot.occupy(std::forward<ForwardKey>(key),
hash);
799 occupied_and_removed_slots_++;
806 template<
typename ForwardKey>
812 if (slot.contains(key, is_equal_,
hash)) {
815 if (slot.is_empty()) {
823 void ensure_can_add()
825 if (occupied_and_removed_slots_ >= usable_slots_) {
826 this->realloc_and_reinsert(this->
size() + 1);
827 BLI_assert(occupied_and_removed_slots_ < usable_slots_);
838 using SetType = std::unordered_set<Key, blender::DefaultHash<Key>>;
844 return static_cast<int64_t>(set_.size());
863 set_.insert(std::move(key));
868 return set_.insert(key).second;
872 return set_.insert(std::move(key)).second;
877 for (
const Key &key : keys) {
884 return set_.find(key) != set_.end();
889 return (
bool)set_.erase(key);
894 return set_.erase(key);
902 typename SetType::iterator
begin()
const
907 typename SetType::iterator
end()
const
917 template<
typename Key,
920 typename Hash = DefaultHash<Key>,
921 typename IsEqual = DefaultEquality,
#define SLOT_PROBING_BEGIN(PROBING_STRATEGY, HASH, MASK, R_SLOT_INDEX)
#define SLOT_PROBING_END()
#define SET_SLOT_PROBING_END()
#define SET_SLOT_PROBING_BEGIN(HASH, R_SLOT)
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)
std::ptrdiff_t difference_type
friend bool operator!=(const Iterator &a, const Iterator &b)
const Key * operator->() const
const Key & operator*() const
std::forward_iterator_tag iterator_category
friend bool operator==(const Iterator &a, const Iterator &b)
Iterator(const Slot *slots, int64_t total_slots, int64_t current_slot)
Iterator operator++(int) const
Set(NoExceptConstructor, Allocator allocator={}) noexcept
const Key & lookup_key_or_add(Key &&key)
int64_t size_per_element() const
const Key & lookup_key_default_as(const ForwardKey &key, const Key &default_key) const
bool remove_as(const ForwardKey &key)
Set(const std::initializer_list< Key > &values)
Set & operator=(const Set &other)
int64_t size_in_bytes() const
Set & operator=(Set &&other)
Set(const Set &other)=default
void add_multiple_new(Span< Key > keys)
const Key * lookup_key_ptr(const Key &key) const
static bool Disjoint(const Set &a, const Set &b)
const Key & lookup_key(const Key &key) const
bool add_as(ForwardKey &&key)
int64_t removed_amount() const
bool contains_as(const ForwardKey &key) const
void reserve(const int64_t n)
const Key * lookup_key_ptr_as(const ForwardKey &key) const
Set(Span< Key > values, Allocator allocator={})
void remove_contained(const Key &key)
bool contains(const Key &key) const
static bool Intersects(const Set &a, const Set &b)
const Key & lookup_key_or_add_as(ForwardKey &&key)
const Key & lookup_key_or_add(const Key &key)
int64_t count_collisions(const Key &key) const
void add_multiple(Span< Key > keys)
Set(Set &&other) noexcept(std::is_nothrow_move_constructible_v< SlotArray >)
void add_new(const Key &key)
Set(Allocator allocator={}) noexcept
void remove_contained_as(const ForwardKey &key)
void print_stats(StringRef name="") const
const Key & lookup_key_default(const Key &key, const Key &default_value) const
bool remove(const Key &key)
const Key & lookup_key_as(const ForwardKey &key) const
bool remove(const Key &key)
bool contains(const Key &key) const
void remove_contained(const Key &key)
SetType::iterator begin() const
void add_multiple(Span< Key > keys)
void add_new(const Key &key)
SetType::iterator end() const
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
constexpr int64_t default_inline_buffer_capacity(size_t element_size)
unsigned __int64 uint64_t
SimpleSetSlot< Key > type