LLVM 22.0.0git
IntervalMap.h
Go to the documentation of this file.
1//===- llvm/ADT/IntervalMap.h - A sorted interval map -----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements a coalescing interval map for small objects.
11///
12/// KeyT objects are mapped to ValT objects. Intervals of keys that map to the
13/// same value are represented in a compressed form.
14///
15/// Iterators provide ordered access to the compressed intervals rather than the
16/// individual keys, and insert and erase operations use key intervals as well.
17///
18/// Like SmallVector, IntervalMap will store the first N intervals in the map
19/// object itself without any allocations. When space is exhausted it switches
20/// to a B+-tree representation with very small overhead for small key and
21/// value objects.
22///
23/// A Traits class specifies how keys are compared. It also allows IntervalMap
24/// to work with both closed and half-open intervals.
25///
26/// Keys and values are not stored next to each other in a std::pair, so we
27/// don't provide such a value_type. Dereferencing iterators only returns the
28/// mapped value. The interval bounds are accessible through the start() and
29/// stop() iterator methods.
30///
31/// IntervalMap is optimized for small key and value objects, 4 or 8 bytes
32/// each is the optimal size. For large objects use std::map instead.
33//
34//===----------------------------------------------------------------------===//
35//
36// Synopsis:
37//
38// template <typename KeyT, typename ValT, unsigned N, typename Traits>
39// class IntervalMap {
40// public:
41// typedef KeyT key_type;
42// typedef ValT mapped_type;
43// typedef RecyclingAllocator<...> Allocator;
44// class iterator;
45// class const_iterator;
46//
47// explicit IntervalMap(Allocator&);
48// ~IntervalMap():
49//
50// bool empty() const;
51// KeyT start() const;
52// KeyT stop() const;
53// ValT lookup(KeyT x, Value NotFound = Value()) const;
54//
55// const_iterator begin() const;
56// const_iterator end() const;
57// iterator begin();
58// iterator end();
59// const_iterator find(KeyT x) const;
60// iterator find(KeyT x);
61//
62// void insert(KeyT a, KeyT b, ValT y);
63// void clear();
64// };
65//
66// template <typename KeyT, typename ValT, unsigned N, typename Traits>
67// class IntervalMap::const_iterator {
68// public:
69// using iterator_category = std::bidirectional_iterator_tag;
70// using value_type = ValT;
71// using difference_type = std::ptrdiff_t;
72// using pointer = value_type *;
73// using reference = value_type &;
74//
75// bool operator==(const const_iterator &) const;
76// bool operator!=(const const_iterator &) const;
77// bool valid() const;
78//
79// const KeyT &start() const;
80// const KeyT &stop() const;
81// const ValT &value() const;
82// const ValT &operator*() const;
83// const ValT *operator->() const;
84//
85// const_iterator &operator++();
86// const_iterator &operator++(int);
87// const_iterator &operator--();
88// const_iterator &operator--(int);
89// void goToBegin();
90// void goToEnd();
91// void find(KeyT x);
92// void advanceTo(KeyT x);
93// };
94//
95// template <typename KeyT, typename ValT, unsigned N, typename Traits>
96// class IntervalMap::iterator : public const_iterator {
97// public:
98// void insert(KeyT a, KeyT b, Value y);
99// void erase();
100// };
101//
102//===----------------------------------------------------------------------===//
103
104#ifndef LLVM_ADT_INTERVALMAP_H
105#define LLVM_ADT_INTERVALMAP_H
106
108#include "llvm/ADT/SmallVector.h"
112#include <algorithm>
113#include <cassert>
114#include <iterator>
115#include <new>
116#include <utility>
117
118namespace llvm {
119
120//===----------------------------------------------------------------------===//
121//--- Key traits ---//
122//===----------------------------------------------------------------------===//
123//
124// The IntervalMap works with closed or half-open intervals.
125// Adjacent intervals that map to the same value are coalesced.
126//
127// The IntervalMapInfo traits class is used to determine if a key is contained
128// in an interval, and if two intervals are adjacent so they can be coalesced.
129// The provided implementation works for closed integer intervals, other keys
130// probably need a specialized version.
131//
132// The point x is contained in [a;b] when !startLess(x, a) && !stopLess(b, x).
133//
134// It is assumed that (a;b] half-open intervals are not used, only [a;b) is
135// allowed. This is so that stopLess(a, b) can be used to determine if two
136// intervals overlap.
137//
138//===----------------------------------------------------------------------===//
139
140template <typename T>
142 /// startLess - Return true if x is not in [a;b].
143 /// This is x < a both for closed intervals and for [a;b) half-open intervals.
144 static inline bool startLess(const T &x, const T &a) {
145 return x < a;
146 }
147
148 /// stopLess - Return true if x is not in [a;b].
149 /// This is b < x for a closed interval, b <= x for [a;b) half-open intervals.
150 static inline bool stopLess(const T &b, const T &x) {
151 return b < x;
152 }
153
154 /// adjacent - Return true when the intervals [x;a] and [b;y] can coalesce.
155 /// This is a+1 == b for closed intervals, a == b for half-open intervals.
156 static inline bool adjacent(const T &a, const T &b) {
157 return a+1 == b;
158 }
159
160 /// nonEmpty - Return true if [a;b] is non-empty.
161 /// This is a <= b for a closed interval, a < b for [a;b) half-open intervals.
162 static inline bool nonEmpty(const T &a, const T &b) {
163 return a <= b;
164 }
165};
166
167template <typename T>
169 /// startLess - Return true if x is not in [a;b).
170 static inline bool startLess(const T &x, const T &a) {
171 return x < a;
172 }
173
174 /// stopLess - Return true if x is not in [a;b).
175 static inline bool stopLess(const T &b, const T &x) {
176 return b <= x;
177 }
178
179 /// adjacent - Return true when the intervals [x;a) and [b;y) can coalesce.
180 static inline bool adjacent(const T &a, const T &b) {
181 return a == b;
182 }
183
184 /// nonEmpty - Return true if [a;b) is non-empty.
185 static inline bool nonEmpty(const T &a, const T &b) {
186 return a < b;
187 }
188};
189
190/// IntervalMapImpl - Namespace used for IntervalMap implementation details.
191/// It should be considered private to the implementation.
192namespace IntervalMapImpl {
193
194using IdxPair = std::pair<unsigned,unsigned>;
195
196//===----------------------------------------------------------------------===//
197//--- IntervalMapImpl::NodeBase ---//
198//===----------------------------------------------------------------------===//
199//
200// Both leaf and branch nodes store vectors of pairs.
201// Leaves store ((KeyT, KeyT), ValT) pairs, branches use (NodeRef, KeyT).
202//
203// Keys and values are stored in separate arrays to avoid padding caused by
204// different object alignments. This also helps improve locality of reference
205// when searching the keys.
206//
207// The nodes don't know how many elements they contain - that information is
208// stored elsewhere. Omitting the size field prevents padding and allows a node
209// to fill the allocated cache lines completely.
210//
211// These are typical key and value sizes, the node branching factor (N), and
212// wasted space when nodes are sized to fit in three cache lines (192 bytes):
213//
214// T1 T2 N Waste Used by
215// 4 4 24 0 Branch<4> (32-bit pointers)
216// 8 4 16 0 Leaf<4,4>, Branch<4>
217// 8 8 12 0 Leaf<4,8>, Branch<8>
218// 16 4 9 12 Leaf<8,4>
219// 16 8 8 0 Leaf<8,8>
220//
221//===----------------------------------------------------------------------===//
222
223template <typename T1, typename T2, unsigned N>
224class NodeBase {
225public:
226 static constexpr unsigned Capacity = N;
227
230
231 /// copy - Copy elements from another node.
232 /// @param Other Node elements are copied from.
233 /// @param i Beginning of the source range in other.
234 /// @param j Beginning of the destination range in this.
235 /// @param Count Number of elements to copy.
236 template <unsigned M>
237 void copy(const NodeBase<T1, T2, M> &Other, unsigned i,
238 unsigned j, unsigned Count) {
239 assert(i + Count <= M && "Invalid source range");
240 assert(j + Count <= N && "Invalid dest range");
241 for (unsigned e = i + Count; i != e; ++i, ++j) {
242 first[j] = Other.first[i];
243 second[j] = Other.second[i];
244 }
245 }
246
247 /// moveLeft - Move elements to the left.
248 /// @param i Beginning of the source range.
249 /// @param j Beginning of the destination range.
250 /// @param Count Number of elements to copy.
251 void moveLeft(unsigned i, unsigned j, unsigned Count) {
252 assert(j <= i && "Use moveRight shift elements right");
253 copy(*this, i, j, Count);
254 }
255
256 /// moveRight - Move elements to the right.
257 /// @param i Beginning of the source range.
258 /// @param j Beginning of the destination range.
259 /// @param Count Number of elements to copy.
260 void moveRight(unsigned i, unsigned j, unsigned Count) {
261 assert(i <= j && "Use moveLeft shift elements left");
262 assert(j + Count <= N && "Invalid range");
263 while (Count--) {
264 first[j + Count] = first[i + Count];
265 second[j + Count] = second[i + Count];
266 }
267 }
268
269 /// erase - Erase elements [i;j).
270 /// @param i Beginning of the range to erase.
271 /// @param j End of the range. (Exclusive).
272 /// @param Size Number of elements in node.
273 void erase(unsigned i, unsigned j, unsigned Size) {
274 moveLeft(j, i, Size - j);
275 }
276
277 /// erase - Erase element at i.
278 /// @param i Index of element to erase.
279 /// @param Size Number of elements in node.
280 void erase(unsigned i, unsigned Size) {
281 erase(i, i+1, Size);
282 }
283
284 /// shift - Shift elements [i;size) 1 position to the right.
285 /// @param i Beginning of the range to move.
286 /// @param Size Number of elements in node.
287 void shift(unsigned i, unsigned Size) {
288 moveRight(i, i + 1, Size - i);
289 }
290
291 /// transferToLeftSib - Transfer elements to a left sibling node.
292 /// @param Size Number of elements in this.
293 /// @param Sib Left sibling node.
294 /// @param SSize Number of elements in sib.
295 /// @param Count Number of elements to transfer.
296 void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize,
297 unsigned Count) {
298 Sib.copy(*this, 0, SSize, Count);
299 erase(0, Count, Size);
300 }
301
302 /// transferToRightSib - Transfer elements to a right sibling node.
303 /// @param Size Number of elements in this.
304 /// @param Sib Right sibling node.
305 /// @param SSize Number of elements in sib.
306 /// @param Count Number of elements to transfer.
307 void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize,
308 unsigned Count) {
309 Sib.moveRight(0, Count, SSize);
310 Sib.copy(*this, Size-Count, 0, Count);
311 }
312
313 /// adjustFromLeftSib - Adjust the number if elements in this node by moving
314 /// elements to or from a left sibling node.
315 /// @param Size Number of elements in this.
316 /// @param Sib Right sibling node.
317 /// @param SSize Number of elements in sib.
318 /// @param Add The number of elements to add to this node, possibly < 0.
319 /// @return Number of elements added to this node, possibly negative.
320 int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add) {
321 if (Add > 0) {
322 // We want to grow, copy from sib.
323 unsigned Count = std::min(std::min(unsigned(Add), SSize), N - Size);
324 Sib.transferToRightSib(SSize, *this, Size, Count);
325 return Count;
326 } else {
327 // We want to shrink, copy to sib.
328 unsigned Count = std::min(std::min(unsigned(-Add), Size), N - SSize);
329 transferToLeftSib(Size, Sib, SSize, Count);
330 return -Count;
331 }
332 }
333};
334
335/// IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes.
336/// @param Node Array of pointers to sibling nodes.
337/// @param Nodes Number of nodes.
338/// @param CurSize Array of current node sizes, will be overwritten.
339/// @param NewSize Array of desired node sizes.
340template <typename NodeT>
341void adjustSiblingSizes(NodeT *Node[], unsigned Nodes,
342 unsigned CurSize[], const unsigned NewSize[]) {
343 // Move elements right.
344 for (int n = Nodes - 1; n; --n) {
345 if (CurSize[n] == NewSize[n])
346 continue;
347 for (int m = n - 1; m != -1; --m) {
348 int d = Node[n]->adjustFromLeftSib(CurSize[n], *Node[m], CurSize[m],
349 NewSize[n] - CurSize[n]);
350 CurSize[m] -= d;
351 CurSize[n] += d;
352 // Keep going if the current node was exhausted.
353 if (CurSize[n] >= NewSize[n])
354 break;
355 }
356 }
357
358 if (Nodes == 0)
359 return;
360
361 // Move elements left.
362 for (unsigned n = 0; n != Nodes - 1; ++n) {
363 if (CurSize[n] == NewSize[n])
364 continue;
365 for (unsigned m = n + 1; m != Nodes; ++m) {
366 int d = Node[m]->adjustFromLeftSib(CurSize[m], *Node[n], CurSize[n],
367 CurSize[n] - NewSize[n]);
368 CurSize[m] += d;
369 CurSize[n] -= d;
370 // Keep going if the current node was exhausted.
371 if (CurSize[n] >= NewSize[n])
372 break;
373 }
374 }
375
376#ifndef NDEBUG
377 for (unsigned n = 0; n != Nodes; n++)
378 assert(CurSize[n] == NewSize[n] && "Insufficient element shuffle");
379#endif
380}
381
382/// IntervalMapImpl::distribute - Compute a new distribution of node elements
383/// after an overflow or underflow. Reserve space for a new element at Position,
384/// and compute the node that will hold Position after redistributing node
385/// elements.
386///
387/// It is required that
388///
389/// Elements == sum(CurSize), and
390/// Elements + Grow <= Nodes * Capacity.
391///
392/// NewSize[] will be filled in such that:
393///
394/// sum(NewSize) == Elements, and
395/// NewSize[i] <= Capacity.
396///
397/// The returned index is the node where Position will go, so:
398///
399/// sum(NewSize[0..idx-1]) <= Position
400/// sum(NewSize[0..idx]) >= Position
401///
402/// The last equality, sum(NewSize[0..idx]) == Position, can only happen when
403/// Grow is set and NewSize[idx] == Capacity-1. The index points to the node
404/// before the one holding the Position'th element where there is room for an
405/// insertion.
406///
407/// @param Nodes The number of nodes.
408/// @param Elements Total elements in all nodes.
409/// @param Capacity The capacity of each node.
410/// @param CurSize Array[Nodes] of current node sizes, or NULL.
411/// @param NewSize Array[Nodes] to receive the new node sizes.
412/// @param Position Insert position.
413/// @param Grow Reserve space for a new element at Position.
414/// @return (node, offset) for Position.
415LLVM_ABI IdxPair distribute(unsigned Nodes, unsigned Elements,
416 unsigned Capacity, const unsigned *CurSize,
417 unsigned NewSize[], unsigned Position, bool Grow);
418
419//===----------------------------------------------------------------------===//
420//--- IntervalMapImpl::NodeSizer ---//
421//===----------------------------------------------------------------------===//
422//
423// Compute node sizes from key and value types.
424//
425// The branching factors are chosen to make nodes fit in three cache lines.
426// This may not be possible if keys or values are very large. Such large objects
427// are handled correctly, but a std::map would probably give better performance.
428//
429//===----------------------------------------------------------------------===//
430
431enum {
432 // Cache line size. Most architectures have 32 or 64 byte cache lines.
433 // We use 64 bytes here because it provides good branching factors.
438
439template <typename KeyT, typename ValT>
440struct NodeSizer {
441 enum {
442 // Compute the leaf node branching factor that makes a node fit in three
443 // cache lines. The branching factor must be at least 3, or some B+-tree
444 // balancing algorithms won't work.
445 // LeafSize can't be larger than CacheLineBytes. This is required by the
446 // PointerIntPair used by NodeRef.
448 static_cast<unsigned>(2*sizeof(KeyT)+sizeof(ValT)),
451 };
452
454
455 enum {
456 // Now that we have the leaf branching factor, compute the actual allocation
457 // unit size by rounding up to a whole number of cache lines.
459
460 // Determine the branching factor for branch nodes.
462 static_cast<unsigned>(sizeof(KeyT) + sizeof(void*))
463 };
464
465 /// Allocator - The recycling allocator used for both branch and leaf nodes.
466 /// This typedef is very likely to be identical for all IntervalMaps with
467 /// reasonably sized entries, so the same allocator can be shared among
468 /// different kinds of maps.
469 using Allocator =
471};
472
473//===----------------------------------------------------------------------===//
474//--- IntervalMapImpl::NodeRef ---//
475//===----------------------------------------------------------------------===//
476//
477// B+-tree nodes can be leaves or branches, so we need a polymorphic node
478// pointer that can point to both kinds.
479//
480// All nodes are cache line aligned and the low 6 bits of a node pointer are
481// always 0. These bits are used to store the number of elements in the
482// referenced node. Besides saving space, placing node sizes in the parents
483// allow tree balancing algorithms to run without faulting cache lines for nodes
484// that may not need to be modified.
485//
486// A NodeRef doesn't know whether it references a leaf node or a branch node.
487// It is the responsibility of the caller to use the correct types.
488//
489// Nodes are never supposed to be empty, and it is invalid to store a node size
490// of 0 in a NodeRef. The valid range of sizes is 1-64.
491//
492//===----------------------------------------------------------------------===//
493
494class NodeRef {
495 struct CacheAlignedPointerTraits {
496 static inline void *getAsVoidPointer(void *P) { return P; }
497 static inline void *getFromVoidPointer(void *P) { return P; }
498 static constexpr int NumLowBitsAvailable = Log2CacheLine;
499 };
501
502public:
503 /// NodeRef - Create a null ref.
504 NodeRef() = default;
505
506 /// operator bool - Detect a null ref.
507 explicit operator bool() const { return pip.getOpaqueValue(); }
508
509 /// NodeRef - Create a reference to the node p with n elements.
510 template <typename NodeT>
511 NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) {
512 assert(n <= NodeT::Capacity && "Size too big for node");
513 }
514
515 /// size - Return the number of elements in the referenced node.
516 unsigned size() const { return pip.getInt() + 1; }
517
518 /// setSize - Update the node size.
519 void setSize(unsigned n) { pip.setInt(n - 1); }
520
521 /// subtree - Access the i'th subtree reference in a branch node.
522 /// This depends on branch nodes storing the NodeRef array as their first
523 /// member.
524 NodeRef &subtree(unsigned i) const {
525 return reinterpret_cast<NodeRef*>(pip.getPointer())[i];
526 }
527
528 /// get - Dereference as a NodeT reference.
529 template <typename NodeT>
530 NodeT &get() const {
531 return *reinterpret_cast<NodeT*>(pip.getPointer());
532 }
533
534 bool operator==(const NodeRef &RHS) const {
535 if (pip == RHS.pip)
536 return true;
537 assert(pip.getPointer() != RHS.pip.getPointer() && "Inconsistent NodeRefs");
538 return false;
539 }
540
541 bool operator!=(const NodeRef &RHS) const {
542 return !operator==(RHS);
543 }
544};
545
546//===----------------------------------------------------------------------===//
547//--- IntervalMapImpl::LeafNode ---//
548//===----------------------------------------------------------------------===//
549//
550// Leaf nodes store up to N disjoint intervals with corresponding values.
551//
552// The intervals are kept sorted and fully coalesced so there are no adjacent
553// intervals mapping to the same value.
554//
555// These constraints are always satisfied:
556//
557// - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals.
558//
559// - Traits::stopLess(stop(i), start(i + 1) - Sorted.
560//
561// - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1))
562// - Fully coalesced.
563//
564//===----------------------------------------------------------------------===//
565
566template <typename KeyT, typename ValT, unsigned N, typename Traits>
567class LeafNode : public NodeBase<std::pair<KeyT, KeyT>, ValT, N> {
568public:
569 const KeyT &start(unsigned i) const { return this->first[i].first; }
570 const KeyT &stop(unsigned i) const { return this->first[i].second; }
571 const ValT &value(unsigned i) const { return this->second[i]; }
572
573 KeyT &start(unsigned i) { return this->first[i].first; }
574 KeyT &stop(unsigned i) { return this->first[i].second; }
575 ValT &value(unsigned i) { return this->second[i]; }
576
577 /// findFrom - Find the first interval after i that may contain x.
578 /// @param i Starting index for the search.
579 /// @param Size Number of elements in node.
580 /// @param x Key to search for.
581 /// @return First index with !stopLess(key[i].stop, x), or size.
582 /// This is the first interval that can possibly contain x.
583 unsigned findFrom(unsigned i, unsigned Size, KeyT x) const {
584 assert(i <= Size && Size <= N && "Bad indices");
585 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) &&
586 "Index is past the needed point");
587 while (i != Size && Traits::stopLess(stop(i), x)) ++i;
588 return i;
589 }
590
591 /// safeFind - Find an interval that is known to exist. This is the same as
592 /// findFrom except is it assumed that x is at least within range of the last
593 /// interval.
594 /// @param i Starting index for the search.
595 /// @param x Key to search for.
596 /// @return First index with !stopLess(key[i].stop, x), never size.
597 /// This is the first interval that can possibly contain x.
598 unsigned safeFind(unsigned i, KeyT x) const {
599 assert(i < N && "Bad index");
600 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) &&
601 "Index is past the needed point");
602 while (Traits::stopLess(stop(i), x)) ++i;
603 assert(i < N && "Unsafe intervals");
604 return i;
605 }
606
607 /// safeLookup - Lookup mapped value for a safe key.
608 /// It is assumed that x is within range of the last entry.
609 /// @param x Key to search for.
610 /// @param NotFound Value to return if x is not in any interval.
611 /// @return The mapped value at x or NotFound.
612 ValT safeLookup(KeyT x, ValT NotFound) const {
613 unsigned i = safeFind(0, x);
614 return Traits::startLess(x, start(i)) ? NotFound : value(i);
615 }
616
617 unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y);
618};
619
620/// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as
621/// possible. This may cause the node to grow by 1, or it may cause the node
622/// to shrink because of coalescing.
623/// @param Pos Starting index = insertFrom(0, size, a)
624/// @param Size Number of elements in node.
625/// @param a Interval start.
626/// @param b Interval stop.
627/// @param y Value be mapped.
628/// @return (insert position, new size), or (i, Capacity+1) on overflow.
629template <typename KeyT, typename ValT, unsigned N, typename Traits>
631insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y) {
632 unsigned i = Pos;
633 assert(i <= Size && Size <= N && "Invalid index");
634 assert(!Traits::stopLess(b, a) && "Invalid interval");
635
636 // Verify the findFrom invariant.
637 assert((i == 0 || Traits::stopLess(stop(i - 1), a)));
638 assert((i == Size || !Traits::stopLess(stop(i), a)));
639 assert((i == Size || Traits::stopLess(b, start(i))) && "Overlapping insert");
640
641 // Coalesce with previous interval.
642 if (i && value(i - 1) == y && Traits::adjacent(stop(i - 1), a)) {
643 Pos = i - 1;
644 // Also coalesce with next interval?
645 if (i != Size && value(i) == y && Traits::adjacent(b, start(i))) {
646 stop(i - 1) = stop(i);
647 this->erase(i, Size);
648 return Size - 1;
649 }
650 stop(i - 1) = b;
651 return Size;
652 }
653
654 // Detect overflow.
655 if (i == N)
656 return N + 1;
657
658 // Add new interval at end.
659 if (i == Size) {
660 start(i) = a;
661 stop(i) = b;
662 value(i) = y;
663 return Size + 1;
664 }
665
666 // Try to coalesce with following interval.
667 if (value(i) == y && Traits::adjacent(b, start(i))) {
668 start(i) = a;
669 return Size;
670 }
671
672 // We must insert before i. Detect overflow.
673 if (Size == N)
674 return N + 1;
675
676 // Insert before i.
677 this->shift(i, Size);
678 start(i) = a;
679 stop(i) = b;
680 value(i) = y;
681 return Size + 1;
682}
683
684//===----------------------------------------------------------------------===//
685//--- IntervalMapImpl::BranchNode ---//
686//===----------------------------------------------------------------------===//
687//
688// A branch node stores references to 1--N subtrees all of the same height.
689//
690// The key array in a branch node holds the rightmost stop key of each subtree.
691// It is redundant to store the last stop key since it can be found in the
692// parent node, but doing so makes tree balancing a lot simpler.
693//
694// It is unusual for a branch node to only have one subtree, but it can happen
695// in the root node if it is smaller than the normal nodes.
696//
697// When all of the leaf nodes from all the subtrees are concatenated, they must
698// satisfy the same constraints as a single leaf node. They must be sorted,
699// sane, and fully coalesced.
700//
701//===----------------------------------------------------------------------===//
702
703template <typename KeyT, typename ValT, unsigned N, typename Traits>
704class BranchNode : public NodeBase<NodeRef, KeyT, N> {
705public:
706 const KeyT &stop(unsigned i) const { return this->second[i]; }
707 const NodeRef &subtree(unsigned i) const { return this->first[i]; }
708
709 KeyT &stop(unsigned i) { return this->second[i]; }
710 NodeRef &subtree(unsigned i) { return this->first[i]; }
711
712 /// findFrom - Find the first subtree after i that may contain x.
713 /// @param i Starting index for the search.
714 /// @param Size Number of elements in node.
715 /// @param x Key to search for.
716 /// @return First index with !stopLess(key[i], x), or size.
717 /// This is the first subtree that can possibly contain x.
718 unsigned findFrom(unsigned i, unsigned Size, KeyT x) const {
719 assert(i <= Size && Size <= N && "Bad indices");
720 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) &&
721 "Index to findFrom is past the needed point");
722 while (i != Size && Traits::stopLess(stop(i), x)) ++i;
723 return i;
724 }
725
726 /// safeFind - Find a subtree that is known to exist. This is the same as
727 /// findFrom except is it assumed that x is in range.
728 /// @param i Starting index for the search.
729 /// @param x Key to search for.
730 /// @return First index with !stopLess(key[i], x), never size.
731 /// This is the first subtree that can possibly contain x.
732 unsigned safeFind(unsigned i, KeyT x) const {
733 assert(i < N && "Bad index");
734 assert((i == 0 || Traits::stopLess(stop(i - 1), x)) &&
735 "Index is past the needed point");
736 while (Traits::stopLess(stop(i), x)) ++i;
737 assert(i < N && "Unsafe intervals");
738 return i;
739 }
740
741 /// safeLookup - Get the subtree containing x, Assuming that x is in range.
742 /// @param x Key to search for.
743 /// @return Subtree containing x
745 return subtree(safeFind(0, x));
746 }
747
748 /// insert - Insert a new (subtree, stop) pair.
749 /// @param i Insert position, following entries will be shifted.
750 /// @param Size Number of elements in node.
751 /// @param Node Subtree to insert.
752 /// @param Stop Last key in subtree.
753 void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) {
754 assert(Size < N && "branch node overflow");
755 assert(i <= Size && "Bad insert position");
756 this->shift(i, Size);
757 subtree(i) = Node;
758 stop(i) = Stop;
759 }
760};
761
762//===----------------------------------------------------------------------===//
763//--- IntervalMapImpl::Path ---//
764//===----------------------------------------------------------------------===//
765//
766// A Path is used by iterators to represent a position in a B+-tree, and the
767// path to get there from the root.
768//
769// The Path class also contains the tree navigation code that doesn't have to
770// be templatized.
771//
772//===----------------------------------------------------------------------===//
773
774class Path {
775 /// Entry - Each step in the path is a node pointer and an offset into that
776 /// node.
777 struct Entry {
778 void *node;
779 unsigned size;
780 unsigned offset;
781
782 Entry(void *Node, unsigned Size, unsigned Offset)
783 : node(Node), size(Size), offset(Offset) {}
784
785 Entry(NodeRef Node, unsigned Offset)
786 : node(&Node.subtree(0)), size(Node.size()), offset(Offset) {}
787
788 NodeRef &subtree(unsigned i) const {
789 return reinterpret_cast<NodeRef*>(node)[i];
790 }
791 };
792
793 /// path - The path entries, path[0] is the root node, path.back() is a leaf.
795
796public:
797 // Node accessors.
798 template <typename NodeT> NodeT &node(unsigned Level) const {
799 return *reinterpret_cast<NodeT*>(path[Level].node);
800 }
801 unsigned size(unsigned Level) const { return path[Level].size; }
802 unsigned offset(unsigned Level) const { return path[Level].offset; }
803 unsigned &offset(unsigned Level) { return path[Level].offset; }
804
805 // Leaf accessors.
806 template <typename NodeT> NodeT &leaf() const {
807 return *reinterpret_cast<NodeT*>(path.back().node);
808 }
809 unsigned leafSize() const { return path.back().size; }
810 unsigned leafOffset() const { return path.back().offset; }
811 unsigned &leafOffset() { return path.back().offset; }
812
813 /// valid - Return true if path is at a valid node, not at end().
814 bool valid() const {
815 return !path.empty() && path.front().offset < path.front().size;
816 }
817
818 /// height - Return the height of the tree corresponding to this path.
819 /// This matches map->height in a full path.
820 unsigned height() const { return path.size() - 1; }
821
822 /// subtree - Get the subtree referenced from Level. When the path is
823 /// consistent, node(Level + 1) == subtree(Level).
824 /// @param Level 0..height-1. The leaves have no subtrees.
825 NodeRef &subtree(unsigned Level) const {
826 return path[Level].subtree(path[Level].offset);
827 }
828
829 /// reset - Reset cached information about node(Level) from subtree(Level -1).
830 /// @param Level 1..height. The node to update after parent node changed.
831 void reset(unsigned Level) {
832 path[Level] = Entry(subtree(Level - 1), offset(Level));
833 }
834
835 /// push - Add entry to path.
836 /// @param Node Node to add, should be subtree(path.size()-1).
837 /// @param Offset Offset into Node.
838 void push(NodeRef Node, unsigned Offset) {
839 path.push_back(Entry(Node, Offset));
840 }
841
842 /// pop - Remove the last path entry.
843 void pop() {
844 path.pop_back();
845 }
846
847 /// setSize - Set the size of a node both in the path and in the tree.
848 /// @param Level 0..height. Note that setting the root size won't change
849 /// map->rootSize.
850 /// @param Size New node size.
851 void setSize(unsigned Level, unsigned Size) {
852 path[Level].size = Size;
853 if (Level)
854 subtree(Level - 1).setSize(Size);
855 }
856
857 /// setRoot - Clear the path and set a new root node.
858 /// @param Node New root node.
859 /// @param Size New root size.
860 /// @param Offset Offset into root node.
861 void setRoot(void *Node, unsigned Size, unsigned Offset) {
862 path.clear();
863 path.push_back(Entry(Node, Size, Offset));
864 }
865
866 /// replaceRoot - Replace the current root node with two new entries after the
867 /// tree height has increased.
868 /// @param Root The new root node.
869 /// @param Size Number of entries in the new root.
870 /// @param Offsets Offsets into the root and first branch nodes.
871 LLVM_ABI void replaceRoot(void *Root, unsigned Size, IdxPair Offsets);
872
873 /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
874 /// @param Level Get the sibling to node(Level).
875 /// @return Left sibling, or NodeRef().
876 LLVM_ABI NodeRef getLeftSibling(unsigned Level) const;
877
878 /// moveLeft - Move path to the left sibling at Level. Leave nodes below Level
879 /// unaltered.
880 /// @param Level Move node(Level).
881 LLVM_ABI void moveLeft(unsigned Level);
882
883 /// fillLeft - Grow path to Height by taking leftmost branches.
884 /// @param Height The target height.
885 void fillLeft(unsigned Height) {
886 while (height() < Height)
887 push(subtree(height()), 0);
888 }
889
890 /// getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
891 /// @param Level Get the sibling to node(Level).
892 /// @return Left sibling, or NodeRef().
893 LLVM_ABI NodeRef getRightSibling(unsigned Level) const;
894
895 /// moveRight - Move path to the left sibling at Level. Leave nodes below
896 /// Level unaltered.
897 /// @param Level Move node(Level).
898 LLVM_ABI void moveRight(unsigned Level);
899
900 /// atBegin - Return true if path is at begin().
901 bool atBegin() const {
902 for (unsigned i = 0, e = path.size(); i != e; ++i)
903 if (path[i].offset != 0)
904 return false;
905 return true;
906 }
907
908 /// atLastEntry - Return true if the path is at the last entry of the node at
909 /// Level.
910 /// @param Level Node to examine.
911 bool atLastEntry(unsigned Level) const {
912 return path[Level].offset == path[Level].size - 1;
913 }
914
915 /// legalizeForInsert - Prepare the path for an insertion at Level. When the
916 /// path is at end(), node(Level) may not be a legal node. legalizeForInsert
917 /// ensures that node(Level) is real by moving back to the last node at Level,
918 /// and setting offset(Level) to size(Level) if required.
919 /// @param Level The level where an insertion is about to take place.
920 void legalizeForInsert(unsigned Level) {
921 if (valid())
922 return;
923 moveLeft(Level);
924 ++path[Level].offset;
925 }
926};
927
928} // end namespace IntervalMapImpl
929
930//===----------------------------------------------------------------------===//
931//--- IntervalMap ----//
932//===----------------------------------------------------------------------===//
933
934template <typename KeyT, typename ValT,
935 unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
936 typename Traits = IntervalMapInfo<KeyT>>
940 using Branch =
943 using IdxPair = IntervalMapImpl::IdxPair;
944
945 // The RootLeaf capacity is given as a template parameter. We must compute the
946 // corresponding RootBranch capacity.
947 enum {
948 DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) /
949 (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)),
950 RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1
951 };
952
953 using RootBranch =
955
956 // When branched, we store a global start key as well as the branch node.
957 struct RootBranchData {
958 KeyT start;
959 RootBranch node;
960 };
961
962public:
963 using Allocator = typename Sizer::Allocator;
964 using KeyType = KeyT;
966 using KeyTraits = Traits;
967
968private:
969 // The root data is either a RootLeaf or a RootBranchData instance.
970 union {
972 RootBranchData branchData;
973 };
974
975 // Tree height.
976 // 0: Leaves in root.
977 // 1: Root points to leaf.
978 // 2: root->branch->leaf ...
979 unsigned height = 0;
980
981 // Number of entries in the root node.
982 unsigned rootSize = 0;
983
984 // Allocator used for creating external nodes.
985 Allocator *allocator = nullptr;
986
987 const RootLeaf &rootLeaf() const {
988 assert(!branched() && "Cannot acces leaf data in branched root");
989 return leaf;
990 }
991 RootLeaf &rootLeaf() {
992 assert(!branched() && "Cannot acces leaf data in branched root");
993 return leaf;
994 }
995
996 const RootBranchData &rootBranchData() const {
997 assert(branched() && "Cannot access branch data in non-branched root");
998 return branchData;
999 }
1000 RootBranchData &rootBranchData() {
1001 assert(branched() && "Cannot access branch data in non-branched root");
1002 return branchData;
1003 }
1004
1005 const RootBranch &rootBranch() const { return rootBranchData().node; }
1006 RootBranch &rootBranch() { return rootBranchData().node; }
1007 KeyT rootBranchStart() const { return rootBranchData().start; }
1008 KeyT &rootBranchStart() { return rootBranchData().start; }
1009
1010 template <typename NodeT> NodeT *newNode() {
1011 return new (allocator->template Allocate<NodeT>()) NodeT();
1012 }
1013
1014 template <typename NodeT> void deleteNode(NodeT *P) {
1015 P->~NodeT();
1016 allocator->Deallocate(P);
1017 }
1018
1019 IdxPair branchRoot(unsigned Position);
1020 IdxPair splitRoot(unsigned Position);
1021
1022 void switchRootToBranch() {
1023 rootLeaf().~RootLeaf();
1024 height = 1;
1025 new (&rootBranchData()) RootBranchData();
1026 }
1027
1028 void switchRootToLeaf() {
1029 rootBranchData().~RootBranchData();
1030 height = 0;
1031 new(&rootLeaf()) RootLeaf();
1032 }
1033
1034 bool branched() const { return height > 0; }
1035
1036 ValT treeSafeLookup(KeyT x, ValT NotFound) const;
1037 void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef,
1038 unsigned Level));
1039 void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level);
1040
1041public:
1042 explicit IntervalMap(Allocator &a) : allocator(&a) {
1043 new (&rootLeaf()) RootLeaf();
1044 }
1045
1046 ///@{
1047 /// NOTE: The moved-from or copied-from object's allocator needs to have a
1048 /// lifetime equal to or exceeding the moved-to or copied-to object to avoid
1049 /// undefined behaviour.
1051 // Future-proofing assertion: this function assumes the IntervalMap
1052 // constructor doesn't add any nodes.
1053 assert(empty() && "Expected emptry tree");
1054 *this = RHS;
1055 }
1057 clear();
1058 allocator = RHS.allocator;
1059 for (auto It = RHS.begin(), End = RHS.end(); It != End; ++It)
1060 insert(It.start(), It.stop(), It.value());
1061 return *this;
1062 }
1063
1065 // Future-proofing assertion: this function assumes the IntervalMap
1066 // constructor doesn't add any nodes.
1067 assert(empty() && "Expected emptry tree");
1068 *this = std::move(RHS);
1069 }
1071 // Calling clear deallocates memory and switches to rootLeaf.
1072 clear();
1073 // Destroy the new rootLeaf.
1074 rootLeaf().~RootLeaf();
1075
1076 height = RHS.height;
1077 rootSize = RHS.rootSize;
1078 allocator = RHS.allocator;
1079
1080 // rootLeaf and rootBranch are both uninitialized. Move RHS data into
1081 // appropriate field.
1082 if (RHS.branched()) {
1083 rootBranch() = std::move(RHS.rootBranch());
1084 // Prevent RHS deallocating memory LHS now owns by replacing RHS
1085 // rootBranch with a new rootLeaf.
1086 RHS.rootBranch().~RootBranch();
1087 RHS.height = 0;
1088 new (&RHS.rootLeaf()) RootLeaf();
1089 } else {
1090 rootLeaf() = std::move(RHS.rootLeaf());
1091 }
1092 return *this;
1093 }
1094 ///@}
1095
1097 clear();
1098 rootLeaf().~RootLeaf();
1099 }
1100
1101 /// empty - Return true when no intervals are mapped.
1102 bool empty() const {
1103 return rootSize == 0;
1104 }
1105
1106 /// start - Return the smallest mapped key in a non-empty map.
1107 KeyT start() const {
1108 assert(!empty() && "Empty IntervalMap has no start");
1109 return !branched() ? rootLeaf().start(0) : rootBranchStart();
1110 }
1111
1112 /// stop - Return the largest mapped key in a non-empty map.
1113 KeyT stop() const {
1114 assert(!empty() && "Empty IntervalMap has no stop");
1115 return !branched() ? rootLeaf().stop(rootSize - 1) :
1116 rootBranch().stop(rootSize - 1);
1117 }
1118
1119 /// lookup - Return the mapped value at x or NotFound.
1120 ValT lookup(KeyT x, ValT NotFound = ValT()) const {
1121 if (empty() || Traits::startLess(x, start()) || Traits::stopLess(stop(), x))
1122 return NotFound;
1123 return branched() ? treeSafeLookup(x, NotFound) :
1124 rootLeaf().safeLookup(x, NotFound);
1125 }
1126
1127 /// insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals.
1128 /// It is assumed that no key in the interval is mapped to another value, but
1129 /// overlapping intervals already mapped to y will be coalesced.
1130 void insert(KeyT a, KeyT b, ValT y) {
1131 if (branched() || rootSize == RootLeaf::Capacity)
1132 return find(a).insert(a, b, y);
1133
1134 // Easy insert into root leaf.
1135 unsigned p = rootLeaf().findFrom(0, rootSize, a);
1136 rootSize = rootLeaf().insertFrom(p, rootSize, a, b, y);
1137 }
1138
1139 /// clear - Remove all entries.
1140 void clear();
1141
1142 class const_iterator;
1143 class iterator;
1144 friend class const_iterator;
1145 friend class iterator;
1146
1148 const_iterator I(*this);
1149 I.goToBegin();
1150 return I;
1151 }
1152
1154 iterator I(*this);
1155 I.goToBegin();
1156 return I;
1157 }
1158
1160 const_iterator I(*this);
1161 I.goToEnd();
1162 return I;
1163 }
1164
1166 iterator I(*this);
1167 I.goToEnd();
1168 return I;
1169 }
1170
1171 /// find - Return an iterator pointing to the first interval ending at or
1172 /// after x, or end().
1174 const_iterator I(*this);
1175 I.find(x);
1176 return I;
1177 }
1178
1180 iterator I(*this);
1181 I.find(x);
1182 return I;
1183 }
1184
1185 /// overlaps(a, b) - Return true if the intervals in this map overlap with the
1186 /// interval [a;b].
1187 bool overlaps(KeyT a, KeyT b) const {
1188 assert(Traits::nonEmpty(a, b));
1189 const_iterator I = find(a);
1190 if (!I.valid())
1191 return false;
1192 // [a;b] and [x;y] overlap iff x<=b and a<=y. The find() call guarantees the
1193 // second part (y = find(a).stop()), so it is sufficient to check the first
1194 // one.
1195 return !Traits::stopLess(b, I.start());
1196 }
1197};
1198
1199/// treeSafeLookup - Return the mapped value at x or NotFound, assuming a
1200/// branched root.
1201template <typename KeyT, typename ValT, unsigned N, typename Traits>
1202ValT IntervalMap<KeyT, ValT, N, Traits>::
1203treeSafeLookup(KeyT x, ValT NotFound) const {
1204 assert(branched() && "treeLookup assumes a branched root");
1205
1206 IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x);
1207 for (unsigned h = height-1; h; --h)
1208 NR = NR.get<Branch>().safeLookup(x);
1209 return NR.get<Leaf>().safeLookup(x, NotFound);
1210}
1211
1212// branchRoot - Switch from a leaf root to a branched root.
1213// Return the new (root offset, node offset) corresponding to Position.
1214template <typename KeyT, typename ValT, unsigned N, typename Traits>
1215IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>::
1216branchRoot(unsigned Position) {
1217 using namespace IntervalMapImpl;
1218 // How many external leaf nodes to hold RootLeaf+1?
1219 const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1;
1220
1221 // Compute element distribution among new nodes.
1222 unsigned size[Nodes];
1223 IdxPair NewOffset(0, Position);
1224
1225 // It is very common for the root node to be smaller than external nodes.
1226 if (Nodes == 1)
1227 size[0] = rootSize;
1228 else
1229 NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, size,
1230 Position, true);
1231
1232 // Allocate new nodes.
1233 unsigned pos = 0;
1234 NodeRef node[Nodes];
1235 for (unsigned n = 0; n != Nodes; ++n) {
1236 Leaf *L = newNode<Leaf>();
1237 L->copy(rootLeaf(), pos, 0, size[n]);
1238 node[n] = NodeRef(L, size[n]);
1239 pos += size[n];
1240 }
1241
1242 // Destroy the old leaf node, construct branch node instead.
1243 switchRootToBranch();
1244 for (unsigned n = 0; n != Nodes; ++n) {
1245 rootBranch().stop(n) = node[n].template get<Leaf>().stop(size[n]-1);
1246 rootBranch().subtree(n) = node[n];
1247 }
1248 rootBranchStart() = node[0].template get<Leaf>().start(0);
1249 rootSize = Nodes;
1250 return NewOffset;
1251}
1252
1253// splitRoot - Split the current BranchRoot into multiple Branch nodes.
1254// Return the new (root offset, node offset) corresponding to Position.
1255template <typename KeyT, typename ValT, unsigned N, typename Traits>
1256IntervalMapImpl::IdxPair IntervalMap<KeyT, ValT, N, Traits>::
1257splitRoot(unsigned Position) {
1258 using namespace IntervalMapImpl;
1259 // How many external leaf nodes to hold RootBranch+1?
1260 const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1;
1261
1262 // Compute element distribution among new nodes.
1263 unsigned Size[Nodes];
1264 IdxPair NewOffset(0, Position);
1265
1266 // It is very common for the root node to be smaller than external nodes.
1267 if (Nodes == 1)
1268 Size[0] = rootSize;
1269 else
1270 NewOffset = distribute(Nodes, rootSize, Leaf::Capacity, nullptr, Size,
1271 Position, true);
1272
1273 // Allocate new nodes.
1274 unsigned Pos = 0;
1275 NodeRef Node[Nodes];
1276 for (unsigned n = 0; n != Nodes; ++n) {
1277 Branch *B = newNode<Branch>();
1278 B->copy(rootBranch(), Pos, 0, Size[n]);
1279 Node[n] = NodeRef(B, Size[n]);
1280 Pos += Size[n];
1281 }
1282
1283 for (unsigned n = 0; n != Nodes; ++n) {
1284 rootBranch().stop(n) = Node[n].template get<Branch>().stop(Size[n]-1);
1285 rootBranch().subtree(n) = Node[n];
1286 }
1287 rootSize = Nodes;
1288 ++height;
1289 return NewOffset;
1290}
1291
1292/// visitNodes - Visit each external node.
1293template <typename KeyT, typename ValT, unsigned N, typename Traits>
1294void IntervalMap<KeyT, ValT, N, Traits>::
1295visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) {
1296 if (!branched())
1297 return;
1298 SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs;
1299
1300 // Collect level 0 nodes from the root.
1301 for (unsigned i = 0; i != rootSize; ++i)
1302 Refs.push_back(rootBranch().subtree(i));
1303
1304 // Visit all branch nodes.
1305 for (unsigned h = height - 1; h; --h) {
1306 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
1307 for (unsigned j = 0, s = Refs[i].size(); j != s; ++j)
1308 NextRefs.push_back(Refs[i].subtree(j));
1309 (this->*f)(Refs[i], h);
1310 }
1311 Refs.clear();
1312 Refs.swap(NextRefs);
1313 }
1314
1315 // Visit all leaf nodes.
1316 for (unsigned i = 0, e = Refs.size(); i != e; ++i)
1317 (this->*f)(Refs[i], 0);
1318}
1319
1320template <typename KeyT, typename ValT, unsigned N, typename Traits>
1321void IntervalMap<KeyT, ValT, N, Traits>::
1322deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) {
1323 if (Level)
1324 deleteNode(&Node.get<Branch>());
1325 else
1326 deleteNode(&Node.get<Leaf>());
1327}
1328
1329template <typename KeyT, typename ValT, unsigned N, typename Traits>
1331clear() {
1332 if (branched()) {
1333 visitNodes(&IntervalMap::deleteNode);
1334 switchRootToLeaf();
1335 }
1336 rootSize = 0;
1337}
1338
1339//===----------------------------------------------------------------------===//
1340//--- IntervalMap::const_iterator ----//
1341//===----------------------------------------------------------------------===//
1342
1343template <typename KeyT, typename ValT, unsigned N, typename Traits>
1345 friend class IntervalMap;
1346
1347public:
1348 using iterator_category = std::bidirectional_iterator_tag;
1350 using difference_type = std::ptrdiff_t;
1353
1354protected:
1355 // The map referred to.
1356 IntervalMap *map = nullptr;
1357
1358 // We store a full path from the root to the current position.
1359 // The path may be partially filled, but never between iterator calls.
1361
1362 explicit const_iterator(const IntervalMap &map) :
1363 map(const_cast<IntervalMap*>(&map)) {}
1364
1365 bool branched() const {
1366 assert(map && "Invalid iterator");
1367 return map->branched();
1368 }
1369
1370 void setRoot(unsigned Offset) {
1371 if (branched())
1372 path.setRoot(&map->rootBranch(), map->rootSize, Offset);
1373 else
1374 path.setRoot(&map->rootLeaf(), map->rootSize, Offset);
1375 }
1376
1377 void pathFillFind(KeyT x);
1378 void treeFind(KeyT x);
1379 void treeAdvanceTo(KeyT x);
1380
1381 /// unsafeStart - Writable access to start() for iterator.
1383 assert(valid() && "Cannot access invalid iterator");
1384 return branched() ? path.leaf<Leaf>().start(path.leafOffset()) :
1385 path.leaf<RootLeaf>().start(path.leafOffset());
1386 }
1387
1388 /// unsafeStop - Writable access to stop() for iterator.
1389 KeyT &unsafeStop() const {
1390 assert(valid() && "Cannot access invalid iterator");
1391 return branched() ? path.leaf<Leaf>().stop(path.leafOffset()) :
1392 path.leaf<RootLeaf>().stop(path.leafOffset());
1393 }
1394
1395 /// unsafeValue - Writable access to value() for iterator.
1397 assert(valid() && "Cannot access invalid iterator");
1398 return branched() ? path.leaf<Leaf>().value(path.leafOffset()) :
1399 path.leaf<RootLeaf>().value(path.leafOffset());
1400 }
1401
1402public:
1403 /// const_iterator - Create an iterator that isn't pointing anywhere.
1404 const_iterator() = default;
1405
1406 /// setMap - Change the map iterated over. This call must be followed by a
1407 /// call to goToBegin(), goToEnd(), or find()
1408 void setMap(const IntervalMap &m) { map = const_cast<IntervalMap*>(&m); }
1409
1410 /// valid - Return true if the current position is valid, false for end().
1411 bool valid() const { return path.valid(); }
1412
1413 /// atBegin - Return true if the current position is the first map entry.
1414 bool atBegin() const { return path.atBegin(); }
1415
1416 /// start - Return the beginning of the current interval.
1417 const KeyT &start() const { return unsafeStart(); }
1418
1419 /// stop - Return the end of the current interval.
1420 const KeyT &stop() const { return unsafeStop(); }
1421
1422 /// value - Return the mapped value at the current interval.
1423 const ValT &value() const { return unsafeValue(); }
1424
1425 const ValT &operator*() const { return value(); }
1426
1427 bool operator==(const const_iterator &RHS) const {
1428 assert(map == RHS.map && "Cannot compare iterators from different maps");
1429 if (!valid())
1430 return !RHS.valid();
1431 if (path.leafOffset() != RHS.path.leafOffset())
1432 return false;
1433 return &path.template leaf<Leaf>() == &RHS.path.template leaf<Leaf>();
1434 }
1435
1436 bool operator!=(const const_iterator &RHS) const {
1437 return !operator==(RHS);
1438 }
1439
1440 /// goToBegin - Move to the first interval in map.
1441 void goToBegin() {
1442 setRoot(0);
1443 if (branched())
1444 path.fillLeft(map->height);
1445 }
1446
1447 /// goToEnd - Move beyond the last interval in map.
1448 void goToEnd() {
1449 setRoot(map->rootSize);
1450 }
1451
1452 /// preincrement - Move to the next interval.
1454 assert(valid() && "Cannot increment end()");
1455 if (++path.leafOffset() == path.leafSize() && branched())
1456 path.moveRight(map->height);
1457 return *this;
1458 }
1459
1460 /// postincrement - Don't do that!
1462 const_iterator tmp = *this;
1463 operator++();
1464 return tmp;
1465 }
1466
1467 /// predecrement - Move to the previous interval.
1469 if (path.leafOffset() && (valid() || !branched()))
1470 --path.leafOffset();
1471 else
1472 path.moveLeft(map->height);
1473 return *this;
1474 }
1475
1476 /// postdecrement - Don't do that!
1478 const_iterator tmp = *this;
1479 operator--();
1480 return tmp;
1481 }
1482
1483 /// find - Move to the first interval with stop >= x, or end().
1484 /// This is a full search from the root, the current position is ignored.
1485 void find(KeyT x) {
1486 if (branched())
1487 treeFind(x);
1488 else
1489 setRoot(map->rootLeaf().findFrom(0, map->rootSize, x));
1490 }
1491
1492 /// advanceTo - Move to the first interval with stop >= x, or end().
1493 /// The search is started from the current position, and no earlier positions
1494 /// can be found. This is much faster than find() for small moves.
1495 void advanceTo(KeyT x) {
1496 if (!valid())
1497 return;
1498 if (branched())
1499 treeAdvanceTo(x);
1500 else
1501 path.leafOffset() =
1502 map->rootLeaf().findFrom(path.leafOffset(), map->rootSize, x);
1503 }
1504};
1505
1506/// pathFillFind - Complete path by searching for x.
1507/// @param x Key to search for.
1508template <typename KeyT, typename ValT, unsigned N, typename Traits>
1511 IntervalMapImpl::NodeRef NR = path.subtree(path.height());
1512 for (unsigned i = map->height - path.height() - 1; i; --i) {
1513 unsigned p = NR.get<Branch>().safeFind(0, x);
1514 path.push(NR, p);
1515 NR = NR.subtree(p);
1516 }
1517 path.push(NR, NR.get<Leaf>().safeFind(0, x));
1518}
1519
1520/// treeFind - Find in a branched tree.
1521/// @param x Key to search for.
1522template <typename KeyT, typename ValT, unsigned N, typename Traits>
1525 setRoot(map->rootBranch().findFrom(0, map->rootSize, x));
1526 if (valid())
1527 pathFillFind(x);
1528}
1529
1530/// treeAdvanceTo - Find position after the current one.
1531/// @param x Key to search for.
1532template <typename KeyT, typename ValT, unsigned N, typename Traits>
1535 // Can we stay on the same leaf node?
1536 if (!Traits::stopLess(path.leaf<Leaf>().stop(path.leafSize() - 1), x)) {
1537 path.leafOffset() = path.leaf<Leaf>().safeFind(path.leafOffset(), x);
1538 return;
1539 }
1540
1541 // Drop the current leaf.
1542 path.pop();
1543
1544 // Search towards the root for a usable subtree.
1545 if (path.height()) {
1546 for (unsigned l = path.height() - 1; l; --l) {
1547 if (!Traits::stopLess(path.node<Branch>(l).stop(path.offset(l)), x)) {
1548 // The branch node at l+1 is usable
1549 path.offset(l + 1) =
1550 path.node<Branch>(l + 1).safeFind(path.offset(l + 1), x);
1551 return pathFillFind(x);
1552 }
1553 path.pop();
1554 }
1555 // Is the level-1 Branch usable?
1556 if (!Traits::stopLess(map->rootBranch().stop(path.offset(0)), x)) {
1557 path.offset(1) = path.node<Branch>(1).safeFind(path.offset(1), x);
1558 return pathFillFind(x);
1559 }
1560 }
1561
1562 // We reached the root.
1563 setRoot(map->rootBranch().findFrom(path.offset(0), map->rootSize, x));
1564 if (valid())
1565 pathFillFind(x);
1566}
1567
1568//===----------------------------------------------------------------------===//
1569//--- IntervalMap::iterator ----//
1570//===----------------------------------------------------------------------===//
1571
1572template <typename KeyT, typename ValT, unsigned N, typename Traits>
1573class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator {
1574 friend class IntervalMap;
1575
1576 using IdxPair = IntervalMapImpl::IdxPair;
1577
1578 explicit iterator(IntervalMap &map) : const_iterator(map) {}
1579
1580 void setNodeStop(unsigned Level, KeyT Stop);
1581 bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
1582 template <typename NodeT> bool overflow(unsigned Level);
1583 void treeInsert(KeyT a, KeyT b, ValT y);
1584 void eraseNode(unsigned Level);
1585 void treeErase(bool UpdateRoot = true);
1586 bool canCoalesceLeft(KeyT Start, ValT x);
1587 bool canCoalesceRight(KeyT Stop, ValT x);
1588
1589public:
1590 /// iterator - Create null iterator.
1591 iterator() = default;
1592
1593 /// setStart - Move the start of the current interval.
1594 /// This may cause coalescing with the previous interval.
1595 /// @param a New start key, must not overlap the previous interval.
1596 void setStart(KeyT a);
1597
1598 /// setStop - Move the end of the current interval.
1599 /// This may cause coalescing with the following interval.
1600 /// @param b New stop key, must not overlap the following interval.
1601 void setStop(KeyT b);
1602
1603 /// setValue - Change the mapped value of the current interval.
1604 /// This may cause coalescing with the previous and following intervals.
1605 /// @param x New value.
1606 void setValue(ValT x);
1607
1608 /// setStartUnchecked - Move the start of the current interval without
1609 /// checking for coalescing or overlaps.
1610 /// This should only be used when it is known that coalescing is not required.
1611 /// @param a New start key.
1612 void setStartUnchecked(KeyT a) { this->unsafeStart() = a; }
1613
1614 /// setStopUnchecked - Move the end of the current interval without checking
1615 /// for coalescing or overlaps.
1616 /// This should only be used when it is known that coalescing is not required.
1617 /// @param b New stop key.
1619 this->unsafeStop() = b;
1620 // Update keys in branch nodes as well.
1621 if (this->path.atLastEntry(this->path.height()))
1622 setNodeStop(this->path.height(), b);
1623 }
1624
1625 /// setValueUnchecked - Change the mapped value of the current interval
1626 /// without checking for coalescing.
1627 /// @param x New value.
1628 void setValueUnchecked(ValT x) { this->unsafeValue() = x; }
1629
1630 /// insert - Insert mapping [a;b] -> y before the current position.
1631 void insert(KeyT a, KeyT b, ValT y);
1632
1633 /// erase - Erase the current interval.
1634 void erase();
1635
1638 return *this;
1639 }
1640
1642 iterator tmp = *this;
1643 operator++();
1644 return tmp;
1645 }
1646
1649 return *this;
1650 }
1651
1653 iterator tmp = *this;
1654 operator--();
1655 return tmp;
1656 }
1657};
1658
1659/// canCoalesceLeft - Can the current interval coalesce to the left after
1660/// changing start or value?
1661/// @param Start New start of current interval.
1662/// @param Value New value for current interval.
1663/// @return True when updating the current interval would enable coalescing.
1664template <typename KeyT, typename ValT, unsigned N, typename Traits>
1667 using namespace IntervalMapImpl;
1668 Path &P = this->path;
1669 if (!this->branched()) {
1670 unsigned i = P.leafOffset();
1671 RootLeaf &Node = P.leaf<RootLeaf>();
1672 return i && Node.value(i-1) == Value &&
1673 Traits::adjacent(Node.stop(i-1), Start);
1674 }
1675 // Branched.
1676 if (unsigned i = P.leafOffset()) {
1677 Leaf &Node = P.leaf<Leaf>();
1678 return Node.value(i-1) == Value && Traits::adjacent(Node.stop(i-1), Start);
1679 } else if (NodeRef NR = P.getLeftSibling(P.height())) {
1680 unsigned i = NR.size() - 1;
1681 Leaf &Node = NR.get<Leaf>();
1682 return Node.value(i) == Value && Traits::adjacent(Node.stop(i), Start);
1683 }
1684 return false;
1685}
1686
1687/// canCoalesceRight - Can the current interval coalesce to the right after
1688/// changing stop or value?
1689/// @param Stop New stop of current interval.
1690/// @param Value New value for current interval.
1691/// @return True when updating the current interval would enable coalescing.
1692template <typename KeyT, typename ValT, unsigned N, typename Traits>
1693bool IntervalMap<KeyT, ValT, N, Traits>::
1694iterator::canCoalesceRight(KeyT Stop, ValT Value) {
1695 using namespace IntervalMapImpl;
1696 Path &P = this->path;
1697 unsigned i = P.leafOffset() + 1;
1698 if (!this->branched()) {
1699 if (i >= P.leafSize())
1700 return false;
1701 RootLeaf &Node = P.leaf<RootLeaf>();
1702 return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i));
1703 }
1704 // Branched.
1705 if (i < P.leafSize()) {
1706 Leaf &Node = P.leaf<Leaf>();
1707 return Node.value(i) == Value && Traits::adjacent(Stop, Node.start(i));
1708 } else if (NodeRef NR = P.getRightSibling(P.height())) {
1709 Leaf &Node = NR.get<Leaf>();
1710 return Node.value(0) == Value && Traits::adjacent(Stop, Node.start(0));
1711 }
1712 return false;
1713}
1714
1715/// setNodeStop - Update the stop key of the current node at level and above.
1716template <typename KeyT, typename ValT, unsigned N, typename Traits>
1717void IntervalMap<KeyT, ValT, N, Traits>::
1718iterator::setNodeStop(unsigned Level, KeyT Stop) {
1719 // There are no references to the root node, so nothing to update.
1720 if (!Level)
1721 return;
1722 IntervalMapImpl::Path &P = this->path;
1723 // Update nodes pointing to the current node.
1724 while (--Level) {
1725 P.node<Branch>(Level).stop(P.offset(Level)) = Stop;
1726 if (!P.atLastEntry(Level))
1727 return;
1728 }
1729 // Update root separately since it has a different layout.
1730 P.node<RootBranch>(Level).stop(P.offset(Level)) = Stop;
1731}
1732
1733template <typename KeyT, typename ValT, unsigned N, typename Traits>
1736 assert(Traits::nonEmpty(a, this->stop()) && "Cannot move start beyond stop");
1737 KeyT &CurStart = this->unsafeStart();
1738 if (!Traits::startLess(a, CurStart) || !canCoalesceLeft(a, this->value())) {
1739 CurStart = a;
1740 return;
1741 }
1742 // Coalesce with the interval to the left.
1743 --*this;
1744 a = this->start();
1745 erase();
1746 setStartUnchecked(a);
1747}
1748
1749template <typename KeyT, typename ValT, unsigned N, typename Traits>
1752 assert(Traits::nonEmpty(this->start(), b) && "Cannot move stop beyond start");
1753 if (Traits::startLess(b, this->stop()) ||
1754 !canCoalesceRight(b, this->value())) {
1755 setStopUnchecked(b);
1756 return;
1757 }
1758 // Coalesce with interval to the right.
1759 KeyT a = this->start();
1760 erase();
1761 setStartUnchecked(a);
1762}
1763
1764template <typename KeyT, typename ValT, unsigned N, typename Traits>
1767 setValueUnchecked(x);
1768 if (canCoalesceRight(this->stop(), x)) {
1769 KeyT a = this->start();
1770 erase();
1771 setStartUnchecked(a);
1772 }
1773 if (canCoalesceLeft(this->start(), x)) {
1774 --*this;
1775 KeyT a = this->start();
1776 erase();
1777 setStartUnchecked(a);
1778 }
1779}
1780
1781/// insertNode - insert a node before the current path at level.
1782/// Leave the current path pointing at the new node.
1783/// @param Level path index of the node to be inserted.
1784/// @param Node The node to be inserted.
1785/// @param Stop The last index in the new node.
1786/// @return True if the tree height was increased.
1787template <typename KeyT, typename ValT, unsigned N, typename Traits>
1790 assert(Level && "Cannot insert next to the root");
1791 bool SplitRoot = false;
1792 IntervalMap &IM = *this->map;
1793 IntervalMapImpl::Path &P = this->path;
1794
1795 if (Level == 1) {
1796 // Insert into the root branch node.
1797 if (IM.rootSize < RootBranch::Capacity) {
1798 IM.rootBranch().insert(P.offset(0), IM.rootSize, Node, Stop);
1799 P.setSize(0, ++IM.rootSize);
1800 P.reset(Level);
1801 return SplitRoot;
1802 }
1803
1804 // We need to split the root while keeping our position.
1805 SplitRoot = true;
1806 IdxPair Offset = IM.splitRoot(P.offset(0));
1807 P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset);
1808
1809 // Fall through to insert at the new higher level.
1810 ++Level;
1811 }
1812
1813 // When inserting before end(), make sure we have a valid path.
1814 P.legalizeForInsert(--Level);
1815
1816 // Insert into the branch node at Level-1.
1817 if (P.size(Level) == Branch::Capacity) {
1818 // Branch node is full, handle the overflow.
1819 assert(!SplitRoot && "Cannot overflow after splitting the root");
1820 SplitRoot = overflow<Branch>(Level);
1821 Level += SplitRoot;
1822 }
1823 P.node<Branch>(Level).insert(P.offset(Level), P.size(Level), Node, Stop);
1824 P.setSize(Level, P.size(Level) + 1);
1825 if (P.atLastEntry(Level))
1826 setNodeStop(Level, Stop);
1827 P.reset(Level + 1);
1828 return SplitRoot;
1829}
1830
1831// insert
1832template <typename KeyT, typename ValT, unsigned N, typename Traits>
1834iterator::insert(KeyT a, KeyT b, ValT y) {
1835 if (this->branched())
1836 return treeInsert(a, b, y);
1837 IntervalMap &IM = *this->map;
1838 IntervalMapImpl::Path &P = this->path;
1839
1840 // Try simple root leaf insert.
1841 unsigned Size = IM.rootLeaf().insertFrom(P.leafOffset(), IM.rootSize, a, b, y);
1842
1843 // Was the root node insert successful?
1844 if (Size <= RootLeaf::Capacity) {
1845 P.setSize(0, IM.rootSize = Size);
1846 return;
1847 }
1848
1849 // Root leaf node is full, we must branch.
1850 IdxPair Offset = IM.branchRoot(P.leafOffset());
1851 P.replaceRoot(&IM.rootBranch(), IM.rootSize, Offset);
1852
1853 // Now it fits in the new leaf.
1854 treeInsert(a, b, y);
1855}
1856
1857template <typename KeyT, typename ValT, unsigned N, typename Traits>
1860 using namespace IntervalMapImpl;
1861 Path &P = this->path;
1862
1863 if (!P.valid())
1864 P.legalizeForInsert(this->map->height);
1865
1866 // Check if this insertion will extend the node to the left.
1867 if (P.leafOffset() == 0 && Traits::startLess(a, P.leaf<Leaf>().start(0))) {
1868 // Node is growing to the left, will it affect a left sibling node?
1869 if (NodeRef Sib = P.getLeftSibling(P.height())) {
1870 Leaf &SibLeaf = Sib.get<Leaf>();
1871 unsigned SibOfs = Sib.size() - 1;
1872 if (SibLeaf.value(SibOfs) == y &&
1873 Traits::adjacent(SibLeaf.stop(SibOfs), a)) {
1874 // This insertion will coalesce with the last entry in SibLeaf. We can
1875 // handle it in two ways:
1876 // 1. Extend SibLeaf.stop to b and be done, or
1877 // 2. Extend a to SibLeaf, erase the SibLeaf entry and continue.
1878 // We prefer 1., but need 2 when coalescing to the right as well.
1879 Leaf &CurLeaf = P.leaf<Leaf>();
1880 P.moveLeft(P.height());
1881 if (Traits::stopLess(b, CurLeaf.start(0)) &&
1882 (y != CurLeaf.value(0) || !Traits::adjacent(b, CurLeaf.start(0)))) {
1883 // Easy, just extend SibLeaf and we're done.
1884 setNodeStop(P.height(), SibLeaf.stop(SibOfs) = b);
1885 return;
1886 } else {
1887 // We have both left and right coalescing. Erase the old SibLeaf entry
1888 // and continue inserting the larger interval.
1889 a = SibLeaf.start(SibOfs);
1890 treeErase(/* UpdateRoot= */false);
1891 }
1892 }
1893 } else {
1894 // No left sibling means we are at begin(). Update cached bound.
1895 this->map->rootBranchStart() = a;
1896 }
1897 }
1898
1899 // When we are inserting at the end of a leaf node, we must update stops.
1900 unsigned Size = P.leafSize();
1901 bool Grow = P.leafOffset() == Size;
1902 Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), Size, a, b, y);
1903
1904 // Leaf insertion unsuccessful? Overflow and try again.
1905 if (Size > Leaf::Capacity) {
1906 overflow<Leaf>(P.height());
1907 Grow = P.leafOffset() == P.leafSize();
1908 Size = P.leaf<Leaf>().insertFrom(P.leafOffset(), P.leafSize(), a, b, y);
1909 assert(Size <= Leaf::Capacity && "overflow() didn't make room");
1910 }
1911
1912 // Inserted, update offset and leaf size.
1913 P.setSize(P.height(), Size);
1914
1915 // Insert was the last node entry, update stops.
1916 if (Grow)
1917 setNodeStop(P.height(), b);
1918}
1919
1920/// erase - erase the current interval and move to the next position.
1921template <typename KeyT, typename ValT, unsigned N, typename Traits>
1924 IntervalMap &IM = *this->map;
1925 IntervalMapImpl::Path &P = this->path;
1926 assert(P.valid() && "Cannot erase end()");
1927 if (this->branched())
1928 return treeErase();
1929 IM.rootLeaf().erase(P.leafOffset(), IM.rootSize);
1930 P.setSize(0, --IM.rootSize);
1931}
1932
1933/// treeErase - erase() for a branched tree.
1934template <typename KeyT, typename ValT, unsigned N, typename Traits>
1936iterator::treeErase(bool UpdateRoot) {
1937 IntervalMap &IM = *this->map;
1938 IntervalMapImpl::Path &P = this->path;
1939 Leaf &Node = P.leaf<Leaf>();
1940
1941 // Nodes are not allowed to become empty.
1942 if (P.leafSize() == 1) {
1943 IM.deleteNode(&Node);
1944 eraseNode(IM.height);
1945 // Update rootBranchStart if we erased begin().
1946 if (UpdateRoot && IM.branched() && P.valid() && P.atBegin())
1947 IM.rootBranchStart() = P.leaf<Leaf>().start(0);
1948 return;
1949 }
1950
1951 // Erase current entry.
1952 Node.erase(P.leafOffset(), P.leafSize());
1953 unsigned NewSize = P.leafSize() - 1;
1954 P.setSize(IM.height, NewSize);
1955 // When we erase the last entry, update stop and move to a legal position.
1956 if (P.leafOffset() == NewSize) {
1957 setNodeStop(IM.height, Node.stop(NewSize - 1));
1958 P.moveRight(IM.height);
1959 } else if (UpdateRoot && P.atBegin())
1960 IM.rootBranchStart() = P.leaf<Leaf>().start(0);
1961}
1962
1963/// eraseNode - Erase the current node at Level from its parent and move path to
1964/// the first entry of the next sibling node.
1965/// The node must be deallocated by the caller.
1966/// @param Level 1..height, the root node cannot be erased.
1967template <typename KeyT, typename ValT, unsigned N, typename Traits>
1968void IntervalMap<KeyT, ValT, N, Traits>::
1969iterator::eraseNode(unsigned Level) {
1970 assert(Level && "Cannot erase root node");
1971 IntervalMap &IM = *this->map;
1972 IntervalMapImpl::Path &P = this->path;
1973
1974 if (--Level == 0) {
1975 IM.rootBranch().erase(P.offset(0), IM.rootSize);
1976 P.setSize(0, --IM.rootSize);
1977 // If this cleared the root, switch to height=0.
1978 if (IM.empty()) {
1979 IM.switchRootToLeaf();
1980 this->setRoot(0);
1981 return;
1982 }
1983 } else {
1984 // Remove node ref from branch node at Level.
1985 Branch &Parent = P.node<Branch>(Level);
1986 if (P.size(Level) == 1) {
1987 // Branch node became empty, remove it recursively.
1988 IM.deleteNode(&Parent);
1989 eraseNode(Level);
1990 } else {
1991 // Branch node won't become empty.
1992 Parent.erase(P.offset(Level), P.size(Level));
1993 unsigned NewSize = P.size(Level) - 1;
1994 P.setSize(Level, NewSize);
1995 // If we removed the last branch, update stop and move to a legal pos.
1996 if (P.offset(Level) == NewSize) {
1997 setNodeStop(Level, Parent.stop(NewSize - 1));
1998 P.moveRight(Level);
1999 }
2000 }
2001 }
2002 // Update path cache for the new right sibling position.
2003 if (P.valid()) {
2004 P.reset(Level + 1);
2005 P.offset(Level + 1) = 0;
2006 }
2007}
2008
2009/// overflow - Distribute entries of the current node evenly among
2010/// its siblings and ensure that the current node is not full.
2011/// This may require allocating a new node.
2012/// @tparam NodeT The type of node at Level (Leaf or Branch).
2013/// @param Level path index of the overflowing node.
2014/// @return True when the tree height was changed.
2015template <typename KeyT, typename ValT, unsigned N, typename Traits>
2016template <typename NodeT>
2017bool IntervalMap<KeyT, ValT, N, Traits>::
2018iterator::overflow(unsigned Level) {
2019 using namespace IntervalMapImpl;
2020 Path &P = this->path;
2021 unsigned CurSize[4];
2022 NodeT *Node[4];
2023 unsigned Nodes = 0;
2024 unsigned Elements = 0;
2025 unsigned Offset = P.offset(Level);
2026
2027 // Do we have a left sibling?
2028 NodeRef LeftSib = P.getLeftSibling(Level);
2029 if (LeftSib) {
2030 Offset += Elements = CurSize[Nodes] = LeftSib.size();
2031 Node[Nodes++] = &LeftSib.get<NodeT>();
2032 }
2033
2034 // Current node.
2035 Elements += CurSize[Nodes] = P.size(Level);
2036 Node[Nodes++] = &P.node<NodeT>(Level);
2037
2038 // Do we have a right sibling?
2039 NodeRef RightSib = P.getRightSibling(Level);
2040 if (RightSib) {
2041 Elements += CurSize[Nodes] = RightSib.size();
2042 Node[Nodes++] = &RightSib.get<NodeT>();
2043 }
2044
2045 // Do we need to allocate a new node?
2046 unsigned NewNode = 0;
2047 if (Elements + 1 > Nodes * NodeT::Capacity) {
2048 // Insert NewNode at the penultimate position, or after a single node.
2049 NewNode = Nodes == 1 ? 1 : Nodes - 1;
2050 CurSize[Nodes] = CurSize[NewNode];
2051 Node[Nodes] = Node[NewNode];
2052 CurSize[NewNode] = 0;
2053 Node[NewNode] = this->map->template newNode<NodeT>();
2054 ++Nodes;
2055 }
2056
2057 // Compute the new element distribution.
2058 unsigned NewSize[4];
2059 IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity,
2060 CurSize, NewSize, Offset, true);
2061 adjustSiblingSizes(Node, Nodes, CurSize, NewSize);
2062
2063 // Move current location to the leftmost node.
2064 if (LeftSib)
2065 P.moveLeft(Level);
2066
2067 // Elements have been rearranged, now update node sizes and stops.
2068 bool SplitRoot = false;
2069 unsigned Pos = 0;
2070 while (true) {
2071 KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1);
2072 if (NewNode && Pos == NewNode) {
2073 SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop);
2074 Level += SplitRoot;
2075 } else {
2076 P.setSize(Level, NewSize[Pos]);
2077 setNodeStop(Level, Stop);
2078 }
2079 if (Pos + 1 == Nodes)
2080 break;
2081 P.moveRight(Level);
2082 ++Pos;
2083 }
2084
2085 // Where was I? Find NewOffset.
2086 while(Pos != NewOffset.first) {
2087 P.moveLeft(Level);
2088 --Pos;
2089 }
2090 P.offset(Level) = NewOffset.second;
2091 return SplitRoot;
2092}
2093
2094//===----------------------------------------------------------------------===//
2095//--- IntervalMapOverlaps ----//
2096//===----------------------------------------------------------------------===//
2097
2098/// IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two
2099/// IntervalMaps. The maps may be different, but the KeyT and Traits types
2100/// should be the same.
2101///
2102/// Typical uses:
2103///
2104/// 1. Test for overlap:
2105/// bool overlap = IntervalMapOverlaps(a, b).valid();
2106///
2107/// 2. Enumerate overlaps:
2108/// for (IntervalMapOverlaps I(a, b); I.valid() ; ++I) { ... }
2109///
2110template <typename MapA, typename MapB>
2112 using KeyType = typename MapA::KeyType;
2113 using Traits = typename MapA::KeyTraits;
2114
2115 typename MapA::const_iterator posA;
2116 typename MapB::const_iterator posB;
2117
2118 /// advance - Move posA and posB forward until reaching an overlap, or until
2119 /// either meets end.
2120 /// Don't move the iterators if they are already overlapping.
2121 void advance() {
2122 if (!valid())
2123 return;
2124
2125 if (Traits::stopLess(posA.stop(), posB.start())) {
2126 // A ends before B begins. Catch up.
2127 posA.advanceTo(posB.start());
2128 if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start()))
2129 return;
2130 } else if (Traits::stopLess(posB.stop(), posA.start())) {
2131 // B ends before A begins. Catch up.
2132 posB.advanceTo(posA.start());
2133 if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start()))
2134 return;
2135 } else {
2136 // Already overlapping.
2137 return;
2138 }
2139
2140 while (true) {
2141 // Make a.end > b.start.
2142 posA.advanceTo(posB.start());
2143 if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start()))
2144 return;
2145 // Make b.end > a.start.
2146 posB.advanceTo(posA.start());
2147 if (!posB.valid() || !Traits::stopLess(posA.stop(), posB.start()))
2148 return;
2149 }
2150 }
2151
2152public:
2153 /// IntervalMapOverlaps - Create an iterator for the overlaps of a and b.
2154 IntervalMapOverlaps(const MapA &a, const MapB &b)
2155 : posA(b.empty() ? a.end() : a.find(b.start())),
2156 posB(posA.valid() ? b.find(posA.start()) : b.end()) { advance(); }
2157
2158 /// valid - Return true if iterator is at an overlap.
2159 bool valid() const {
2160 return posA.valid() && posB.valid();
2161 }
2162
2163 /// a - access the left hand side in the overlap.
2164 const typename MapA::const_iterator &a() const { return posA; }
2165
2166 /// b - access the right hand side in the overlap.
2167 const typename MapB::const_iterator &b() const { return posB; }
2168
2169 /// start - Beginning of the overlapping interval.
2170 KeyType start() const {
2171 KeyType ak = a().start();
2172 KeyType bk = b().start();
2173 return Traits::startLess(ak, bk) ? bk : ak;
2174 }
2175
2176 /// stop - End of the overlapping interval.
2177 KeyType stop() const {
2178 KeyType ak = a().stop();
2179 KeyType bk = b().stop();
2180 return Traits::startLess(ak, bk) ? ak : bk;
2181 }
2182
2183 /// skipA - Move to the next overlap that doesn't involve a().
2184 void skipA() {
2185 ++posA;
2186 advance();
2187 }
2188
2189 /// skipB - Move to the next overlap that doesn't involve b().
2190 void skipB() {
2191 ++posB;
2192 advance();
2193 }
2194
2195 /// Preincrement - Move to the next overlap.
2197 // Bump the iterator that ends first. The other one may have more overlaps.
2198 if (Traits::startLess(posB.stop(), posA.stop()))
2199 skipB();
2200 else
2201 skipA();
2202 return *this;
2203 }
2204
2205 /// advanceTo - Move to the first overlapping interval with
2206 /// stopLess(x, stop()).
2207 void advanceTo(KeyType x) {
2208 if (!valid())
2209 return;
2210 // Make sure advanceTo sees monotonic keys.
2211 if (Traits::stopLess(posA.stop(), x))
2212 posA.advanceTo(x);
2213 if (Traits::stopLess(posB.stop(), x))
2214 posB.advanceTo(x);
2215 advance();
2216 }
2217};
2218
2219} // end namespace llvm
2220
2221#endif // LLVM_ADT_INTERVALMAP_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition: Compiler.h:213
Given that RA is a live value
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
#define I(x, y, z)
Definition: MD5.cpp:58
#define T1
#define P(N)
This file defines the PointerIntPair class.
This file defines the SmallVector class.
Value * RHS
const NodeRef & subtree(unsigned i) const
Definition: IntervalMap.h:707
NodeRef & subtree(unsigned i)
Definition: IntervalMap.h:710
unsigned safeFind(unsigned i, KeyT x) const
safeFind - Find a subtree that is known to exist.
Definition: IntervalMap.h:732
const KeyT & stop(unsigned i) const
Definition: IntervalMap.h:706
unsigned findFrom(unsigned i, unsigned Size, KeyT x) const
findFrom - Find the first subtree after i that may contain x.
Definition: IntervalMap.h:718
NodeRef safeLookup(KeyT x) const
safeLookup - Get the subtree containing x, Assuming that x is in range.
Definition: IntervalMap.h:744
void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop)
insert - Insert a new (subtree, stop) pair.
Definition: IntervalMap.h:753
unsigned safeFind(unsigned i, KeyT x) const
safeFind - Find an interval that is known to exist.
Definition: IntervalMap.h:598
const KeyT & stop(unsigned i) const
Definition: IntervalMap.h:570
const ValT & value(unsigned i) const
Definition: IntervalMap.h:571
ValT safeLookup(KeyT x, ValT NotFound) const
safeLookup - Lookup mapped value for a safe key.
Definition: IntervalMap.h:612
unsigned insertFrom(unsigned &Pos, unsigned Size, KeyT a, KeyT b, ValT y)
insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as possible.
Definition: IntervalMap.h:631
const KeyT & start(unsigned i) const
Definition: IntervalMap.h:569
unsigned findFrom(unsigned i, unsigned Size, KeyT x) const
findFrom - Find the first interval after i that may contain x.
Definition: IntervalMap.h:583
void erase(unsigned i, unsigned j, unsigned Size)
erase - Erase elements [i;j).
Definition: IntervalMap.h:273
void moveLeft(unsigned i, unsigned j, unsigned Count)
moveLeft - Move elements to the left.
Definition: IntervalMap.h:251
void transferToLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, unsigned Count)
transferToLeftSib - Transfer elements to a left sibling node.
Definition: IntervalMap.h:296
void copy(const NodeBase< T1, T2, M > &Other, unsigned i, unsigned j, unsigned Count)
copy - Copy elements from another node.
Definition: IntervalMap.h:237
static constexpr unsigned Capacity
Definition: IntervalMap.h:226
int adjustFromLeftSib(unsigned Size, NodeBase &Sib, unsigned SSize, int Add)
adjustFromLeftSib - Adjust the number if elements in this node by moving elements to or from a left s...
Definition: IntervalMap.h:320
void shift(unsigned i, unsigned Size)
shift - Shift elements [i;size) 1 position to the right.
Definition: IntervalMap.h:287
void transferToRightSib(unsigned Size, NodeBase &Sib, unsigned SSize, unsigned Count)
transferToRightSib - Transfer elements to a right sibling node.
Definition: IntervalMap.h:307
void erase(unsigned i, unsigned Size)
erase - Erase element at i.
Definition: IntervalMap.h:280
void moveRight(unsigned i, unsigned j, unsigned Count)
moveRight - Move elements to the right.
Definition: IntervalMap.h:260
unsigned size() const
size - Return the number of elements in the referenced node.
Definition: IntervalMap.h:516
bool operator!=(const NodeRef &RHS) const
Definition: IntervalMap.h:541
void setSize(unsigned n)
setSize - Update the node size.
Definition: IntervalMap.h:519
bool operator==(const NodeRef &RHS) const
Definition: IntervalMap.h:534
NodeT & get() const
get - Dereference as a NodeT reference.
Definition: IntervalMap.h:530
NodeRef(NodeT *p, unsigned n)
NodeRef - Create a reference to the node p with n elements.
Definition: IntervalMap.h:511
NodeRef & subtree(unsigned i) const
subtree - Access the i'th subtree reference in a branch node.
Definition: IntervalMap.h:524
NodeRef()=default
NodeRef - Create a null ref.
LLVM_ABI void replaceRoot(void *Root, unsigned Size, IdxPair Offsets)
replaceRoot - Replace the current root node with two new entries after the tree height has increased.
Definition: IntervalMap.cpp:19
unsigned & offset(unsigned Level)
Definition: IntervalMap.h:803
bool valid() const
valid - Return true if path is at a valid node, not at end().
Definition: IntervalMap.h:814
void reset(unsigned Level)
reset - Reset cached information about node(Level) from subtree(Level -1).
Definition: IntervalMap.h:831
LLVM_ABI NodeRef getLeftSibling(unsigned Level) const
getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
Definition: IntervalMap.cpp:25
void setRoot(void *Node, unsigned Size, unsigned Offset)
setRoot - Clear the path and set a new root node.
Definition: IntervalMap.h:861
unsigned offset(unsigned Level) const
Definition: IntervalMap.h:802
unsigned leafOffset() const
Definition: IntervalMap.h:810
NodeT & node(unsigned Level) const
Definition: IntervalMap.h:798
bool atLastEntry(unsigned Level) const
atLastEntry - Return true if the path is at the last entry of the node at Level.
Definition: IntervalMap.h:911
unsigned leafSize() const
Definition: IntervalMap.h:809
bool atBegin() const
atBegin - Return true if path is at begin().
Definition: IntervalMap.h:901
unsigned height() const
height - Return the height of the tree corresponding to this path.
Definition: IntervalMap.h:820
LLVM_ABI void moveRight(unsigned Level)
moveRight - Move path to the left sibling at Level.
Definition: IntervalMap.cpp:98
void pop()
pop - Remove the last path entry.
Definition: IntervalMap.h:843
void setSize(unsigned Level, unsigned Size)
setSize - Set the size of a node both in the path and in the tree.
Definition: IntervalMap.h:851
LLVM_ABI NodeRef getRightSibling(unsigned Level) const
getLeftSibling - Get the left sibling node at Level, or a null NodeRef.
Definition: IntervalMap.cpp:75
void fillLeft(unsigned Height)
fillLeft - Grow path to Height by taking leftmost branches.
Definition: IntervalMap.h:885
void legalizeForInsert(unsigned Level)
legalizeForInsert - Prepare the path for an insertion at Level.
Definition: IntervalMap.h:920
unsigned size(unsigned Level) const
Definition: IntervalMap.h:801
LLVM_ABI void moveLeft(unsigned Level)
moveLeft - Move path to the left sibling at Level.
Definition: IntervalMap.cpp:48
void push(NodeRef Node, unsigned Offset)
push - Add entry to path.
Definition: IntervalMap.h:838
NodeRef & subtree(unsigned Level) const
subtree - Get the subtree referenced from Level.
Definition: IntervalMap.h:825
IntervalMapOverlaps - Iterate over the overlaps of mapped intervals in two IntervalMaps.
Definition: IntervalMap.h:2111
IntervalMapOverlaps & operator++()
Preincrement - Move to the next overlap.
Definition: IntervalMap.h:2196
void skipB()
skipB - Move to the next overlap that doesn't involve b().
Definition: IntervalMap.h:2190
void skipA()
skipA - Move to the next overlap that doesn't involve a().
Definition: IntervalMap.h:2184
IntervalMapOverlaps(const MapA &a, const MapB &b)
IntervalMapOverlaps - Create an iterator for the overlaps of a and b.
Definition: IntervalMap.h:2154
KeyType start() const
start - Beginning of the overlapping interval.
Definition: IntervalMap.h:2170
const MapA::const_iterator & a() const
a - access the left hand side in the overlap.
Definition: IntervalMap.h:2164
void advanceTo(KeyType x)
advanceTo - Move to the first overlapping interval with stopLess(x, stop()).
Definition: IntervalMap.h:2207
bool valid() const
valid - Return true if iterator is at an overlap.
Definition: IntervalMap.h:2159
const MapB::const_iterator & b() const
b - access the right hand side in the overlap.
Definition: IntervalMap.h:2167
KeyType stop() const
stop - End of the overlapping interval.
Definition: IntervalMap.h:2177
void setMap(const IntervalMap &m)
setMap - Change the map iterated over.
Definition: IntervalMap.h:1408
const_iterator(const IntervalMap &map)
Definition: IntervalMap.h:1362
const_iterator()=default
const_iterator - Create an iterator that isn't pointing anywhere.
void advanceTo(KeyT x)
advanceTo - Move to the first interval with stop >= x, or end().
Definition: IntervalMap.h:1495
void pathFillFind(KeyT x)
pathFillFind - Complete path by searching for x.
Definition: IntervalMap.h:1510
bool operator==(const const_iterator &RHS) const
Definition: IntervalMap.h:1427
bool operator!=(const const_iterator &RHS) const
Definition: IntervalMap.h:1436
void goToEnd()
goToEnd - Move beyond the last interval in map.
Definition: IntervalMap.h:1448
const KeyT & stop() const
stop - Return the end of the current interval.
Definition: IntervalMap.h:1420
KeyT & unsafeStop() const
unsafeStop - Writable access to stop() for iterator.
Definition: IntervalMap.h:1389
const_iterator & operator++()
preincrement - Move to the next interval.
Definition: IntervalMap.h:1453
bool valid() const
valid - Return true if the current position is valid, false for end().
Definition: IntervalMap.h:1411
const KeyT & start() const
start - Return the beginning of the current interval.
Definition: IntervalMap.h:1417
void treeAdvanceTo(KeyT x)
treeAdvanceTo - Find position after the current one.
Definition: IntervalMap.h:1534
ValT & unsafeValue() const
unsafeValue - Writable access to value() for iterator.
Definition: IntervalMap.h:1396
const ValT & operator*() const
Definition: IntervalMap.h:1425
std::bidirectional_iterator_tag iterator_category
Definition: IntervalMap.h:1348
const ValT & value() const
value - Return the mapped value at the current interval.
Definition: IntervalMap.h:1423
const_iterator operator--(int)
postdecrement - Don't do that!
Definition: IntervalMap.h:1477
IntervalMapImpl::Path path
Definition: IntervalMap.h:1360
void setRoot(unsigned Offset)
Definition: IntervalMap.h:1370
void treeFind(KeyT x)
treeFind - Find in a branched tree.
Definition: IntervalMap.h:1524
bool atBegin() const
atBegin - Return true if the current position is the first map entry.
Definition: IntervalMap.h:1414
void find(KeyT x)
find - Move to the first interval with stop >= x, or end().
Definition: IntervalMap.h:1485
const_iterator & operator--()
predecrement - Move to the previous interval.
Definition: IntervalMap.h:1468
KeyT & unsafeStart() const
unsafeStart - Writable access to start() for iterator.
Definition: IntervalMap.h:1382
void goToBegin()
goToBegin - Move to the first interval in map.
Definition: IntervalMap.h:1441
const_iterator operator++(int)
postincrement - Don't do that!
Definition: IntervalMap.h:1461
void insert(KeyT a, KeyT b, ValT y)
insert - Insert mapping [a;b] -> y before the current position.
Definition: IntervalMap.h:1834
void setValueUnchecked(ValT x)
setValueUnchecked - Change the mapped value of the current interval without checking for coalescing.
Definition: IntervalMap.h:1628
iterator()=default
iterator - Create null iterator.
void setStart(KeyT a)
setStart - Move the start of the current interval.
Definition: IntervalMap.h:1735
void erase()
erase - Erase the current interval.
Definition: IntervalMap.h:1923
void setValue(ValT x)
setValue - Change the mapped value of the current interval.
Definition: IntervalMap.h:1766
void setStartUnchecked(KeyT a)
setStartUnchecked - Move the start of the current interval without checking for coalescing or overlap...
Definition: IntervalMap.h:1612
void setStop(KeyT b)
setStop - Move the end of the current interval.
Definition: IntervalMap.h:1751
void setStopUnchecked(KeyT b)
setStopUnchecked - Move the end of the current interval without checking for coalescing or overlaps.
Definition: IntervalMap.h:1618
iterator begin()
Definition: IntervalMap.h:1153
const_iterator begin() const
Definition: IntervalMap.h:1147
void insert(KeyT a, KeyT b, ValT y)
insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals.
Definition: IntervalMap.h:1130
ValT lookup(KeyT x, ValT NotFound=ValT()) const
lookup - Return the mapped value at x or NotFound.
Definition: IntervalMap.h:1120
KeyT stop() const
stop - Return the largest mapped key in a non-empty map.
Definition: IntervalMap.h:1113
IntervalMap & operator=(IntervalMap const &RHS)
Definition: IntervalMap.h:1056
typename Sizer::Allocator Allocator
Definition: IntervalMap.h:963
IntervalMap & operator=(IntervalMap &&RHS)
Definition: IntervalMap.h:1070
IntervalMap(IntervalMap &&RHS)
Definition: IntervalMap.h:1064
const_iterator find(KeyT x) const
find - Return an iterator pointing to the first interval ending at or after x, or end().
Definition: IntervalMap.h:1173
RootBranchData branchData
Definition: IntervalMap.h:972
IntervalMap(IntervalMap const &RHS)
Definition: IntervalMap.h:1050
bool overlaps(KeyT a, KeyT b) const
overlaps(a, b) - Return true if the intervals in this map overlap with the interval [a;b].
Definition: IntervalMap.h:1187
bool empty() const
empty - Return true when no intervals are mapped.
Definition: IntervalMap.h:1102
const_iterator end() const
Definition: IntervalMap.h:1159
KeyT start() const
start - Return the smallest mapped key in a non-empty map.
Definition: IntervalMap.h:1107
void clear()
clear - Remove all entries.
Definition: IntervalMap.h:1331
IntervalMap(Allocator &a)
Definition: IntervalMap.h:1042
iterator find(KeyT x)
Definition: IntervalMap.h:1179
PointerIntPair - This class implements a pair of a pointer and small integer.
IntType getInt() const
void setInt(IntType IntVal) &
void * getOpaqueValue() const
PointerTy getPointer() const
RecyclingAllocator - This class wraps an Allocator, adding the functionality of recycling deleted obj...
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
LLVM Value Representation.
Definition: Value.h:75
std::pair< unsigned, unsigned > IdxPair
Definition: IntervalMap.h:194
void adjustSiblingSizes(NodeT *Node[], unsigned Nodes, unsigned CurSize[], const unsigned NewSize[])
IntervalMapImpl::adjustSiblingSizes - Move elements between sibling nodes.
Definition: IntervalMap.h:341
LLVM_ABI IdxPair distribute(unsigned Nodes, unsigned Elements, unsigned Capacity, const unsigned *CurSize, unsigned NewSize[], unsigned Position, bool Grow)
IntervalMapImpl::distribute - Compute a new distribution of node elements after an overflow or underf...
constexpr double e
Definition: MathExtras.h:47
std::pair< NodeId, LaneBitmask > NodeRef
Definition: RDFLiveness.h:36
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1770
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1702
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition: STLExtras.h:2147
@ Other
Any other memory.
@ Add
Sum of integers.
#define N
static bool startLess(const T &x, const T &a)
startLess - Return true if x is not in [a;b).
Definition: IntervalMap.h:170
static bool adjacent(const T &a, const T &b)
adjacent - Return true when the intervals [x;a) and [b;y) can coalesce.
Definition: IntervalMap.h:180
static bool stopLess(const T &b, const T &x)
stopLess - Return true if x is not in [a;b).
Definition: IntervalMap.h:175
static bool nonEmpty(const T &a, const T &b)
nonEmpty - Return true if [a;b) is non-empty.
Definition: IntervalMap.h:185
NodeBase< std::pair< KeyT, KeyT >, ValT, LeafSize > LeafBase
Definition: IntervalMap.h:453
RecyclingAllocator< BumpPtrAllocator, char, AllocBytes, CacheLineBytes > Allocator
Allocator - The recycling allocator used for both branch and leaf nodes.
Definition: IntervalMap.h:470
static bool startLess(const T &x, const T &a)
startLess - Return true if x is not in [a;b].
Definition: IntervalMap.h:144
static bool adjacent(const T &a, const T &b)
adjacent - Return true when the intervals [x;a] and [b;y] can coalesce.
Definition: IntervalMap.h:156
static bool nonEmpty(const T &a, const T &b)
nonEmpty - Return true if [a;b] is non-empty.
Definition: IntervalMap.h:162
static bool stopLess(const T &b, const T &x)
stopLess - Return true if x is not in [a;b].
Definition: IntervalMap.h:150