EquivalenceClasses.h revision 551ccae044b0ff658fe629dd67edd5ffe75d10e8
1//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Generic implementation of equivalence classes and implementation of 11// union-find algorithms A not-so-fancy implementation: 2 level tree i.e root 12// and one more level Overhead of a union = size of the equivalence class being 13// attached Overhead of a find = 1. 14// 15//===----------------------------------------------------------------------===// 16 17#ifndef LLVM_ADT_EQUIVALENCECLASSES_H 18#define LLVM_ADT_EQUIVALENCECLASSES_H 19 20#include <map> 21#include <set> 22#include <vector> 23 24namespace llvm { 25 26template <class ElemTy> 27class EquivalenceClasses { 28 // Maps each element to the element that is the leader of its 29 // equivalence class. 30 std::map<ElemTy, ElemTy> Elem2LeaderMap; 31 32 // Maintains the set of leaders 33 std::set<ElemTy> LeaderSet; 34 35 // Caches the equivalence class for each leader 36 std::map<ElemTy, std::set<ElemTy> > LeaderToEqClassMap; 37 38 // Make Element2 the leader of the union of classes Element1 and Element2 39 // Element1 and Element2 are presumed to be leaders of their respective 40 // equivalence classes. 41 void attach(ElemTy Element1, ElemTy Element2) { 42 for (typename std::map<ElemTy, ElemTy>::iterator ElemI = 43 Elem2LeaderMap.begin(), ElemE = Elem2LeaderMap.end(); 44 ElemI != ElemE; ++ElemI) { 45 if (ElemI->second == Element1) 46 Elem2LeaderMap[ElemI->first] = Element2; 47 } 48 } 49 50public: 51 // If an element has not yet in any class, make it a separate new class. 52 // Return the leader of the class containing the element. 53 ElemTy addElement (ElemTy NewElement) { 54 typename std::map<ElemTy, ElemTy>::iterator ElemI = 55 Elem2LeaderMap.find(NewElement); 56 if (ElemI == Elem2LeaderMap.end()) { 57 Elem2LeaderMap[NewElement] = NewElement; 58 LeaderSet.insert(NewElement); 59 return NewElement; 60 } 61 else 62 return ElemI->second; 63 } 64 65 ElemTy findClass(ElemTy Element) const { 66 typename std::map<ElemTy, ElemTy>::const_iterator I = 67 Elem2LeaderMap.find(Element); 68 return (I == Elem2LeaderMap.end())? (ElemTy) 0 : I->second; 69 } 70 71 /// Attach the set with Element1 to the set with Element2 adding Element1 and 72 /// Element2 to the set of equivalence classes if they are not there already. 73 /// Implication: Make Element1 the element in the smaller set. 74 /// Take Leader[Element1] out of the set of leaders. 75 void unionSetsWith(ElemTy Element1, ElemTy Element2) { 76 // If either Element1 or Element2 does not already exist, include it 77 const ElemTy& leader1 = addElement(Element1); 78 const ElemTy& leader2 = addElement(Element2); 79 assert(leader1 != (ElemTy) 0 && leader2 != (ElemTy) 0); 80 if (leader1 != leader2) { 81 attach(leader1, leader2); 82 LeaderSet.erase(leader1); 83 } 84 } 85 86 // Returns a vector containing all the elements in the equivalence class 87 // including Element1 88 const std::set<ElemTy> & getEqClass(ElemTy Element1) { 89 assert(Elem2LeaderMap.find(Element1) != Elem2LeaderMap.end()); 90 const ElemTy classLeader = Elem2LeaderMap[Element1]; 91 92 std::set<ElemTy> & EqClass = LeaderToEqClassMap[classLeader]; 93 94 // If the EqClass vector is empty, it has not been computed yet: do it now 95 if (EqClass.empty()) { 96 for (typename std::map<ElemTy, ElemTy>::iterator 97 ElemI = Elem2LeaderMap.begin(), ElemE = Elem2LeaderMap.end(); 98 ElemI != ElemE; ++ElemI) 99 if (ElemI->second == classLeader) 100 EqClass.insert(ElemI->first); 101 assert(! EqClass.empty()); // must at least include the leader 102 } 103 104 return EqClass; 105 } 106 107 std::set<ElemTy>& getLeaderSet() { return LeaderSet; } 108 const std::set<ElemTy>& getLeaderSet() const { return LeaderSet; } 109 110 std::map<ElemTy, ElemTy>& getLeaderMap() { return Elem2LeaderMap;} 111 const std::map<ElemTy, ElemTy>& getLeaderMap() const { return Elem2LeaderMap;} 112}; 113 114} // End llvm namespace 115 116#endif 117