[Bf-blender-cvs] [7041568ff92] master: BLI: improve VectorSet data structure

Jacques Lucke noreply at git.blender.org
Fri Apr 30 11:09:28 CEST 2021


Commit: 7041568ff922318f462b06e1c833cc9287aaa04b
Author: Jacques Lucke
Date:   Fri Apr 30 11:09:19 2021 +0200
Branches: master
https://developer.blender.org/rB7041568ff922318f462b06e1c833cc9287aaa04b

BLI: improve VectorSet data structure

This adds two new methods:
* `clear` just removes all keys from the vector set.
* `index_of_or_add` returns the index of a key and adds it if has not
  been added before.

===================================================================

M	source/blender/blenlib/BLI_vector_set.hh
M	source/blender/blenlib/tests/BLI_vector_set_test.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_vector_set.hh b/source/blender/blenlib/BLI_vector_set.hh
index 14b38d564cb..2f5d04aefa2 100644
--- a/source/blender/blenlib/BLI_vector_set.hh
+++ b/source/blender/blenlib/BLI_vector_set.hh
@@ -397,6 +397,23 @@ class VectorSet {
     return this->index_of_try__impl(key, hash_(key));
   }
 
+  /**
+   * Return the index of the key in the vector. If the key is not in the set, add it and return its
+   * index.
+   */
+  int64_t index_of_or_add(const Key &key)
+  {
+    return this->index_of_or_add_as(key);
+  }
+  int64_t index_of_or_add(Key &&key)
+  {
+    return this->index_of_or_add_as(std::move(key));
+  }
+  template<typename ForwardKey> int64_t index_of_or_add_as(ForwardKey &&key)
+  {
+    return this->index_of_or_add__impl(std::forward<ForwardKey>(key), hash_(key));
+  }
+
   /**
    * Get a pointer to the beginning of the array containing all keys.
    */
@@ -483,6 +500,14 @@ class VectorSet {
     }
   }
 
+  /**
+   * Remove all keys from the vector set.
+   */
+  void clear()
+  {
+    this->noexcept_reset();
+  }
+
   /**
    * Get the number of collisions that the probing strategy has to go through to find the key or
    * determine that it is not in the set.
@@ -652,6 +677,26 @@ class VectorSet {
     VECTOR_SET_SLOT_PROBING_END();
   }
 
+  template<typename ForwardKey>
+  int64_t index_of_or_add__impl(ForwardKey &&key, const uint64_t hash)
+  {
+    this->ensure_can_add();
+
+    VECTOR_SET_SLOT_PROBING_BEGIN (hash, slot) {
+      if (slot.contains(key, is_equal_, hash, keys_)) {
+        return slot.index();
+      }
+      if (slot.is_empty()) {
+        const int64_t index = this->size();
+        new (keys_ + index) Key(std::forward<ForwardKey>(key));
+        slot.occupy(index, hash);
+        occupied_and_removed_slots_++;
+        return index;
+      }
+    }
+    VECTOR_SET_SLOT_PROBING_END();
+  }
+
   Key pop__impl()
   {
     BLI_assert(this->size() > 0);
diff --git a/source/blender/blenlib/tests/BLI_vector_set_test.cc b/source/blender/blenlib/tests/BLI_vector_set_test.cc
index bbbe96f9b7e..c535ac57774 100644
--- a/source/blender/blenlib/tests/BLI_vector_set_test.cc
+++ b/source/blender/blenlib/tests/BLI_vector_set_test.cc
@@ -232,4 +232,30 @@ TEST(vector_set, PopExceptions)
   EXPECT_EQ(set.size(), 4);
 }
 
+TEST(vector_set, IndexOfOrAdd)
+{
+  VectorSet<int> set;
+  EXPECT_EQ(set.index_of_or_add(3), 0);
+  EXPECT_EQ(set.index_of_or_add(3), 0);
+  EXPECT_EQ(set.index_of_or_add(2), 1);
+  EXPECT_EQ(set.index_of_or_add(0), 2);
+  EXPECT_EQ(set.index_of_or_add(2), 1);
+  EXPECT_EQ(set.index_of_or_add(3), 0);
+  EXPECT_EQ(set.index_of_or_add(5), 3);
+  EXPECT_EQ(set.index_of_or_add(8), 4);
+  EXPECT_EQ(set.index_of_or_add(5), 3);
+}
+
+TEST(vector_set, Clear)
+{
+  VectorSet<int> set = {4, 6, 2, 4};
+  EXPECT_EQ(set.size(), 3);
+  set.clear();
+  EXPECT_EQ(set.size(), 0);
+  set.add_multiple({4, 1, 6, 8, 3, 6, 9, 3});
+  EXPECT_EQ(set.size(), 6);
+  set.clear();
+  EXPECT_EQ(set.size(), 0);
+}
+
 }  // namespace blender::tests



More information about the Bf-blender-cvs mailing list