Jlm
HashSet.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2022 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_UTIL_HASHSET_HPP
7 #define JLM_UTIL_HASHSET_HPP
8 
9 #include <jlm/util/Hash.hpp>
11 
12 #include <unordered_set>
13 
14 namespace jlm::util
15 {
16 
22 template<typename ItemType, typename HashFunctor = Hash<ItemType>>
23 class HashSet
24 {
25  using InternalSet = std::unordered_set<ItemType, HashFunctor>;
26 
27 public:
28  class ItemConstIterator final
29  {
30  public:
31  using iterator_category = std::forward_iterator_tag;
32  using value_type = ItemType;
33  using difference_type = std::ptrdiff_t;
34  using pointer = ItemType *;
35  using reference = ItemType &;
36 
37  private:
38  friend HashSet;
39 
40  explicit ItemConstIterator(const typename InternalSet::const_iterator & it)
41  : It_(it)
42  {}
43 
44  public:
45  [[nodiscard]] ItemType *
46  Item() const noexcept
47  {
48  return It_.operator->();
49  }
50 
51  const ItemType &
52  operator*() const
53  {
54  return It_.operator*();
55  }
56 
57  ItemType *
58  operator->() const
59  {
60  return Item();
61  }
62 
65  {
66  ++It_;
67  return *this;
68  }
69 
72  {
73  ItemConstIterator tmp = *this;
74  ++*this;
75  return tmp;
76  }
77 
78  bool
79  operator==(const ItemConstIterator & other) const
80  {
81  return It_ == other.It_;
82  }
83 
84  bool
85  operator!=(const ItemConstIterator & other) const
86  {
87  return !operator==(other);
88  }
89 
90  private:
91  typename InternalSet::const_iterator It_;
92  };
93 
94  ~HashSet() noexcept = default;
95 
96  HashSet() = default;
97 
98  template<class InputIt>
99  HashSet(InputIt begin, InputIt end)
100  : Set_(begin, end)
101  {}
102 
103  HashSet(const HashSet & other)
104  : Set_(other.Set_)
105  {}
106 
107  HashSet(HashSet && other) noexcept
108  : Set_(std::move(other.Set_))
109  {}
110 
111  HashSet(std::initializer_list<ItemType> initializerList)
112  : Set_(initializerList)
113  {}
114 
115  template<typename OtherHashFunctor>
116  explicit HashSet(const std::unordered_set<ItemType, OtherHashFunctor> & other)
117  : Set_(other.begin(), other.end())
118  {}
119 
120  HashSet &
121  operator=(const HashSet & other)
122  {
123  Set_ = other.Set_;
124  return *this;
125  }
126 
127  HashSet &
128  operator=(HashSet && other) noexcept
129  {
130  Set_ = std::move(other.Set_);
131  return *this;
132  }
133 
137  void
138  Clear() noexcept
139  {
140  Set_.clear();
141  }
142 
149  bool
150  Contains(const ItemType & item) const noexcept
151  {
152  return Set_.find(item) != Set_.end();
153  }
154 
162  bool
163  IsSubsetOf(const HashSet<ItemType> & other) const noexcept
164  {
165  if (Size() > other.Size())
166  {
167  return false;
168  }
169 
170  for (auto & item : other.Items())
171  {
172  if (!other.Contains(item))
173  {
174  return false;
175  }
176  }
177 
178  return true;
179  }
180 
186  [[nodiscard]] std::size_t
187  Size() const noexcept
188  {
189  return Set_.size();
190  }
191 
197  [[nodiscard]] bool
198  IsEmpty() const noexcept
199  {
200  return Size() == 0;
201  }
202 
209  bool
210  insert(ItemType item)
211  {
212  auto size = Size();
213  Set_.emplace(std::move(item));
214  return (size != Size());
215  }
216 
223  Items() const noexcept
224  {
225  return { ItemConstIterator(Set_.begin()), ItemConstIterator(Set_.end()) };
226  }
227 
235  bool
237  {
238  const size_t sizeBefore = Size();
239  for (auto & item : other.Items())
240  insert(item);
241  return sizeBefore != Size();
242  }
243 
251  bool
253  {
254  // Make *this the largest of the two sets, to make the union cheaper
255  if (Size() < other.Size())
256  std::swap(*this, other);
257 
258  bool result = UnionWith(other);
259  other.Clear();
260  return result;
261  }
262 
268  void
270  {
271  auto isContained = [&](const ItemType & item)
272  {
273  return !other.Contains(item);
274  };
275 
276  RemoveWhere(isContained);
277  }
278 
285  void
287  {
288  // Make *this the smallest of the two sets, to make the intersection cheaper
289  if (Size() > other.Size())
290  std::swap(*this, other);
291 
292  IntersectWith(other);
293  other.Clear();
294  }
295 
301  void
303  {
304  // If this HashSet is smaller, loop over it and remove elements in other.
305  // If other is smaller, loop over it and remove elements from this.
306 
307  if (Size() <= other.Size())
308  {
309  // This branch also handles the unlikely case where this and other are the same set.
310 
311  auto isInOther = [&](const ItemType & item)
312  {
313  return other.Contains(item);
314  };
315 
316  RemoveWhere(isInOther);
317  }
318  else
319  {
320  for (auto & item : other.Set_)
321  Remove(item);
322  }
323  }
324 
331  bool
332  Remove(ItemType item)
333  {
334  return Set_.erase(item) != 0;
335  }
336 
345  template<typename F>
346  size_t
347  RemoveWhere(const F & match)
348  {
349  size_t numRemoved = 0;
350  auto it = Set_.begin();
351  while (it != Set_.end())
352  {
353  if (match(*it))
354  {
355  it = Set_.erase(it);
356  numRemoved++;
357  }
358  else
359  {
360  it++;
361  }
362  }
363 
364  return numRemoved;
365  }
366 
372  ItemConstIterator
374  {
375  return ItemConstIterator(Set_.erase(iterator.It_));
376  }
377 
384  bool
385  operator==(const HashSet<ItemType> & other) const noexcept
386  {
387  if (Size() != other.Size())
388  return false;
389 
390  for (auto & item : Set_)
391  if (!other.Contains(item))
392  return false;
393 
394  return true;
395  }
396 
403  bool
404  operator!=(const HashSet<ItemType> & other) const noexcept
405  {
406  return !operator==(other);
407  }
408 
409 private:
411 };
412 
413 }
414 
415 #endif // JLM_UTIL_HASHSET_HPP
ItemConstIterator(const typename InternalSet::const_iterator &it)
Definition: HashSet.hpp:40
InternalSet::const_iterator It_
Definition: HashSet.hpp:91
const ItemType & operator*() const
Definition: HashSet.hpp:52
ItemType * Item() const noexcept
Definition: HashSet.hpp:46
ItemConstIterator & operator++()
Definition: HashSet.hpp:64
std::forward_iterator_tag iterator_category
Definition: HashSet.hpp:31
bool operator!=(const ItemConstIterator &other) const
Definition: HashSet.hpp:85
ItemConstIterator operator++(int)
Definition: HashSet.hpp:71
bool operator==(const ItemConstIterator &other) const
Definition: HashSet.hpp:79
void DifferenceWith(const HashSet< ItemType > &other)
Definition: HashSet.hpp:302
void Clear() noexcept
Definition: HashSet.hpp:138
InternalSet Set_
Definition: HashSet.hpp:410
bool insert(ItemType item)
Definition: HashSet.hpp:210
std::unordered_set< ItemType, HashFunctor > InternalSet
Definition: HashSet.hpp:25
ItemConstIterator Erase(ItemConstIterator iterator)
Definition: HashSet.hpp:373
size_t RemoveWhere(const F &match)
Definition: HashSet.hpp:347
~HashSet() noexcept=default
std::size_t Size() const noexcept
Definition: HashSet.hpp:187
HashSet & operator=(const HashSet &other)
Definition: HashSet.hpp:121
bool IsSubsetOf(const HashSet< ItemType > &other) const noexcept
Definition: HashSet.hpp:163
bool operator==(const HashSet< ItemType > &other) const noexcept
Definition: HashSet.hpp:385
bool operator!=(const HashSet< ItemType > &other) const noexcept
Definition: HashSet.hpp:404
HashSet & operator=(HashSet &&other) noexcept
Definition: HashSet.hpp:128
HashSet(const HashSet &other)
Definition: HashSet.hpp:103
bool Contains(const ItemType &item) const noexcept
Definition: HashSet.hpp:150
void IntersectWith(const HashSet< ItemType > &other)
Definition: HashSet.hpp:269
bool UnionWithAndClear(HashSet< ItemType > &other)
Definition: HashSet.hpp:252
bool Remove(ItemType item)
Definition: HashSet.hpp:332
HashSet(HashSet &&other) noexcept
Definition: HashSet.hpp:107
HashSet(const std::unordered_set< ItemType, OtherHashFunctor > &other)
Definition: HashSet.hpp:116
IteratorRange< ItemConstIterator > Items() const noexcept
Definition: HashSet.hpp:223
HashSet(std::initializer_list< ItemType > initializerList)
Definition: HashSet.hpp:111
bool IsEmpty() const noexcept
Definition: HashSet.hpp:198
void IntersectWithAndClear(HashSet< ItemType > &other)
Definition: HashSet.hpp:286
bool UnionWith(const HashSet< ItemType > &other)
Definition: HashSet.hpp:236
jlm::rvsdg::Output * match(size_t nbits, const std::unordered_map< uint64_t, uint64_t > &mapping, uint64_t default_alternative, size_t nalternatives, jlm::rvsdg::Output *operand)
Definition: control.cpp:179