Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
10 KiB

  1. //===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Generic implementation of equivalence classes through the use Tarjan's
  11. // efficient union-find algorithm.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_ADT_EQUIVALENCECLASSES_H
  15. #define LLVM_ADT_EQUIVALENCECLASSES_H
  16. #include "llvm/Support/DataTypes.h"
  17. #include <cassert>
  18. #include <set>
  19. namespace llvm {
  20. /// EquivalenceClasses - This represents a collection of equivalence classes and
  21. /// supports three efficient operations: insert an element into a class of its
  22. /// own, union two classes, and find the class for a given element. In
  23. /// addition to these modification methods, it is possible to iterate over all
  24. /// of the equivalence classes and all of the elements in a class.
  25. ///
  26. /// This implementation is an efficient implementation that only stores one copy
  27. /// of the element being indexed per entry in the set, and allows any arbitrary
  28. /// type to be indexed (as long as it can be ordered with operator<).
  29. ///
  30. /// Here is a simple example using integers:
  31. ///
  32. /// \code
  33. /// EquivalenceClasses<int> EC;
  34. /// EC.unionSets(1, 2); // insert 1, 2 into the same set
  35. /// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets
  36. /// EC.unionSets(5, 1); // merge the set for 1 with 5's set.
  37. ///
  38. /// for (EquivalenceClasses<int>::iterator I = EC.begin(), E = EC.end();
  39. /// I != E; ++I) { // Iterate over all of the equivalence sets.
  40. /// if (!I->isLeader()) continue; // Ignore non-leader sets.
  41. /// for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I);
  42. /// MI != EC.member_end(); ++MI) // Loop over members in this set.
  43. /// cerr << *MI << " "; // Print member.
  44. /// cerr << "\n"; // Finish set.
  45. /// }
  46. /// \endcode
  47. ///
  48. /// This example prints:
  49. /// 4
  50. /// 5 1 2
  51. ///
  52. template <class ElemTy>
  53. class EquivalenceClasses {
  54. /// ECValue - The EquivalenceClasses data structure is just a set of these.
  55. /// Each of these represents a relation for a value. First it stores the
  56. /// value itself, which provides the ordering that the set queries. Next, it
  57. /// provides a "next pointer", which is used to enumerate all of the elements
  58. /// in the unioned set. Finally, it defines either a "end of list pointer" or
  59. /// "leader pointer" depending on whether the value itself is a leader. A
  60. /// "leader pointer" points to the node that is the leader for this element,
  61. /// if the node is not a leader. A "end of list pointer" points to the last
  62. /// node in the list of members of this list. Whether or not a node is a
  63. /// leader is determined by a bit stolen from one of the pointers.
  64. class ECValue {
  65. friend class EquivalenceClasses;
  66. mutable const ECValue *Leader, *Next;
  67. ElemTy Data;
  68. // ECValue ctor - Start out with EndOfList pointing to this node, Next is
  69. // Null, isLeader = true.
  70. ECValue(const ElemTy &Elt)
  71. : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {}
  72. const ECValue *getLeader() const {
  73. if (isLeader()) return this;
  74. if (Leader->isLeader()) return Leader;
  75. // Path compression.
  76. return Leader = Leader->getLeader();
  77. }
  78. const ECValue *getEndOfList() const {
  79. assert(isLeader() && "Cannot get the end of a list for a non-leader!");
  80. return Leader;
  81. }
  82. void setNext(const ECValue *NewNext) const {
  83. assert(getNext() == 0 && "Already has a next pointer!");
  84. Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader());
  85. }
  86. public:
  87. ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1),
  88. Data(RHS.Data) {
  89. // Only support copying of singleton nodes.
  90. assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!");
  91. }
  92. bool operator<(const ECValue &UFN) const { return Data < UFN.Data; }
  93. bool isLeader() const { return (intptr_t)Next & 1; }
  94. const ElemTy &getData() const { return Data; }
  95. const ECValue *getNext() const {
  96. return (ECValue*)((intptr_t)Next & ~(intptr_t)1);
  97. }
  98. template<typename T>
  99. bool operator<(const T &Val) const { return Data < Val; }
  100. };
  101. /// TheMapping - This implicitly provides a mapping from ElemTy values to the
  102. /// ECValues, it just keeps the key as part of the value.
  103. std::set<ECValue> TheMapping;
  104. public:
  105. EquivalenceClasses() {}
  106. EquivalenceClasses(const EquivalenceClasses &RHS) {
  107. operator=(RHS);
  108. }
  109. const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) {
  110. TheMapping.clear();
  111. for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I)
  112. if (I->isLeader()) {
  113. member_iterator MI = RHS.member_begin(I);
  114. member_iterator LeaderIt = member_begin(insert(*MI));
  115. for (++MI; MI != member_end(); ++MI)
  116. unionSets(LeaderIt, member_begin(insert(*MI)));
  117. }
  118. return *this;
  119. }
  120. //===--------------------------------------------------------------------===//
  121. // Inspection methods
  122. //
  123. /// iterator* - Provides a way to iterate over all values in the set.
  124. typedef typename std::set<ECValue>::const_iterator iterator;
  125. iterator begin() const { return TheMapping.begin(); }
  126. iterator end() const { return TheMapping.end(); }
  127. bool empty() const { return TheMapping.empty(); }
  128. /// member_* Iterate over the members of an equivalence class.
  129. ///
  130. class member_iterator;
  131. member_iterator member_begin(iterator I) const {
  132. // Only leaders provide anything to iterate over.
  133. return member_iterator(I->isLeader() ? &*I : 0);
  134. }
  135. member_iterator member_end() const {
  136. return member_iterator(0);
  137. }
  138. /// findValue - Return an iterator to the specified value. If it does not
  139. /// exist, end() is returned.
  140. iterator findValue(const ElemTy &V) const {
  141. return TheMapping.find(V);
  142. }
  143. /// getLeaderValue - Return the leader for the specified value that is in the
  144. /// set. It is an error to call this method for a value that is not yet in
  145. /// the set. For that, call getOrInsertLeaderValue(V).
  146. const ElemTy &getLeaderValue(const ElemTy &V) const {
  147. member_iterator MI = findLeader(V);
  148. assert(MI != member_end() && "Value is not in the set!");
  149. return *MI;
  150. }
  151. /// getOrInsertLeaderValue - Return the leader for the specified value that is
  152. /// in the set. If the member is not in the set, it is inserted, then
  153. /// returned.
  154. const ElemTy &getOrInsertLeaderValue(const ElemTy &V) {
  155. member_iterator MI = findLeader(insert(V));
  156. assert(MI != member_end() && "Value is not in the set!");
  157. return *MI;
  158. }
  159. /// getNumClasses - Return the number of equivalence classes in this set.
  160. /// Note that this is a linear time operation.
  161. unsigned getNumClasses() const {
  162. unsigned NC = 0;
  163. for (iterator I = begin(), E = end(); I != E; ++I)
  164. if (I->isLeader()) ++NC;
  165. return NC;
  166. }
  167. //===--------------------------------------------------------------------===//
  168. // Mutation methods
  169. /// insert - Insert a new value into the union/find set, ignoring the request
  170. /// if the value already exists.
  171. iterator insert(const ElemTy &Data) {
  172. return TheMapping.insert(ECValue(Data)).first;
  173. }
  174. /// findLeader - Given a value in the set, return a member iterator for the
  175. /// equivalence class it is in. This does the path-compression part that
  176. /// makes union-find "union findy". This returns an end iterator if the value
  177. /// is not in the equivalence class.
  178. ///
  179. member_iterator findLeader(iterator I) const {
  180. if (I == TheMapping.end()) return member_end();
  181. return member_iterator(I->getLeader());
  182. }
  183. member_iterator findLeader(const ElemTy &V) const {
  184. return findLeader(TheMapping.find(V));
  185. }
  186. /// union - Merge the two equivalence sets for the specified values, inserting
  187. /// them if they do not already exist in the equivalence set.
  188. member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) {
  189. iterator V1I = insert(V1), V2I = insert(V2);
  190. return unionSets(findLeader(V1I), findLeader(V2I));
  191. }
  192. member_iterator unionSets(member_iterator L1, member_iterator L2) {
  193. assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!");
  194. if (L1 == L2) return L1; // Unifying the same two sets, noop.
  195. // Otherwise, this is a real union operation. Set the end of the L1 list to
  196. // point to the L2 leader node.
  197. const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node;
  198. L1LV.getEndOfList()->setNext(&L2LV);
  199. // Update L1LV's end of list pointer.
  200. L1LV.Leader = L2LV.getEndOfList();
  201. // Clear L2's leader flag:
  202. L2LV.Next = L2LV.getNext();
  203. // L2's leader is now L1.
  204. L2LV.Leader = &L1LV;
  205. return L1;
  206. }
  207. class member_iterator : public std::iterator<std::forward_iterator_tag,
  208. const ElemTy, ptrdiff_t> {
  209. typedef std::iterator<std::forward_iterator_tag,
  210. const ElemTy, ptrdiff_t> super;
  211. const ECValue *Node;
  212. friend class EquivalenceClasses;
  213. public:
  214. typedef size_t size_type;
  215. typedef typename super::pointer pointer;
  216. typedef typename super::reference reference;
  217. explicit member_iterator() {}
  218. explicit member_iterator(const ECValue *N) : Node(N) {}
  219. member_iterator(const member_iterator &I) : Node(I.Node) {}
  220. reference operator*() const {
  221. assert(Node != 0 && "Dereferencing end()!");
  222. return Node->getData();
  223. }
  224. reference operator->() const { return operator*(); }
  225. member_iterator &operator++() {
  226. assert(Node != 0 && "++'d off the end of the list!");
  227. Node = Node->getNext();
  228. return *this;
  229. }
  230. member_iterator operator++(int) { // postincrement operators.
  231. member_iterator tmp = *this;
  232. ++*this;
  233. return tmp;
  234. }
  235. bool operator==(const member_iterator &RHS) const {
  236. return Node == RHS.Node;
  237. }
  238. bool operator!=(const member_iterator &RHS) const {
  239. return Node != RHS.Node;
  240. }
  241. };
  242. };
  243. } // End llvm namespace
  244. #endif