diff options
author | Thomas Lively <tlively@google.com> | 2024-08-01 15:08:25 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-01 12:08:25 -0700 |
commit | 2a7c0931edf681076e678a0e8092e170333c6e86 (patch) | |
tree | af60ec405b6d6d2a38b1b05466120cebcde45249 /src/support/disjoint_sets.h | |
parent | 705c28d3a33d606c8c938d079dbf82de7e7a6b7d (diff) | |
download | binaryen-2a7c0931edf681076e678a0e8092e170333c6e86.tar.gz binaryen-2a7c0931edf681076e678a0e8092e170333c6e86.tar.bz2 binaryen-2a7c0931edf681076e678a0e8092e170333c6e86.zip |
Add a disjoint sets (union-find) utility (#6797)
This will be used in an upcoming type optimization pass and may be
generally useful.
Diffstat (limited to 'src/support/disjoint_sets.h')
-rw-r--r-- | src/support/disjoint_sets.h | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/support/disjoint_sets.h b/src/support/disjoint_sets.h new file mode 100644 index 000000000..198e5cb67 --- /dev/null +++ b/src/support/disjoint_sets.h @@ -0,0 +1,87 @@ +/* + * Copyright 2024 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_support_disjoint_sets_h +#define wasm_support_disjoint_sets_h + +#include <cassert> +#include <cstddef> +#include <vector> + +namespace wasm { + +// A disjoint set forest (a.k.a. union-find) implementation. See +// https://en.wikipedia.org/wiki/Disjoint-set_data_structure. +struct DisjointSets { + struct ElemInfo { + // The index of the parent element, or the index of the element itself if it + // has no parent. + size_t parent; + // An upper bound on the height of the tree rooted at this element. + size_t rank; + }; + std::vector<ElemInfo> info; + + // Add an element and return its index. + size_t addSet() { + size_t ret = info.size(); + info.push_back({ret, 0}); + return ret; + } + + // Get the representative element of the set to which `elem` belongs. + size_t getRoot(size_t elem) { + assert(elem < info.size()); + size_t root = elem; + // Follow parent pointers up to the root. + for (; info[root].parent != root; root = info[root].parent) { + } + // Compress the path to make subsequent getRoots of this set faster. + while (elem != root) { + size_t parent = info[elem].parent; + info[elem].parent = root; + elem = parent; + } + return root; + } + + // Join the sets to which the elements belong and return the representative + // element of the union. + size_t getUnion(size_t elem1, size_t elem2) { + assert(elem1 < info.size() && elem2 < info.size()); + size_t root1 = getRoot(elem1); + size_t root2 = getRoot(elem2); + if (root1 == root2) { + // Already in the same set. + return root1; + } + // Canonicalize so that root1 has the greater rank. + if (info[root1].rank < info[root2].rank) { + std::swap(root1, root2); + } + // Merge the trees, smaller into larger. + info[root2].parent = root1; + // If the ranks were equal, the new root has a larger rank. + if (info[root1].rank == info[root2].rank) { + ++info[root1].rank; + } + return root1; + } +}; + +} // namespace wasm + +#endif // wasm_support_disjoint_sets_h |