DenseSet.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/ADT/DenseSet.h - Dense probed hash table ------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. ///
  14. /// \file
  15. /// This file defines the DenseSet and SmallDenseSet classes.
  16. ///
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_ADT_DENSESET_H
  19. #define LLVM_ADT_DENSESET_H
  20. #include "llvm/ADT/DenseMap.h"
  21. #include "llvm/ADT/DenseMapInfo.h"
  22. #include "llvm/Support/MathExtras.h"
  23. #include "llvm/Support/type_traits.h"
  24. #include <cstddef>
  25. #include <initializer_list>
  26. #include <iterator>
  27. #include <utility>
  28. namespace llvm {
  29. namespace detail {
  30. struct DenseSetEmpty {};
  31. // Use the empty base class trick so we can create a DenseMap where the buckets
  32. // contain only a single item.
  33. template <typename KeyT> class DenseSetPair : public DenseSetEmpty {
  34. KeyT key;
  35. public:
  36. KeyT &getFirst() { return key; }
  37. const KeyT &getFirst() const { return key; }
  38. DenseSetEmpty &getSecond() { return *this; }
  39. const DenseSetEmpty &getSecond() const { return *this; }
  40. };
  41. /// Base class for DenseSet and DenseSmallSet.
  42. ///
  43. /// MapTy should be either
  44. ///
  45. /// DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
  46. /// detail::DenseSetPair<ValueT>>
  47. ///
  48. /// or the equivalent SmallDenseMap type. ValueInfoT must implement the
  49. /// DenseMapInfo "concept".
  50. template <typename ValueT, typename MapTy, typename ValueInfoT>
  51. class DenseSetImpl {
  52. static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
  53. "DenseMap buckets unexpectedly large!");
  54. MapTy TheMap;
  55. template <typename T>
  56. using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
  57. public:
  58. using key_type = ValueT;
  59. using value_type = ValueT;
  60. using size_type = unsigned;
  61. explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
  62. template <typename InputIt>
  63. DenseSetImpl(const InputIt &I, const InputIt &E)
  64. : DenseSetImpl(PowerOf2Ceil(std::distance(I, E))) {
  65. insert(I, E);
  66. }
  67. DenseSetImpl(std::initializer_list<ValueT> Elems)
  68. : DenseSetImpl(PowerOf2Ceil(Elems.size())) {
  69. insert(Elems.begin(), Elems.end());
  70. }
  71. bool empty() const { return TheMap.empty(); }
  72. size_type size() const { return TheMap.size(); }
  73. size_t getMemorySize() const { return TheMap.getMemorySize(); }
  74. /// Grow the DenseSet so that it has at least Size buckets. Will not shrink
  75. /// the Size of the set.
  76. void resize(size_t Size) { TheMap.resize(Size); }
  77. /// Grow the DenseSet so that it can contain at least \p NumEntries items
  78. /// before resizing again.
  79. void reserve(size_t Size) { TheMap.reserve(Size); }
  80. void clear() {
  81. TheMap.clear();
  82. }
  83. /// Return 1 if the specified key is in the set, 0 otherwise.
  84. size_type count(const_arg_type_t<ValueT> V) const {
  85. return TheMap.count(V);
  86. }
  87. bool erase(const ValueT &V) {
  88. return TheMap.erase(V);
  89. }
  90. void swap(DenseSetImpl &RHS) { TheMap.swap(RHS.TheMap); }
  91. // Iterators.
  92. class ConstIterator;
  93. class Iterator {
  94. typename MapTy::iterator I;
  95. friend class DenseSetImpl;
  96. friend class ConstIterator;
  97. public:
  98. using difference_type = typename MapTy::iterator::difference_type;
  99. using value_type = ValueT;
  100. using pointer = value_type *;
  101. using reference = value_type &;
  102. using iterator_category = std::forward_iterator_tag;
  103. Iterator() = default;
  104. Iterator(const typename MapTy::iterator &i) : I(i) {}
  105. ValueT &operator*() { return I->getFirst(); }
  106. const ValueT &operator*() const { return I->getFirst(); }
  107. ValueT *operator->() { return &I->getFirst(); }
  108. const ValueT *operator->() const { return &I->getFirst(); }
  109. Iterator& operator++() { ++I; return *this; }
  110. Iterator operator++(int) { auto T = *this; ++I; return T; }
  111. friend bool operator==(const Iterator &X, const Iterator &Y) {
  112. return X.I == Y.I;
  113. }
  114. friend bool operator!=(const Iterator &X, const Iterator &Y) {
  115. return X.I != Y.I;
  116. }
  117. };
  118. class ConstIterator {
  119. typename MapTy::const_iterator I;
  120. friend class DenseSetImpl;
  121. friend class Iterator;
  122. public:
  123. using difference_type = typename MapTy::const_iterator::difference_type;
  124. using value_type = ValueT;
  125. using pointer = const value_type *;
  126. using reference = const value_type &;
  127. using iterator_category = std::forward_iterator_tag;
  128. ConstIterator() = default;
  129. ConstIterator(const Iterator &B) : I(B.I) {}
  130. ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
  131. const ValueT &operator*() const { return I->getFirst(); }
  132. const ValueT *operator->() const { return &I->getFirst(); }
  133. ConstIterator& operator++() { ++I; return *this; }
  134. ConstIterator operator++(int) { auto T = *this; ++I; return T; }
  135. friend bool operator==(const ConstIterator &X, const ConstIterator &Y) {
  136. return X.I == Y.I;
  137. }
  138. friend bool operator!=(const ConstIterator &X, const ConstIterator &Y) {
  139. return X.I != Y.I;
  140. }
  141. };
  142. using iterator = Iterator;
  143. using const_iterator = ConstIterator;
  144. iterator begin() { return Iterator(TheMap.begin()); }
  145. iterator end() { return Iterator(TheMap.end()); }
  146. const_iterator begin() const { return ConstIterator(TheMap.begin()); }
  147. const_iterator end() const { return ConstIterator(TheMap.end()); }
  148. iterator find(const_arg_type_t<ValueT> V) { return Iterator(TheMap.find(V)); }
  149. const_iterator find(const_arg_type_t<ValueT> V) const {
  150. return ConstIterator(TheMap.find(V));
  151. }
  152. /// Check if the set contains the given element.
  153. bool contains(const_arg_type_t<ValueT> V) const {
  154. return TheMap.find(V) != TheMap.end();
  155. }
  156. /// Alternative version of find() which allows a different, and possibly less
  157. /// expensive, key type.
  158. /// The DenseMapInfo is responsible for supplying methods
  159. /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type
  160. /// used.
  161. template <class LookupKeyT>
  162. iterator find_as(const LookupKeyT &Val) {
  163. return Iterator(TheMap.find_as(Val));
  164. }
  165. template <class LookupKeyT>
  166. const_iterator find_as(const LookupKeyT &Val) const {
  167. return ConstIterator(TheMap.find_as(Val));
  168. }
  169. void erase(Iterator I) { return TheMap.erase(I.I); }
  170. void erase(ConstIterator CI) { return TheMap.erase(CI.I); }
  171. std::pair<iterator, bool> insert(const ValueT &V) {
  172. detail::DenseSetEmpty Empty;
  173. return TheMap.try_emplace(V, Empty);
  174. }
  175. std::pair<iterator, bool> insert(ValueT &&V) {
  176. detail::DenseSetEmpty Empty;
  177. return TheMap.try_emplace(std::move(V), Empty);
  178. }
  179. /// Alternative version of insert that uses a different (and possibly less
  180. /// expensive) key type.
  181. template <typename LookupKeyT>
  182. std::pair<iterator, bool> insert_as(const ValueT &V,
  183. const LookupKeyT &LookupKey) {
  184. return TheMap.insert_as({V, detail::DenseSetEmpty()}, LookupKey);
  185. }
  186. template <typename LookupKeyT>
  187. std::pair<iterator, bool> insert_as(ValueT &&V, const LookupKeyT &LookupKey) {
  188. return TheMap.insert_as({std::move(V), detail::DenseSetEmpty()}, LookupKey);
  189. }
  190. // Range insertion of values.
  191. template<typename InputIt>
  192. void insert(InputIt I, InputIt E) {
  193. for (; I != E; ++I)
  194. insert(*I);
  195. }
  196. };
  197. /// Equality comparison for DenseSet.
  198. ///
  199. /// Iterates over elements of LHS confirming that each element is also a member
  200. /// of RHS, and that RHS contains no additional values.
  201. /// Equivalent to N calls to RHS.count. Amortized complexity is linear, worst
  202. /// case is O(N^2) (if every hash collides).
  203. template <typename ValueT, typename MapTy, typename ValueInfoT>
  204. bool operator==(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
  205. const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
  206. if (LHS.size() != RHS.size())
  207. return false;
  208. for (auto &E : LHS)
  209. if (!RHS.count(E))
  210. return false;
  211. return true;
  212. }
  213. /// Inequality comparison for DenseSet.
  214. ///
  215. /// Equivalent to !(LHS == RHS). See operator== for performance notes.
  216. template <typename ValueT, typename MapTy, typename ValueInfoT>
  217. bool operator!=(const DenseSetImpl<ValueT, MapTy, ValueInfoT> &LHS,
  218. const DenseSetImpl<ValueT, MapTy, ValueInfoT> &RHS) {
  219. return !(LHS == RHS);
  220. }
  221. } // end namespace detail
  222. /// Implements a dense probed hash-table based set.
  223. template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
  224. class DenseSet : public detail::DenseSetImpl<
  225. ValueT, DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
  226. detail::DenseSetPair<ValueT>>,
  227. ValueInfoT> {
  228. using BaseT =
  229. detail::DenseSetImpl<ValueT,
  230. DenseMap<ValueT, detail::DenseSetEmpty, ValueInfoT,
  231. detail::DenseSetPair<ValueT>>,
  232. ValueInfoT>;
  233. public:
  234. using BaseT::BaseT;
  235. };
  236. /// Implements a dense probed hash-table based set with some number of buckets
  237. /// stored inline.
  238. template <typename ValueT, unsigned InlineBuckets = 4,
  239. typename ValueInfoT = DenseMapInfo<ValueT>>
  240. class SmallDenseSet
  241. : public detail::DenseSetImpl<
  242. ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
  243. ValueInfoT, detail::DenseSetPair<ValueT>>,
  244. ValueInfoT> {
  245. using BaseT = detail::DenseSetImpl<
  246. ValueT, SmallDenseMap<ValueT, detail::DenseSetEmpty, InlineBuckets,
  247. ValueInfoT, detail::DenseSetPair<ValueT>>,
  248. ValueInfoT>;
  249. public:
  250. using BaseT::BaseT;
  251. };
  252. } // end namespace llvm
  253. #endif // LLVM_ADT_DENSESET_H
  254. #ifdef __GNUC__
  255. #pragma GCC diagnostic pop
  256. #endif