21 #ifndef LLVM_ADT_SPARSEMULTISET_H
22 #define LLVM_ADT_SPARSEMULTISET_H
75 template<
typename ValueT,
77 typename SparseT = uint8_t>
79 static_assert(std::numeric_limits<SparseT>::is_integer &&
80 !std::numeric_limits<SparseT>::is_signed,
81 "SparseT must be an unsigned integer type");
90 static const unsigned INVALID = ~0U;
96 SMSNode(ValueT D,
unsigned P,
unsigned N) :
Data(D), Prev(P), Next(N) { }
100 return Next == INVALID;
104 bool isTombstone()
const {
105 return Prev == INVALID;
110 bool isValid()
const {
return Prev != INVALID; }
113 typedef typename KeyFunctorT::argument_type KeyT;
118 KeyFunctorT KeyIndexOf;
124 unsigned FreelistIdx;
127 unsigned sparseIndex(
const ValueT &Val)
const {
128 assert(ValIndexOf(Val) < Universe &&
129 "Invalid key in set. Did object mutate?");
130 return ValIndexOf(Val);
132 unsigned sparseIndex(
const SMSNode &
N)
const {
return sparseIndex(N.Data); }
142 bool isHead(
const SMSNode &D)
const {
143 assert(D.isValid() &&
"Invalid node for head");
144 return Dense[D.Prev].isTail();
149 bool isSingleton(
const SMSNode &N)
const {
150 assert(N.isValid() &&
"Invalid node for singleton");
152 return &Dense[N.Prev] == &
N;
157 unsigned addValue(
const ValueT& V,
unsigned Prev,
unsigned Next) {
160 return Dense.
size() - 1;
164 unsigned Idx = FreelistIdx;
165 unsigned NextFree = Dense[Idx].Next;
166 assert(Dense[Idx].isTombstone() &&
"Non-tombstone free?");
168 Dense[Idx] = SMSNode(V, Prev, Next);
169 FreelistIdx = NextFree;
175 void makeTombstone(
unsigned Idx) {
176 Dense[Idx].Prev = SMSNode::INVALID;
177 Dense[Idx].Next = FreelistIdx;
191 : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {}
203 assert(
empty() &&
"Can only resize universe on an empty map");
205 if (U >= Universe/4 && U <= Universe)
211 Sparse =
reinterpret_cast<SparseT*
>(calloc(U,
sizeof(SparseT)));
217 template<
typename SMSPtrTy>
226 : SMS(P), Idx(I), SparseIdx(SI) { }
230 if (Idx == SMSNode::INVALID)
233 assert(Idx < SMS->Dense.size() &&
"Out of range, non-INVALID Idx?");
238 bool isKeyed()
const {
return SparseIdx < SMS->Universe; }
240 unsigned Prev()
const {
return SMS->Dense[Idx].Prev; }
241 unsigned Next()
const {
return SMS->Dense[Idx].Next; }
243 void setPrev(
unsigned P) { SMS->Dense[Idx].Prev =
P; }
244 void setNext(
unsigned N) { SMS->Dense[Idx].Next =
N; }
247 typedef std::iterator<std::bidirectional_iterator_tag, ValueT>
super;
254 assert(isKeyed() && SMS->sparseIndex(SMS->Dense[Idx].Data) == SparseIdx &&
255 "Dereferencing iterator of invalid key or index");
257 return SMS->Dense[Idx].Data;
264 if (SMS == RHS.SMS && Idx == RHS.Idx) {
265 assert((isEnd() || SparseIdx == RHS.SparseIdx) &&
266 "Same dense entry, but different keys?");
279 assert(isKeyed() &&
"Decrementing an invalid iterator");
280 assert((isEnd() || !SMS->isHead(SMS->Dense[Idx])) &&
281 "Decrementing head of list");
285 Idx = SMS->findIndex(SparseIdx).Prev();
292 assert(!isEnd() && isKeyed() &&
"Incrementing an invalid/end iterator");
332 assert(NumFree <= Dense.
size() &&
"Out-of-bounds free entries");
333 return Dense.
size() - NumFree;
342 FreelistIdx = SMSNode::INVALID;
351 assert(Idx < Universe &&
"Key out of range");
352 const unsigned Stride = std::numeric_limits<SparseT>::max() + 1u;
353 for (
unsigned i = Sparse[Idx], e = Dense.
size(); i < e; i += Stride) {
354 const unsigned FoundIdx = sparseIndex(Dense[i]);
357 if (Idx == FoundIdx && Dense[i].isValid() && isHead(Dense[i]))
400 I =
iterator(
this, I.Prev(), KeyIndexOf(Key));
410 return make_pair(B, E);
416 unsigned Idx = sparseIndex(Val);
419 unsigned NodeIdx = addValue(Val, SMSNode::INVALID, SMSNode::INVALID);
423 Sparse[Idx] = NodeIdx;
424 Dense[NodeIdx].Prev = NodeIdx;
425 return iterator(
this, NodeIdx, Idx);
429 unsigned HeadIdx = I.Idx;
430 unsigned TailIdx = I.Prev();
431 Dense[TailIdx].Next = NodeIdx;
432 Dense[HeadIdx].Prev = NodeIdx;
433 Dense[NodeIdx].Prev = TailIdx;
435 return iterator(
this, NodeIdx, Idx);
463 assert(I.isKeyed() && !I.isEnd() && !Dense[I.Idx].isTombstone() &&
464 "erasing invalid/end/tombstone iterator");
468 iterator NextI = unlink(Dense[I.Idx]);
471 makeTombstone(I.Idx);
486 if (isSingleton(N)) {
488 assert(N.Next == SMSNode::INVALID &&
"Singleton has next?");
489 return iterator(
this, SMSNode::INVALID, ValIndexOf(N.Data));
494 Sparse[sparseIndex(N)] = N.Next;
495 Dense[N.Next].Prev = N.Prev;
496 return iterator(
this, N.Next, ValIndexOf(N.Data));
501 findIndex(sparseIndex(N)).setPrev(N.Prev);
502 Dense[N.Prev].Next = N.Next;
505 iterator I(
this, N.Prev, ValIndexOf(N.Data));
510 Dense[N.Next].Prev = N.Prev;
511 Dense[N.Prev].Next = N.Next;
512 return iterator(
this, N.Next, ValIndexOf(N.Data));
iterator end()
Returns an iterator past this container.
void push_back(const T &Elt)
super::reference reference
iterator insert(const ValueT &Val)
Insert a new element at the tail of the subset list.
bool contains(const KeyT &Key) const
Returns true if this set contains an element identified by Key.
size_type size() const
Returns the number of elements in the set.
iterator_base & operator--()
Increment and decrement operators.
const_iterator find(const KeyT &Key) const
RangePair equal_range(const KeyT &K)
The bounds of the range of items sharing Key K.
iterator_base< SparseMultiSet * > iterator
iterator getHead(const KeyT &Key)
Return the head and tail of the subset's list, otherwise returns end().
const ValueT * const_pointer
iterator getTail(const KeyT &Key)
iterator_base & operator++()
iterator_base operator++(int)
iterator_base< const SparseMultiSet * > const_iterator
super::value_type value_type
void setUniverse(unsigned U)
Set the universe size which determines the largest key the set can hold.
pointer operator->() const
void clear()
Clears the set.
iterator find(const KeyT &Key)
Find an element by its key.
const_iterator end() const
reference operator*() const
iterator_base operator--(int)
super::difference_type difference_type
void eraseAll(const KeyT &K)
Erase all elements with the given key.
iterator findIndex(unsigned Idx)
Find an element by its index.
**iterator erase(iterator I)
SparseSetValFunctor - Helper class for selecting SparseSetValTraits.
std::iterator< std::bidirectional_iterator_tag, ValueT > super
bool operator!=(const iterator_base &RHS) const
Fast multiset implementation for objects that can be identified by small unsigned keys...
bool empty() const
Returns true if the set is empty.
Our iterators are iterators over the collection of objects that share a key.
const ValueT & const_reference
bool operator==(const iterator_base &RHS) const
Comparison operators.
std::pair< iterator, iterator > RangePair
size_type count(const KeyT &Key) const
Returns the number of elements identified by Key.