+
+ /// getLeaderValue - Return the leader for the specified value that is in the
+ /// set. It is an error to call this method for a value that is not yet in
+ /// the set. For that, call getOrInsertLeaderValue(V).
+ const ElemTy &getLeaderValue(const ElemTy &V) const {
+ member_iterator MI = findLeader(V);
+ assert(MI != member_end() && "Value is not in the set!");
+ return *MI;
+ }
+
+ /// getOrInsertLeaderValue - Return the leader for the specified value that is
+ /// in the set. If the member is not in the set, it is inserted, then
+ /// returned.
+ const ElemTy &getOrInsertLeaderValue(const ElemTy &V) const {
+ member_iterator MI = findLeader(insert(V));
+ assert(MI != member_end() && "Value is not in the set!");
+ return *MI;
+ }
+
+ /// getNumClasses - Return the number of equivalence classes in this set.
+ /// Note that this is a linear time operation.
+ unsigned getNumClasses() const {
+ unsigned NC = 0;
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (I->isLeader()) ++NC;
+ return NC;
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // Mutation methods
+
+ /// insert - Insert a new value into the union/find set, ignoring the request
+ /// if the value already exists.
+ iterator insert(const ElemTy &Data) {
+ return TheMapping.insert(Data).first;
+ }
+
+ /// findLeader - Given a value in the set, return a member iterator for the
+ /// equivalence class it is in. This does the path-compression part that
+ /// makes union-find "union findy". This returns an end iterator if the value
+ /// is not in the equivalence class.
+ ///
+ member_iterator findLeader(iterator I) const {
+ if (I == TheMapping.end()) return member_end();
+ return member_iterator(I->getLeader());
+ }
+ member_iterator findLeader(const ElemTy &V) const {
+ return findLeader(TheMapping.find(V));
+ }
+
+
+ /// union - Merge the two equivalence sets for the specified values, inserting
+ /// them if they do not already exist in the equivalence set.
+ member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) {
+ iterator V1I = insert(V1), V2I = insert(V2);
+ return unionSets(findLeader(V1I), findLeader(V2I));
+ }
+ member_iterator unionSets(member_iterator L1, member_iterator L2) {
+ assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!");
+ if (L1 == L2) return L1; // Unifying the same two sets, noop.
+
+ // Otherwise, this is a real union operation. Set the end of the L1 list to
+ // point to the L2 leader node.
+ const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node;
+ L1LV.getEndOfList()->setNext(&L2LV);
+
+ // Update L1LV's end of list pointer.
+ L1LV.Leader = L2LV.getEndOfList();
+
+ // Clear L2's leader flag:
+ L2LV.Next = L2LV.getNext();
+
+ // L2's leader is now L1.
+ L2LV.Leader = &L1LV;
+ return L1;
+ }
+
+ class member_iterator : public forward_iterator<ElemTy, ptrdiff_t> {
+ typedef forward_iterator<const ElemTy, ptrdiff_t> super;
+ const ECValue *Node;
+ friend class EquivalenceClasses;
+ public:
+ typedef size_t size_type;
+ typedef typename super::pointer pointer;
+ typedef typename super::reference reference;
+
+ explicit member_iterator() {}
+ explicit member_iterator(const ECValue *N) : Node(N) {}
+ member_iterator(const member_iterator &I) : Node(I.Node) {}
+
+ reference operator*() const {
+ assert(Node != 0 && "Dereferencing end()!");
+ return Node->getData();
+ }
+ reference operator->() const { return operator*(); }
+
+ member_iterator &operator++() {
+ assert(Node != 0 && "++'d off the end of the list!");
+ Node = Node->getNext();
+ return *this;
+ }
+
+ member_iterator operator++(int) { // postincrement operators.
+ member_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+
+ bool operator==(const member_iterator &RHS) const {
+ return Node == RHS.Node;
+ }
+ bool operator!=(const member_iterator &RHS) const {
+ return Node != RHS.Node;
+ }
+ };